blob: 88968e711d3dac7dbcb2d4ef86b430e2d6c047f7 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Gustavo F. Padovan590051d2011-12-18 13:39:33 -02006 Copyright (C) 2011 ProFUSION Embedded Systems
Linus Torvalds1da177e2005-04-16 15:20:36 -07007
8 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License version 2 as
12 published by the Free Software Foundation;
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
17 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090018 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090023 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
24 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070025 SOFTWARE IS DISCLAIMED.
26*/
27
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020028/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070029
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/module.h>
31
32#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080033#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/errno.h>
35#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/sched.h>
37#include <linux/slab.h>
38#include <linux/poll.h>
39#include <linux/fcntl.h>
40#include <linux/init.h>
41#include <linux/interrupt.h>
42#include <linux/socket.h>
43#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080045#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010046#include <linux/debugfs.h>
47#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030048#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030049#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#include <net/sock.h>
51
52#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070053#include <asm/unaligned.h>
54
55#include <net/bluetooth/bluetooth.h>
56#include <net/bluetooth/hci_core.h>
57#include <net/bluetooth/l2cap.h>
Anderson Brigliab501d6a2011-06-07 18:46:31 -030058#include <net/bluetooth/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
Rusty Russelleb939922011-12-19 14:08:01 +000060bool disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020061
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070062static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Mat Martineau50a147c2011-11-02 16:18:34 -070063static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Johannes Bergb5ad8b72011-06-01 08:54:45 +020065static LIST_HEAD(chan_list);
66static DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Linus Torvalds1da177e2005-04-16 15:20:36 -070068static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
69 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030070static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
71 void *data);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -030072static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030073static void l2cap_send_disconn_req(struct l2cap_conn *conn,
74 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
Marcel Holtmann01394182006-07-03 10:02:46 +020076/* ---- L2CAP channels ---- */
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -030077
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030078static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020079{
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -020080 struct l2cap_chan *c, *r = NULL;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030081
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -020082 rcu_read_lock();
83
84 list_for_each_entry_rcu(c, &conn->chan_l, list) {
85 if (c->dcid == cid) {
86 r = c;
87 break;
88 }
Marcel Holtmann01394182006-07-03 10:02:46 +020089 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -020090
91 rcu_read_unlock();
92 return r;
Marcel Holtmann01394182006-07-03 10:02:46 +020093}
94
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030095static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020096{
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -020097 struct l2cap_chan *c, *r = NULL;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030098
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -020099 rcu_read_lock();
100
101 list_for_each_entry_rcu(c, &conn->chan_l, list) {
102 if (c->scid == cid) {
103 r = c;
104 break;
105 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200106 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200107
108 rcu_read_unlock();
109 return r;
Marcel Holtmann01394182006-07-03 10:02:46 +0200110}
111
112/* Find channel with given SCID.
113 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300114static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200115{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300116 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300117
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300118 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300119 if (c)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300120 lock_sock(c->sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300121 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200122}
123
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300124static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200125{
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200126 struct l2cap_chan *c, *r = NULL;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300127
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200128 rcu_read_lock();
129
130 list_for_each_entry_rcu(c, &conn->chan_l, list) {
131 if (c->ident == ident) {
132 r = c;
133 break;
134 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200135 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200136
137 rcu_read_unlock();
138 return r;
Marcel Holtmann01394182006-07-03 10:02:46 +0200139}
140
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300141static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200142{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300143 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300144
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300145 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300146 if (c)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300147 lock_sock(c->sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300148 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200149}
150
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300151static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300152{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300153 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300154
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300155 list_for_each_entry(c, &chan_list, global_l) {
156 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Szymon Janc250938c2011-11-16 09:32:22 +0100157 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300158 }
Szymon Janc250938c2011-11-16 09:32:22 +0100159 return NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300160}
161
162int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
163{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300164 int err;
165
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200166 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300167
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300168 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300169 err = -EADDRINUSE;
170 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300171 }
172
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300173 if (psm) {
174 chan->psm = psm;
175 chan->sport = psm;
176 err = 0;
177 } else {
178 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300179
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300180 err = -EINVAL;
181 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300182 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300183 chan->psm = cpu_to_le16(p);
184 chan->sport = cpu_to_le16(p);
185 err = 0;
186 break;
187 }
188 }
189
190done:
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200191 write_unlock(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300192 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300193}
194
195int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
196{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200197 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300198
199 chan->scid = scid;
200
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200201 write_unlock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300202
203 return 0;
204}
205
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300206static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200207{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300208 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200209
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300210 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300211 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200212 return cid;
213 }
214
215 return 0;
216}
217
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300218static void l2cap_state_change(struct l2cap_chan *chan, int state)
219{
Gustavo F. Padovanbadaaa02011-11-23 20:11:46 -0200220 BT_DBG("%p %s -> %s", chan, state_to_string(chan->state),
221 state_to_string(state));
222
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300223 chan->state = state;
224 chan->ops->state_change(chan->data, state);
225}
226
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300227static void l2cap_chan_timeout(struct work_struct *work)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300228{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300229 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
230 chan_timer.work);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300231 struct sock *sk = chan->sk;
232 int reason;
233
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200234 BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300235
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300236 lock_sock(sk);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300237
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300238 if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300239 reason = ECONNREFUSED;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300240 else if (chan->state == BT_CONNECT &&
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300241 chan->sec_level != BT_SECURITY_SDP)
242 reason = ECONNREFUSED;
243 else
244 reason = ETIMEDOUT;
245
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300246 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300247
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300248 release_sock(sk);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300249
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300250 chan->ops->close(chan->data);
Ulisses Furquim371fd832011-12-21 20:02:36 -0200251 l2cap_chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300252}
253
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300254struct l2cap_chan *l2cap_chan_create(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200255{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300256 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200257
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300258 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
259 if (!chan)
260 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200261
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300262 chan->sk = sk;
263
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200264 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300265 list_add(&chan->global_l, &chan_list);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200266 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300267
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300268 INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300269
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300270 chan->state = BT_OPEN;
271
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300272 atomic_set(&chan->refcnt, 1);
273
Szymon Jancabc545b2011-11-03 16:05:44 +0100274 BT_DBG("sk %p chan %p", sk, chan);
275
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300276 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200277}
278
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300279void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300280{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200281 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300282 list_del(&chan->global_l);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200283 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300284
Ulisses Furquim371fd832011-12-21 20:02:36 -0200285 l2cap_chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300286}
287
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200288static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200289{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300290 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300291 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200292
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +0200293 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +0100294
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300295 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200296
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200297 switch (chan->chan_type) {
298 case L2CAP_CHAN_CONN_ORIENTED:
Ville Tervob62f3282011-02-10 22:38:50 -0300299 if (conn->hcon->type == LE_LINK) {
300 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300301 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300302 chan->scid = L2CAP_CID_LE_DATA;
303 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300304 } else {
305 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300306 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300307 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300308 }
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200309 break;
310
311 case L2CAP_CHAN_CONN_LESS:
Marcel Holtmann01394182006-07-03 10:02:46 +0200312 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300313 chan->scid = L2CAP_CID_CONN_LESS;
314 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300315 chan->omtu = L2CAP_DEFAULT_MTU;
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200316 break;
317
318 default:
Marcel Holtmann01394182006-07-03 10:02:46 +0200319 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300320 chan->scid = L2CAP_CID_SIGNALING;
321 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300322 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200323 }
324
Andrei Emeltchenko8f7975b2011-10-13 16:18:54 +0300325 chan->local_id = L2CAP_BESTEFFORT_ID;
326 chan->local_stype = L2CAP_SERV_BESTEFFORT;
327 chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
328 chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
329 chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
330 chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
331
Ulisses Furquim371fd832011-12-21 20:02:36 -0200332 l2cap_chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300333
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200334 list_add_rcu(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200335}
336
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900337/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200338 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300339static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200340{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300341 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300342 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200343 struct sock *parent = bt_sk(sk)->parent;
344
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300345 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200346
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300347 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200348
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900349 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300350 /* Delete from channel list */
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200351 list_del_rcu(&chan->list);
352 synchronize_rcu();
353
Ulisses Furquim371fd832011-12-21 20:02:36 -0200354 l2cap_chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300355
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300356 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200357 hci_conn_put(conn->hcon);
358 }
359
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300360 l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200361 sock_set_flag(sk, SOCK_ZAPPED);
362
363 if (err)
364 sk->sk_err = err;
365
366 if (parent) {
367 bt_accept_unlink(sk);
368 parent->sk_data_ready(parent, 0);
369 } else
370 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300371
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300372 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
373 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300374 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300375
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300376 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300377
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300378 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300379 struct srej_list *l, *tmp;
380
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300381 __clear_retrans_timer(chan);
382 __clear_monitor_timer(chan);
383 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300384
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300385 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300386
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300387 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300388 list_del(&l->list);
389 kfree(l);
390 }
391 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200392}
393
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300394static void l2cap_chan_cleanup_listen(struct sock *parent)
395{
396 struct sock *sk;
397
398 BT_DBG("parent %p", parent);
399
400 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300401 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300402 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300403 __clear_chan_timer(chan);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300404 lock_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300405 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300406 release_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300407 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300408 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300409}
410
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300411void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300412{
413 struct l2cap_conn *conn = chan->conn;
414 struct sock *sk = chan->sk;
415
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200416 BT_DBG("chan %p state %s sk %p", chan,
417 state_to_string(chan->state), sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300418
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300419 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300420 case BT_LISTEN:
421 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300422
423 l2cap_state_change(chan, BT_CLOSED);
424 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300425 break;
426
427 case BT_CONNECTED:
428 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300429 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300430 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300431 __clear_chan_timer(chan);
432 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300433 l2cap_send_disconn_req(conn, chan, reason);
434 } else
435 l2cap_chan_del(chan, reason);
436 break;
437
438 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300439 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300440 conn->hcon->type == ACL_LINK) {
441 struct l2cap_conn_rsp rsp;
442 __u16 result;
443
444 if (bt_sk(sk)->defer_setup)
445 result = L2CAP_CR_SEC_BLOCK;
446 else
447 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300448 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300449
450 rsp.scid = cpu_to_le16(chan->dcid);
451 rsp.dcid = cpu_to_le16(chan->scid);
452 rsp.result = cpu_to_le16(result);
453 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
454 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
455 sizeof(rsp), &rsp);
456 }
457
458 l2cap_chan_del(chan, reason);
459 break;
460
461 case BT_CONNECT:
462 case BT_DISCONN:
463 l2cap_chan_del(chan, reason);
464 break;
465
466 default:
467 sock_set_flag(sk, SOCK_ZAPPED);
468 break;
469 }
470}
471
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300472static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530473{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300474 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300475 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530476 case BT_SECURITY_HIGH:
477 return HCI_AT_DEDICATED_BONDING_MITM;
478 case BT_SECURITY_MEDIUM:
479 return HCI_AT_DEDICATED_BONDING;
480 default:
481 return HCI_AT_NO_BONDING;
482 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300483 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300484 if (chan->sec_level == BT_SECURITY_LOW)
485 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530486
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300487 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530488 return HCI_AT_NO_BONDING_MITM;
489 else
490 return HCI_AT_NO_BONDING;
491 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300492 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530493 case BT_SECURITY_HIGH:
494 return HCI_AT_GENERAL_BONDING_MITM;
495 case BT_SECURITY_MEDIUM:
496 return HCI_AT_GENERAL_BONDING;
497 default:
498 return HCI_AT_NO_BONDING;
499 }
500 }
501}
502
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200503/* Service level security */
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200504int l2cap_chan_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200505{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300506 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100507 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200508
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300509 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100510
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300511 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200512}
513
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200514static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200515{
516 u8 id;
517
518 /* Get next available identificator.
519 * 1 - 128 are used by kernel.
520 * 129 - 199 are reserved.
521 * 200 - 254 are used by utilities like l2ping, etc.
522 */
523
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200524 spin_lock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200525
526 if (++conn->tx_ident > 128)
527 conn->tx_ident = 1;
528
529 id = conn->tx_ident;
530
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200531 spin_unlock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200532
533 return id;
534}
535
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300536static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200537{
538 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200539 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200540
541 BT_DBG("code 0x%2.2x", code);
542
543 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300544 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200545
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200546 if (lmp_no_flush_capable(conn->hcon->hdev))
547 flags = ACL_START_NO_FLUSH;
548 else
549 flags = ACL_START;
550
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700551 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +0200552 skb->priority = HCI_PRIO_MAX;
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700553
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200554 hci_send_acl(conn->hchan, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200555}
556
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200557static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
558{
559 struct hci_conn *hcon = chan->conn->hcon;
560 u16 flags;
561
562 BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
563 skb->priority);
564
565 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
566 lmp_no_flush_capable(hcon->hdev))
567 flags = ACL_START_NO_FLUSH;
568 else
569 flags = ACL_START;
570
571 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
572 hci_send_acl(chan->conn->hchan, skb, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573}
574
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300575static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300576{
577 struct sk_buff *skb;
578 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300579 struct l2cap_conn *conn = chan->conn;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300580 int count, hlen;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300581
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300582 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300583 return;
584
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300585 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
586 hlen = L2CAP_EXT_HDR_SIZE;
587 else
588 hlen = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300589
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300590 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300591 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300592
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300593 BT_DBG("chan %p, control 0x%8.8x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300594
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300595 count = min_t(unsigned int, conn->mtu, hlen);
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +0300596
597 control |= __set_sframe(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300598
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300599 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +0300600 control |= __set_ctrl_final(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300601
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300602 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +0300603 control |= __set_ctrl_poll(chan);
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300604
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300605 skb = bt_skb_alloc(count, GFP_ATOMIC);
606 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300607 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300608
609 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300610 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300611 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300612
613 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300614
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300615 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300616 u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
617 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300618 }
619
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200620 skb->priority = HCI_PRIO_MAX;
621 l2cap_do_send(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300622}
623
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300624static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300625{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300626 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300627 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300628 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300629 } else
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300630 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300631
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300632 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300633
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300634 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300635}
636
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300637static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300638{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300639 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300640}
641
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300642static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200643{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300644 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200645
646 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100647 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
648 return;
649
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200650 if (l2cap_chan_check_security(chan) &&
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300651 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200652 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300653 req.scid = cpu_to_le16(chan->scid);
654 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200655
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300656 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300657 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200658
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300659 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
660 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200661 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200662 } else {
663 struct l2cap_info_req req;
664 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
665
666 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
667 conn->info_ident = l2cap_get_ident(conn);
668
Gustavo F. Padovan030013d2011-12-20 10:57:28 -0200669 schedule_delayed_work(&conn->info_timer,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200670 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
671
672 l2cap_send_cmd(conn, conn->info_ident,
673 L2CAP_INFO_REQ, sizeof(req), &req);
674 }
675}
676
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300677static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
678{
679 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300680 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300681 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
682
683 switch (mode) {
684 case L2CAP_MODE_ERTM:
685 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
686 case L2CAP_MODE_STREAMING:
687 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
688 default:
689 return 0x00;
690 }
691}
692
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300693static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300694{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300695 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300696 struct l2cap_disconn_req req;
697
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300698 if (!conn)
699 return;
700
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300701 sk = chan->sk;
702
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300703 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300704 __clear_retrans_timer(chan);
705 __clear_monitor_timer(chan);
706 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300707 }
708
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300709 req.dcid = cpu_to_le16(chan->dcid);
710 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300711 l2cap_send_cmd(conn, l2cap_get_ident(conn),
712 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300713
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300714 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300715 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300716}
717
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200719static void l2cap_conn_start(struct l2cap_conn *conn)
720{
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200721 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200722
723 BT_DBG("conn %p", conn);
724
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200725 rcu_read_lock();
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200726
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200727 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300728 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300729
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200730 bh_lock_sock(sk);
731
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300732 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200733 bh_unlock_sock(sk);
734 continue;
735 }
736
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300737 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300738 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300739
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200740 if (!l2cap_chan_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300741 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300742 bh_unlock_sock(sk);
743 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200744 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300745
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300746 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
747 && test_bit(CONF_STATE2_DEVICE,
748 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300749 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300750 * so release the lock */
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300751 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300752 bh_unlock_sock(sk);
753 continue;
754 }
755
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300756 req.scid = cpu_to_le16(chan->scid);
757 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300758
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300759 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300760 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300761
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300762 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
763 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300764
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300765 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200766 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300767 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300768 rsp.scid = cpu_to_le16(chan->dcid);
769 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200770
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200771 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100772 if (bt_sk(sk)->defer_setup) {
773 struct sock *parent = bt_sk(sk)->parent;
774 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
775 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +0000776 if (parent)
777 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100778
779 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300780 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100781 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
782 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
783 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200784 } else {
785 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
786 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
787 }
788
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300789 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
790 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300791
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300792 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300793 rsp.result != L2CAP_CR_SUCCESS) {
794 bh_unlock_sock(sk);
795 continue;
796 }
797
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300798 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300799 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300800 l2cap_build_conf_req(chan, buf), buf);
801 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200802 }
803
804 bh_unlock_sock(sk);
805 }
806
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200807 rcu_read_unlock();
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200808}
809
Ville Tervob62f3282011-02-10 22:38:50 -0300810/* Find socket with cid and source bdaddr.
811 * Returns closest match, locked.
812 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300813static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300814{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300815 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300816
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300817 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300818
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300819 list_for_each_entry(c, &chan_list, global_l) {
820 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300821
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300822 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300823 continue;
824
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300825 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300826 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300827 if (!bacmp(&bt_sk(sk)->src, src)) {
828 read_unlock(&chan_list_lock);
829 return c;
830 }
Ville Tervob62f3282011-02-10 22:38:50 -0300831
832 /* Closest match */
833 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300834 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300835 }
836 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300837
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300838 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300839
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300840 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300841}
842
843static void l2cap_le_conn_ready(struct l2cap_conn *conn)
844{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300845 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300846 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300847
848 BT_DBG("");
849
850 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300851 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300852 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300853 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300854 return;
855
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300856 parent = pchan->sk;
857
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300858 lock_sock(parent);
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300859
Ville Tervob62f3282011-02-10 22:38:50 -0300860 /* Check for backlog size */
861 if (sk_acceptq_is_full(parent)) {
862 BT_DBG("backlog full %d", parent->sk_ack_backlog);
863 goto clean;
864 }
865
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300866 chan = pchan->ops->new_connection(pchan->data);
867 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300868 goto clean;
869
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300870 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300871
Ville Tervob62f3282011-02-10 22:38:50 -0300872 hci_conn_hold(conn->hcon);
873
Ville Tervob62f3282011-02-10 22:38:50 -0300874 bacpy(&bt_sk(sk)->src, conn->src);
875 bacpy(&bt_sk(sk)->dst, conn->dst);
876
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300877 bt_accept_enqueue(parent, sk);
878
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200879 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300880
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300881 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300882
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300883 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300884 parent->sk_data_ready(parent, 0);
885
Ville Tervob62f3282011-02-10 22:38:50 -0300886clean:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300887 release_sock(parent);
Ville Tervob62f3282011-02-10 22:38:50 -0300888}
889
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +0200890static void l2cap_chan_ready(struct l2cap_chan *chan)
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300891{
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +0200892 struct sock *sk = chan->sk;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300893 struct sock *parent = bt_sk(sk)->parent;
894
895 BT_DBG("sk %p, parent %p", sk, parent);
896
897 chan->conf_state = 0;
898 __clear_chan_timer(chan);
899
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300900 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300901 sk->sk_state_change(sk);
902
903 if (parent)
904 parent->sk_data_ready(parent, 0);
905}
906
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200907static void l2cap_conn_ready(struct l2cap_conn *conn)
908{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300909 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200910
911 BT_DBG("conn %p", conn);
912
Ville Tervob62f3282011-02-10 22:38:50 -0300913 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
914 l2cap_le_conn_ready(conn);
915
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -0300916 if (conn->hcon->out && conn->hcon->type == LE_LINK)
917 smp_conn_security(conn, conn->hcon->pending_sec_level);
918
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200919 rcu_read_lock();
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200920
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200921 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300922 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300923
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200924 bh_lock_sock(sk);
925
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300926 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300927 if (smp_conn_security(conn, chan->sec_level))
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +0200928 l2cap_chan_ready(chan);
Ville Tervoacd7d372011-02-10 22:38:49 -0300929
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300930 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300931 __clear_chan_timer(chan);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300932 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200933 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300934
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300935 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300936 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200937
938 bh_unlock_sock(sk);
939 }
940
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200941 rcu_read_unlock();
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200942}
943
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200944/* Notify sockets that we cannot guaranty reliability anymore */
945static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
946{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300947 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200948
949 BT_DBG("conn %p", conn);
950
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200951 rcu_read_lock();
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200952
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200953 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300954 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300955
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +0300956 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200957 sk->sk_err = err;
958 }
959
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200960 rcu_read_unlock();
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200961}
962
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -0200963static void l2cap_info_timeout(struct work_struct *work)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200964{
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -0200965 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
Gustavo F. Padovan030013d2011-12-20 10:57:28 -0200966 info_timer.work);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200967
Marcel Holtmann984947d2009-02-06 23:35:19 +0100968 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100969 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100970
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200971 l2cap_conn_start(conn);
972}
973
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300974static void l2cap_conn_del(struct hci_conn *hcon, int err)
975{
976 struct l2cap_conn *conn = hcon->l2cap_data;
977 struct l2cap_chan *chan, *l;
978 struct sock *sk;
979
980 if (!conn)
981 return;
982
983 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
984
985 kfree_skb(conn->rx_skb);
986
987 /* Kill channels */
988 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
989 sk = chan->sk;
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300990 lock_sock(sk);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300991 l2cap_chan_del(chan, err);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300992 release_sock(sk);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300993 chan->ops->close(chan->data);
994 }
995
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200996 hci_chan_del(conn->hchan);
997
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300998 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
Ulisses Furquim127074b2012-01-30 18:26:29 -0200999 cancel_delayed_work_sync(&conn->info_timer);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001000
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001001 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
Ulisses Furquim127074b2012-01-30 18:26:29 -02001002 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001003 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001004 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001005
1006 hcon->l2cap_data = NULL;
1007 kfree(conn);
1008}
1009
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001010static void security_timeout(struct work_struct *work)
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001011{
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001012 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1013 security_timer.work);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001014
1015 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1016}
1017
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1019{
Marcel Holtmann01394182006-07-03 10:02:46 +02001020 struct l2cap_conn *conn = hcon->l2cap_data;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001021 struct hci_chan *hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022
Marcel Holtmann01394182006-07-03 10:02:46 +02001023 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 return conn;
1025
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001026 hchan = hci_chan_create(hcon);
1027 if (!hchan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001030 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1031 if (!conn) {
1032 hci_chan_del(hchan);
1033 return NULL;
1034 }
1035
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 hcon->l2cap_data = conn;
1037 conn->hcon = hcon;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001038 conn->hchan = hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001040 BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
Marcel Holtmann01394182006-07-03 10:02:46 +02001041
Ville Tervoacd7d372011-02-10 22:38:49 -03001042 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1043 conn->mtu = hcon->hdev->le_mtu;
1044 else
1045 conn->mtu = hcon->hdev->acl_mtu;
1046
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 conn->src = &hcon->hdev->bdaddr;
1048 conn->dst = &hcon->dst;
1049
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001050 conn->feat_mask = 0;
1051
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001053
1054 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001056 if (hcon->type == LE_LINK)
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001057 INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001058 else
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02001059 INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
Dave Young45054dc2009-10-18 20:28:30 +00001060
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001061 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01001062
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 return conn;
1064}
1065
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067
1068/* Find socket with psm and source bdaddr.
1069 * Returns closest match.
1070 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001071static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001073 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001075 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001076
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001077 list_for_each_entry(c, &chan_list, global_l) {
1078 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001079
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001080 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 continue;
1082
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001083 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001085 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001086 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001087 return c;
1088 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089
1090 /* Closest match */
1091 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001092 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 }
1094 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001096 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001097
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001098 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099}
1100
Johan Hedbergcbe8fed2012-01-08 22:51:16 +02001101int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001103 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 bdaddr_t *src = &bt_sk(sk)->src;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 struct l2cap_conn *conn;
1106 struct hci_conn *hcon;
1107 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001108 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001109 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001111 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001112 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001114 hdev = hci_get_route(dst, src);
1115 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 return -EHOSTUNREACH;
1117
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001118 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001120 lock_sock(sk);
1121
1122 /* PSM must be odd and lsb of upper byte must be 0 */
1123 if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
1124 chan->chan_type != L2CAP_CHAN_RAW) {
1125 err = -EINVAL;
1126 goto done;
1127 }
1128
1129 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
1130 err = -EINVAL;
1131 goto done;
1132 }
1133
1134 switch (chan->mode) {
1135 case L2CAP_MODE_BASIC:
1136 break;
1137 case L2CAP_MODE_ERTM:
1138 case L2CAP_MODE_STREAMING:
1139 if (!disable_ertm)
1140 break;
1141 /* fall through */
1142 default:
1143 err = -ENOTSUPP;
1144 goto done;
1145 }
1146
1147 switch (sk->sk_state) {
1148 case BT_CONNECT:
1149 case BT_CONNECT2:
1150 case BT_CONFIG:
1151 /* Already connecting */
1152 err = 0;
1153 goto done;
1154
1155 case BT_CONNECTED:
1156 /* Already connected */
1157 err = -EISCONN;
1158 goto done;
1159
1160 case BT_OPEN:
1161 case BT_BOUND:
1162 /* Can connect */
1163 break;
1164
1165 default:
1166 err = -EBADFD;
1167 goto done;
1168 }
1169
1170 /* Set destination address and psm */
Gustavo F. Padovan9219b2a2012-01-02 20:08:04 -02001171 bacpy(&bt_sk(sk)->dst, dst);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001172 chan->psm = psm;
1173 chan->dcid = cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001175 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001176
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001177 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001178 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001179 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001180 else
1181 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001182 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001183
Ville Tervo30e76272011-02-22 16:10:53 -03001184 if (IS_ERR(hcon)) {
1185 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001187 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188
1189 conn = l2cap_conn_add(hcon, 0);
1190 if (!conn) {
1191 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001192 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 goto done;
1194 }
1195
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 /* Update source addr of the socket */
1197 bacpy(src, conn->src);
1198
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001199 l2cap_chan_add(conn, chan);
1200
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001201 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001202 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203
1204 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001205 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001206 __clear_chan_timer(chan);
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001207 if (l2cap_chan_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001208 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001209 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001210 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 }
1212
Ville Tervo30e76272011-02-22 16:10:53 -03001213 err = 0;
1214
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001216 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 hci_dev_put(hdev);
1218 return err;
1219}
1220
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001221int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001222{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001223 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001224 DECLARE_WAITQUEUE(wait, current);
1225 int err = 0;
1226 int timeo = HZ/5;
1227
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001228 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001229 set_current_state(TASK_INTERRUPTIBLE);
1230 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001231 if (!timeo)
1232 timeo = HZ/5;
1233
1234 if (signal_pending(current)) {
1235 err = sock_intr_errno(timeo);
1236 break;
1237 }
1238
1239 release_sock(sk);
1240 timeo = schedule_timeout(timeo);
1241 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001242 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001243
1244 err = sock_error(sk);
1245 if (err)
1246 break;
1247 }
1248 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001249 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001250 return err;
1251}
1252
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001253static void l2cap_monitor_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001254{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001255 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1256 monitor_timer.work);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001257 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001258
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001259 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001260
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001261 lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001262 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001263 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001264 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001265 return;
1266 }
1267
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001268 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001269 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001270
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001271 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001272 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001273}
1274
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001275static void l2cap_retrans_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001276{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001277 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1278 retrans_timer.work);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001279 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001280
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001281 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001282
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001283 lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001284 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001285 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001286
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001287 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001288
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001289 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001290 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001291}
1292
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001293static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001294{
1295 struct sk_buff *skb;
1296
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001297 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001298 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001299 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001300 break;
1301
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001302 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001303 kfree_skb(skb);
1304
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001305 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001306 }
1307
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001308 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001309 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001310}
1311
Szymon Janc67c9e842011-07-28 16:24:33 +02001312static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001313{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001314 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001315 u32 control;
1316 u16 fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001317
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001318 while ((skb = skb_dequeue(&chan->tx_q))) {
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001319 control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001320 control |= __set_txseq(chan, chan->next_tx_seq);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001321 __put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001322
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001323 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001324 fcs = crc16(0, (u8 *)skb->data,
1325 skb->len - L2CAP_FCS_SIZE);
1326 put_unaligned_le16(fcs,
1327 skb->data + skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001328 }
1329
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001330 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001331
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001332 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001333 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001334}
1335
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001336static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001337{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001338 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001339 u16 fcs;
1340 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001341
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001342 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001343 if (!skb)
1344 return;
1345
Szymon Jancd1726b62011-11-16 09:32:20 +01001346 while (bt_cb(skb)->tx_seq != tx_seq) {
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001347 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001348 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001349
Szymon Jancd1726b62011-11-16 09:32:20 +01001350 skb = skb_queue_next(&chan->tx_q, skb);
1351 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001352
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001353 if (chan->remote_max_tx &&
1354 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001355 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001356 return;
1357 }
1358
1359 tx_skb = skb_clone(skb, GFP_ATOMIC);
1360 bt_cb(skb)->retries++;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001361
1362 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001363 control &= __get_sar_mask(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001364
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001365 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001366 control |= __set_ctrl_final(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001367
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001368 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001369 control |= __set_txseq(chan, tx_seq);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001370
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001371 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001372
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001373 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001374 fcs = crc16(0, (u8 *)tx_skb->data,
1375 tx_skb->len - L2CAP_FCS_SIZE);
1376 put_unaligned_le16(fcs,
1377 tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001378 }
1379
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001380 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001381}
1382
Szymon Janc67c9e842011-07-28 16:24:33 +02001383static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001384{
1385 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001386 u16 fcs;
1387 u32 control;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001388 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001389
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001390 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001391 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001392
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001393 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001394
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001395 if (chan->remote_max_tx &&
1396 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001397 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001398 break;
1399 }
1400
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001401 tx_skb = skb_clone(skb, GFP_ATOMIC);
1402
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001403 bt_cb(skb)->retries++;
1404
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001405 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001406 control &= __get_sar_mask(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001407
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001408 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001409 control |= __set_ctrl_final(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001410
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001411 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001412 control |= __set_txseq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001413
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001414 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001415
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001416 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001417 fcs = crc16(0, (u8 *)skb->data,
1418 tx_skb->len - L2CAP_FCS_SIZE);
1419 put_unaligned_le16(fcs, skb->data +
1420 tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001421 }
1422
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001423 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001424
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001425 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001426
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001427 bt_cb(skb)->tx_seq = chan->next_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001428
1429 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001430
Szymon Janc8ed7a0a2012-02-07 15:43:01 +01001431 if (bt_cb(skb)->retries == 1) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001432 chan->unacked_frames++;
Szymon Janc930fa4a2012-02-07 15:43:02 +01001433
1434 if (!nsent++)
1435 __clear_ack_timer(chan);
Szymon Janc8ed7a0a2012-02-07 15:43:01 +01001436 }
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301437
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001438 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001439
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001440 if (skb_queue_is_last(&chan->tx_q, skb))
1441 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001442 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001443 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001444 }
1445
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001446 return nsent;
1447}
1448
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001449static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001450{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001451 int ret;
1452
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001453 if (!skb_queue_empty(&chan->tx_q))
1454 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001455
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001456 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001457 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001458 return ret;
1459}
1460
Szymon Jancb17e73b2012-01-11 10:59:47 +01001461static void __l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001462{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001463 u32 control = 0;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001464
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001465 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001466
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001467 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001468 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001469 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001470 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001471 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001472 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001473
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001474 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001475 return;
1476
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001477 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001478 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001479}
1480
Szymon Jancb17e73b2012-01-11 10:59:47 +01001481static void l2cap_send_ack(struct l2cap_chan *chan)
1482{
1483 __clear_ack_timer(chan);
1484 __l2cap_send_ack(chan);
1485}
1486
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001487static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001488{
1489 struct srej_list *tail;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001490 u32 control;
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001491
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001492 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001493 control |= __set_ctrl_final(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001494
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001495 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001496 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001497
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001498 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001499}
1500
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001501static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, struct msghdr *msg, int len, int count, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502{
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001503 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001504 struct sk_buff **frag;
1505 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001507 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001508 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509
1510 sent += count;
1511 len -= count;
1512
1513 /* Continuation fragments (no L2CAP header) */
1514 frag = &skb_shinfo(skb)->frag_list;
1515 while (len) {
1516 count = min_t(unsigned int, conn->mtu, len);
1517
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001518 *frag = chan->ops->alloc_skb(chan, count,
1519 msg->msg_flags & MSG_DONTWAIT, &err);
1520
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001522 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001523 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1524 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001526 (*frag)->priority = skb->priority;
1527
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 sent += count;
1529 len -= count;
1530
1531 frag = &(*frag)->next;
1532 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533
1534 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001535}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001537static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
1538 struct msghdr *msg, size_t len,
1539 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001540{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001541 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001542 struct sk_buff *skb;
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001543 int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001544 struct l2cap_hdr *lh;
1545
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001546 BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001547
1548 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001549
1550 skb = chan->ops->alloc_skb(chan, count + hlen,
1551 msg->msg_flags & MSG_DONTWAIT, &err);
1552
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001553 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001554 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001555
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001556 skb->priority = priority;
1557
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001558 /* Create L2CAP header */
1559 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001560 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001561 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001562 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001563
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001564 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001565 if (unlikely(err < 0)) {
1566 kfree_skb(skb);
1567 return ERR_PTR(err);
1568 }
1569 return skb;
1570}
1571
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001572static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
1573 struct msghdr *msg, size_t len,
1574 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001575{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001576 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001577 struct sk_buff *skb;
1578 int err, count, hlen = L2CAP_HDR_SIZE;
1579 struct l2cap_hdr *lh;
1580
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001581 BT_DBG("chan %p len %d", chan, (int)len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001582
1583 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001584
1585 skb = chan->ops->alloc_skb(chan, count + hlen,
1586 msg->msg_flags & MSG_DONTWAIT, &err);
1587
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001588 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001589 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001590
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001591 skb->priority = priority;
1592
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001593 /* Create L2CAP header */
1594 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001595 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001596 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1597
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001598 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001599 if (unlikely(err < 0)) {
1600 kfree_skb(skb);
1601 return ERR_PTR(err);
1602 }
1603 return skb;
1604}
1605
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001606static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1607 struct msghdr *msg, size_t len,
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001608 u32 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001609{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001610 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001611 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001612 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001613 struct l2cap_hdr *lh;
1614
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001615 BT_DBG("chan %p len %d", chan, (int)len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001616
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001617 if (!conn)
1618 return ERR_PTR(-ENOTCONN);
1619
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001620 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1621 hlen = L2CAP_EXT_HDR_SIZE;
1622 else
1623 hlen = L2CAP_ENH_HDR_SIZE;
1624
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001625 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001626 hlen += L2CAP_SDULEN_SIZE;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001627
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001628 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001629 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001630
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001631 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001632
1633 skb = chan->ops->alloc_skb(chan, count + hlen,
1634 msg->msg_flags & MSG_DONTWAIT, &err);
1635
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001636 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001637 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001638
1639 /* Create L2CAP header */
1640 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001641 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001642 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001643
1644 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
1645
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001646 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001647 put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001648
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001649 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001650 if (unlikely(err < 0)) {
1651 kfree_skb(skb);
1652 return ERR_PTR(err);
1653 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001654
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001655 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001656 put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001657
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001658 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001659 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660}
1661
Szymon Janc67c9e842011-07-28 16:24:33 +02001662static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001663{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001664 struct sk_buff *skb;
1665 struct sk_buff_head sar_queue;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001666 u32 control;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001667 size_t size = 0;
1668
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001669 skb_queue_head_init(&sar_queue);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001670 control = __set_ctrl_sar(chan, L2CAP_SAR_START);
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001671 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001672 if (IS_ERR(skb))
1673 return PTR_ERR(skb);
1674
1675 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001676 len -= chan->remote_mps;
1677 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001678
1679 while (len > 0) {
1680 size_t buflen;
1681
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001682 if (len > chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001683 control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001684 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001685 } else {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001686 control = __set_ctrl_sar(chan, L2CAP_SAR_END);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001687 buflen = len;
1688 }
1689
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001690 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001691 if (IS_ERR(skb)) {
1692 skb_queue_purge(&sar_queue);
1693 return PTR_ERR(skb);
1694 }
1695
1696 __skb_queue_tail(&sar_queue, skb);
1697 len -= buflen;
1698 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001699 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001700 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1701 if (chan->tx_send_head == NULL)
1702 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001703
1704 return size;
1705}
1706
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001707int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
1708 u32 priority)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001709{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001710 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001711 u32 control;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001712 int err;
1713
1714 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001715 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001716 skb = l2cap_create_connless_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001717 if (IS_ERR(skb))
1718 return PTR_ERR(skb);
1719
1720 l2cap_do_send(chan, skb);
1721 return len;
1722 }
1723
1724 switch (chan->mode) {
1725 case L2CAP_MODE_BASIC:
1726 /* Check outgoing MTU */
1727 if (len > chan->omtu)
1728 return -EMSGSIZE;
1729
1730 /* Create a basic PDU */
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001731 skb = l2cap_create_basic_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001732 if (IS_ERR(skb))
1733 return PTR_ERR(skb);
1734
1735 l2cap_do_send(chan, skb);
1736 err = len;
1737 break;
1738
1739 case L2CAP_MODE_ERTM:
1740 case L2CAP_MODE_STREAMING:
1741 /* Entire SDU fits into one PDU */
1742 if (len <= chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001743 control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001744 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1745 0);
1746 if (IS_ERR(skb))
1747 return PTR_ERR(skb);
1748
1749 __skb_queue_tail(&chan->tx_q, skb);
1750
1751 if (chan->tx_send_head == NULL)
1752 chan->tx_send_head = skb;
1753
1754 } else {
1755 /* Segment SDU into multiples PDUs */
1756 err = l2cap_sar_segment_sdu(chan, msg, len);
1757 if (err < 0)
1758 return err;
1759 }
1760
1761 if (chan->mode == L2CAP_MODE_STREAMING) {
1762 l2cap_streaming_send(chan);
1763 err = len;
1764 break;
1765 }
1766
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001767 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1768 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001769 err = len;
1770 break;
1771 }
1772
1773 err = l2cap_ertm_send(chan);
1774 if (err >= 0)
1775 err = len;
1776
1777 break;
1778
1779 default:
1780 BT_DBG("bad state %1.1x", chan->mode);
1781 err = -EBADFD;
1782 }
1783
1784 return err;
1785}
1786
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787/* Copy frame to all raw sockets on that connection */
1788static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1789{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001791 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792
1793 BT_DBG("conn %p", conn);
1794
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001795 rcu_read_lock();
1796
1797 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001798 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001799 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800 continue;
1801
1802 /* Don't send frame to the socket it came from */
1803 if (skb->sk == sk)
1804 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001805 nskb = skb_clone(skb, GFP_ATOMIC);
1806 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 continue;
1808
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001809 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 kfree_skb(nskb);
1811 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001812
1813 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814}
1815
1816/* ---- L2CAP signalling commands ---- */
1817static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1818 u8 code, u8 ident, u16 dlen, void *data)
1819{
1820 struct sk_buff *skb, **frag;
1821 struct l2cap_cmd_hdr *cmd;
1822 struct l2cap_hdr *lh;
1823 int len, count;
1824
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001825 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1826 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827
1828 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1829 count = min_t(unsigned int, conn->mtu, len);
1830
1831 skb = bt_skb_alloc(count, GFP_ATOMIC);
1832 if (!skb)
1833 return NULL;
1834
1835 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001836 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001837
1838 if (conn->hcon->type == LE_LINK)
1839 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1840 else
1841 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842
1843 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1844 cmd->code = code;
1845 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001846 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847
1848 if (dlen) {
1849 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1850 memcpy(skb_put(skb, count), data, count);
1851 data += count;
1852 }
1853
1854 len -= skb->len;
1855
1856 /* Continuation fragments (no L2CAP header) */
1857 frag = &skb_shinfo(skb)->frag_list;
1858 while (len) {
1859 count = min_t(unsigned int, conn->mtu, len);
1860
1861 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1862 if (!*frag)
1863 goto fail;
1864
1865 memcpy(skb_put(*frag, count), data, count);
1866
1867 len -= count;
1868 data += count;
1869
1870 frag = &(*frag)->next;
1871 }
1872
1873 return skb;
1874
1875fail:
1876 kfree_skb(skb);
1877 return NULL;
1878}
1879
1880static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1881{
1882 struct l2cap_conf_opt *opt = *ptr;
1883 int len;
1884
1885 len = L2CAP_CONF_OPT_SIZE + opt->len;
1886 *ptr += len;
1887
1888 *type = opt->type;
1889 *olen = opt->len;
1890
1891 switch (opt->len) {
1892 case 1:
1893 *val = *((u8 *) opt->val);
1894 break;
1895
1896 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001897 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 break;
1899
1900 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001901 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 break;
1903
1904 default:
1905 *val = (unsigned long) opt->val;
1906 break;
1907 }
1908
1909 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1910 return len;
1911}
1912
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1914{
1915 struct l2cap_conf_opt *opt = *ptr;
1916
1917 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1918
1919 opt->type = type;
1920 opt->len = len;
1921
1922 switch (len) {
1923 case 1:
1924 *((u8 *) opt->val) = val;
1925 break;
1926
1927 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001928 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929 break;
1930
1931 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001932 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 break;
1934
1935 default:
1936 memcpy(opt->val, (void *) val, len);
1937 break;
1938 }
1939
1940 *ptr += L2CAP_CONF_OPT_SIZE + len;
1941}
1942
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001943static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
1944{
1945 struct l2cap_conf_efs efs;
1946
Szymon Janc1ec918c2011-11-16 09:32:21 +01001947 switch (chan->mode) {
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001948 case L2CAP_MODE_ERTM:
1949 efs.id = chan->local_id;
1950 efs.stype = chan->local_stype;
1951 efs.msdu = cpu_to_le16(chan->local_msdu);
1952 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1953 efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
1954 efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
1955 break;
1956
1957 case L2CAP_MODE_STREAMING:
1958 efs.id = 1;
1959 efs.stype = L2CAP_SERV_BESTEFFORT;
1960 efs.msdu = cpu_to_le16(chan->local_msdu);
1961 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1962 efs.acc_lat = 0;
1963 efs.flush_to = 0;
1964 break;
1965
1966 default:
1967 return;
1968 }
1969
1970 l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
1971 (unsigned long) &efs);
1972}
1973
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001974static void l2cap_ack_timeout(struct work_struct *work)
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001975{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001976 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1977 ack_timer.work);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001978
Gustavo F. Padovan2fb9b3d2011-12-22 16:56:05 -02001979 BT_DBG("chan %p", chan);
1980
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001981 lock_sock(chan->sk);
Szymon Jancb17e73b2012-01-11 10:59:47 +01001982 __l2cap_send_ack(chan);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001983 release_sock(chan->sk);
Szymon Janc09bfb2e2012-01-11 10:59:49 +01001984
1985 l2cap_chan_put(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001986}
1987
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001988static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001989{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001990 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001991 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001992 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001993 chan->num_acked = 0;
1994 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001995
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001996 INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
1997 INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
1998 INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001999
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002000 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002001
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03002002 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002003}
2004
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002005static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2006{
2007 switch (mode) {
2008 case L2CAP_MODE_STREAMING:
2009 case L2CAP_MODE_ERTM:
2010 if (l2cap_mode_supported(mode, remote_feat_mask))
2011 return mode;
2012 /* fall through */
2013 default:
2014 return L2CAP_MODE_BASIC;
2015 }
2016}
2017
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002018static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
2019{
2020 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
2021}
2022
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002023static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2024{
2025 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2026}
2027
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002028static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
2029{
2030 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002031 __l2cap_ews_supported(chan)) {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002032 /* use extended control field */
2033 set_bit(FLAG_EXT_CTRL, &chan->flags);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002034 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2035 } else {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002036 chan->tx_win = min_t(u16, chan->tx_win,
2037 L2CAP_DEFAULT_TX_WINDOW);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002038 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2039 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002040}
2041
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002042static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002045 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 void *ptr = req->data;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002047 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002049 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002051 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002052 goto done;
2053
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002054 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002055 case L2CAP_MODE_STREAMING:
2056 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002057 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002058 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002059
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002060 if (__l2cap_efs_supported(chan))
2061 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2062
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002063 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002064 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002065 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002066 break;
2067 }
2068
2069done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002070 if (chan->imtu != L2CAP_DEFAULT_MTU)
2071 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002072
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002073 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002074 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002075 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2076 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002077 break;
2078
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002079 rfc.mode = L2CAP_MODE_BASIC;
2080 rfc.txwin_size = 0;
2081 rfc.max_transmit = 0;
2082 rfc.retrans_timeout = 0;
2083 rfc.monitor_timeout = 0;
2084 rfc.max_pdu_size = 0;
2085
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002086 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2087 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002088 break;
2089
2090 case L2CAP_MODE_ERTM:
2091 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002092 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002093 rfc.retrans_timeout = 0;
2094 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002095
2096 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2097 L2CAP_EXT_HDR_SIZE -
2098 L2CAP_SDULEN_SIZE -
2099 L2CAP_FCS_SIZE);
2100 rfc.max_pdu_size = cpu_to_le16(size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002101
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002102 l2cap_txwin_setup(chan);
2103
2104 rfc.txwin_size = min_t(u16, chan->tx_win,
2105 L2CAP_DEFAULT_TX_WINDOW);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002106
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002107 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2108 (unsigned long) &rfc);
2109
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002110 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2111 l2cap_add_opt_efs(&ptr, chan);
2112
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002113 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002114 break;
2115
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002116 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002117 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002118 chan->fcs = L2CAP_FCS_NONE;
2119 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002120 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002121
2122 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2123 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2124 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002125 break;
2126
2127 case L2CAP_MODE_STREAMING:
2128 rfc.mode = L2CAP_MODE_STREAMING;
2129 rfc.txwin_size = 0;
2130 rfc.max_transmit = 0;
2131 rfc.retrans_timeout = 0;
2132 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002133
2134 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2135 L2CAP_EXT_HDR_SIZE -
2136 L2CAP_SDULEN_SIZE -
2137 L2CAP_FCS_SIZE);
2138 rfc.max_pdu_size = cpu_to_le16(size);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002139
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002140 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2141 (unsigned long) &rfc);
2142
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002143 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2144 l2cap_add_opt_efs(&ptr, chan);
2145
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002146 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002147 break;
2148
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002149 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002150 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002151 chan->fcs = L2CAP_FCS_NONE;
2152 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002153 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002154 break;
2155 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002157 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002158 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159
2160 return ptr - data;
2161}
2162
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002163static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002165 struct l2cap_conf_rsp *rsp = data;
2166 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002167 void *req = chan->conf_req;
2168 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002169 int type, hint, olen;
2170 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002171 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002172 struct l2cap_conf_efs efs;
2173 u8 remote_efs = 0;
Marcel Holtmann861d6882007-10-20 13:37:06 +02002174 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002175 u16 result = L2CAP_CONF_SUCCESS;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002176 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002178 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002179
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002180 while (len >= L2CAP_CONF_OPT_SIZE) {
2181 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002183 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002184 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002185
2186 switch (type) {
2187 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002188 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002189 break;
2190
2191 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002192 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002193 break;
2194
2195 case L2CAP_CONF_QOS:
2196 break;
2197
Marcel Holtmann6464f352007-10-20 13:39:51 +02002198 case L2CAP_CONF_RFC:
2199 if (olen == sizeof(rfc))
2200 memcpy(&rfc, (void *) val, olen);
2201 break;
2202
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002203 case L2CAP_CONF_FCS:
2204 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002205 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002206 break;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002207
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002208 case L2CAP_CONF_EFS:
2209 remote_efs = 1;
2210 if (olen == sizeof(efs))
2211 memcpy(&efs, (void *) val, olen);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002212 break;
2213
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002214 case L2CAP_CONF_EWS:
2215 if (!enable_hs)
2216 return -ECONNREFUSED;
2217
2218 set_bit(FLAG_EXT_CTRL, &chan->flags);
2219 set_bit(CONF_EWS_RECV, &chan->conf_state);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002220 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002221 chan->remote_tx_win = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002222 break;
2223
2224 default:
2225 if (hint)
2226 break;
2227
2228 result = L2CAP_CONF_UNKNOWN;
2229 *((u8 *) ptr++) = type;
2230 break;
2231 }
2232 }
2233
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002234 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002235 goto done;
2236
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002237 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002238 case L2CAP_MODE_STREAMING:
2239 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002240 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002241 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002242 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002243 break;
2244 }
2245
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002246 if (remote_efs) {
2247 if (__l2cap_efs_supported(chan))
2248 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2249 else
2250 return -ECONNREFUSED;
2251 }
2252
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002253 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002254 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002255
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002256 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002257 }
2258
2259done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002260 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002261 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002262 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002263
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002264 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002265 return -ECONNREFUSED;
2266
2267 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2268 sizeof(rfc), (unsigned long) &rfc);
2269 }
2270
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002271 if (result == L2CAP_CONF_SUCCESS) {
2272 /* Configure output options and let the other side know
2273 * which ones we don't like. */
2274
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002275 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2276 result = L2CAP_CONF_UNACCEPT;
2277 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002278 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002279 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002280 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002281 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002282
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002283 if (remote_efs) {
2284 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2285 efs.stype != L2CAP_SERV_NOTRAFIC &&
2286 efs.stype != chan->local_stype) {
2287
2288 result = L2CAP_CONF_UNACCEPT;
2289
2290 if (chan->num_conf_req >= 1)
2291 return -ECONNREFUSED;
2292
2293 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002294 sizeof(efs),
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002295 (unsigned long) &efs);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002296 } else {
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002297 /* Send PENDING Conf Rsp */
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002298 result = L2CAP_CONF_PENDING;
2299 set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002300 }
2301 }
2302
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002303 switch (rfc.mode) {
2304 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002305 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002306 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002307 break;
2308
2309 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002310 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2311 chan->remote_tx_win = rfc.txwin_size;
2312 else
2313 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2314
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002315 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002316
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002317 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2318 chan->conn->mtu -
2319 L2CAP_EXT_HDR_SIZE -
2320 L2CAP_SDULEN_SIZE -
2321 L2CAP_FCS_SIZE);
2322 rfc.max_pdu_size = cpu_to_le16(size);
2323 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002324
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002325 rfc.retrans_timeout =
2326 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2327 rfc.monitor_timeout =
2328 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002329
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002330 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002331
2332 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2333 sizeof(rfc), (unsigned long) &rfc);
2334
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002335 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2336 chan->remote_id = efs.id;
2337 chan->remote_stype = efs.stype;
2338 chan->remote_msdu = le16_to_cpu(efs.msdu);
2339 chan->remote_flush_to =
2340 le32_to_cpu(efs.flush_to);
2341 chan->remote_acc_lat =
2342 le32_to_cpu(efs.acc_lat);
2343 chan->remote_sdu_itime =
2344 le32_to_cpu(efs.sdu_itime);
2345 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2346 sizeof(efs), (unsigned long) &efs);
2347 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002348 break;
2349
2350 case L2CAP_MODE_STREAMING:
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002351 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2352 chan->conn->mtu -
2353 L2CAP_EXT_HDR_SIZE -
2354 L2CAP_SDULEN_SIZE -
2355 L2CAP_FCS_SIZE);
2356 rfc.max_pdu_size = cpu_to_le16(size);
2357 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002358
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002359 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002360
2361 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2362 sizeof(rfc), (unsigned long) &rfc);
2363
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002364 break;
2365
2366 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002367 result = L2CAP_CONF_UNACCEPT;
2368
2369 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002370 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002371 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002372
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002373 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002374 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002375 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002376 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002377 rsp->result = cpu_to_le16(result);
2378 rsp->flags = cpu_to_le16(0x0000);
2379
2380 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381}
2382
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002383static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002384{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002385 struct l2cap_conf_req *req = data;
2386 void *ptr = req->data;
2387 int type, olen;
2388 unsigned long val;
Mat Martineau36e999a2011-12-08 17:23:21 -08002389 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002390 struct l2cap_conf_efs efs;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002391
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002392 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002393
2394 while (len >= L2CAP_CONF_OPT_SIZE) {
2395 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2396
2397 switch (type) {
2398 case L2CAP_CONF_MTU:
2399 if (val < L2CAP_DEFAULT_MIN_MTU) {
2400 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002401 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002402 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002403 chan->imtu = val;
2404 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002405 break;
2406
2407 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002408 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002409 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002410 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002411 break;
2412
2413 case L2CAP_CONF_RFC:
2414 if (olen == sizeof(rfc))
2415 memcpy(&rfc, (void *)val, olen);
2416
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002417 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002418 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002419 return -ECONNREFUSED;
2420
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002421 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002422
2423 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2424 sizeof(rfc), (unsigned long) &rfc);
2425 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002426
2427 case L2CAP_CONF_EWS:
2428 chan->tx_win = min_t(u16, val,
2429 L2CAP_DEFAULT_EXT_WINDOW);
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002430 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2431 chan->tx_win);
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002432 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002433
2434 case L2CAP_CONF_EFS:
2435 if (olen == sizeof(efs))
2436 memcpy(&efs, (void *)val, olen);
2437
2438 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2439 efs.stype != L2CAP_SERV_NOTRAFIC &&
2440 efs.stype != chan->local_stype)
2441 return -ECONNREFUSED;
2442
2443 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2444 sizeof(efs), (unsigned long) &efs);
2445 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002446 }
2447 }
2448
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002449 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002450 return -ECONNREFUSED;
2451
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002452 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002453
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002454 if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002455 switch (rfc.mode) {
2456 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002457 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2458 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2459 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002460
2461 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2462 chan->local_msdu = le16_to_cpu(efs.msdu);
2463 chan->local_sdu_itime =
2464 le32_to_cpu(efs.sdu_itime);
2465 chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
2466 chan->local_flush_to =
2467 le32_to_cpu(efs.flush_to);
2468 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002469 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002470
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002471 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002472 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002473 }
2474 }
2475
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002476 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002477 req->flags = cpu_to_le16(0x0000);
2478
2479 return ptr - data;
2480}
2481
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002482static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483{
2484 struct l2cap_conf_rsp *rsp = data;
2485 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002487 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002489 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002490 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002491 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492
2493 return ptr - data;
2494}
2495
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002496void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002497{
2498 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002499 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002500 u8 buf[128];
2501
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002502 rsp.scid = cpu_to_le16(chan->dcid);
2503 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002504 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2505 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2506 l2cap_send_cmd(conn, chan->ident,
2507 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2508
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002509 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002510 return;
2511
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002512 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2513 l2cap_build_conf_req(chan, buf), buf);
2514 chan->num_conf_req++;
2515}
2516
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002517static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002518{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002519 int type, olen;
2520 unsigned long val;
2521 struct l2cap_conf_rfc rfc;
2522
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002523 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002524
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002525 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002526 return;
2527
2528 while (len >= L2CAP_CONF_OPT_SIZE) {
2529 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2530
2531 switch (type) {
2532 case L2CAP_CONF_RFC:
2533 if (olen == sizeof(rfc))
2534 memcpy(&rfc, (void *)val, olen);
2535 goto done;
2536 }
2537 }
2538
Mat Martineau36e999a2011-12-08 17:23:21 -08002539 /* Use sane default values in case a misbehaving remote device
2540 * did not send an RFC option.
2541 */
2542 rfc.mode = chan->mode;
2543 rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
2544 rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
2545 rfc.max_pdu_size = cpu_to_le16(chan->imtu);
2546
2547 BT_ERR("Expected RFC option was not found, using defaults");
2548
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002549done:
2550 switch (rfc.mode) {
2551 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002552 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2553 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2554 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002555 break;
2556 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002557 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002558 }
2559}
2560
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002561static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2562{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002563 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002564
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002565 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002566 return 0;
2567
2568 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2569 cmd->ident == conn->info_ident) {
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02002570 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002571
2572 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002573 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002574
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002575 l2cap_conn_start(conn);
2576 }
2577
2578 return 0;
2579}
2580
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2582{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2584 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002585 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002586 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002587 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588
2589 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002590 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591
2592 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2593
2594 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002595 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2596 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597 result = L2CAP_CR_BAD_PSM;
2598 goto sendresp;
2599 }
2600
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002601 parent = pchan->sk;
2602
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002603 lock_sock(parent);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002604
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002605 /* Check if the ACL is secure enough (if not SDP) */
2606 if (psm != cpu_to_le16(0x0001) &&
2607 !hci_conn_check_link_mode(conn->hcon)) {
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002608 conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002609 result = L2CAP_CR_SEC_BLOCK;
2610 goto response;
2611 }
2612
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 result = L2CAP_CR_NO_MEM;
2614
2615 /* Check for backlog size */
2616 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002617 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618 goto response;
2619 }
2620
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002621 chan = pchan->ops->new_connection(pchan->data);
2622 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623 goto response;
2624
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002625 sk = chan->sk;
2626
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002628 if (__l2cap_get_chan_by_dcid(conn, scid)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002630 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631 goto response;
2632 }
2633
2634 hci_conn_hold(conn->hcon);
2635
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 bacpy(&bt_sk(sk)->src, conn->src);
2637 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002638 chan->psm = psm;
2639 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002641 bt_accept_enqueue(parent, sk);
2642
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02002643 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002644
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002645 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002647 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002649 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650
Marcel Holtmann984947d2009-02-06 23:35:19 +01002651 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02002652 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002653 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002654 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002655 result = L2CAP_CR_PEND;
2656 status = L2CAP_CS_AUTHOR_PEND;
2657 parent->sk_data_ready(parent, 0);
2658 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002659 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002660 result = L2CAP_CR_SUCCESS;
2661 status = L2CAP_CS_NO_INFO;
2662 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002663 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002664 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002665 result = L2CAP_CR_PEND;
2666 status = L2CAP_CS_AUTHEN_PEND;
2667 }
2668 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002669 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002670 result = L2CAP_CR_PEND;
2671 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672 }
2673
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674response:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002675 release_sock(parent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676
2677sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002678 rsp.scid = cpu_to_le16(scid);
2679 rsp.dcid = cpu_to_le16(dcid);
2680 rsp.result = cpu_to_le16(result);
2681 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002683
2684 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2685 struct l2cap_info_req info;
2686 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2687
2688 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2689 conn->info_ident = l2cap_get_ident(conn);
2690
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02002691 schedule_delayed_work(&conn->info_timer,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002692 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2693
2694 l2cap_send_cmd(conn, conn->info_ident,
2695 L2CAP_INFO_REQ, sizeof(info), &info);
2696 }
2697
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002698 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002699 result == L2CAP_CR_SUCCESS) {
2700 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002701 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002702 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002703 l2cap_build_conf_req(chan, buf), buf);
2704 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002705 }
2706
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707 return 0;
2708}
2709
2710static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2711{
2712 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2713 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002714 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 struct sock *sk;
2716 u8 req[128];
2717
2718 scid = __le16_to_cpu(rsp->scid);
2719 dcid = __le16_to_cpu(rsp->dcid);
2720 result = __le16_to_cpu(rsp->result);
2721 status = __le16_to_cpu(rsp->status);
2722
2723 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2724
2725 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002726 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002727 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002728 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002730 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002731 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002732 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 }
2734
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002735 sk = chan->sk;
2736
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737 switch (result) {
2738 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002739 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002740 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002741 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002742 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002743
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002744 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002745 break;
2746
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002748 l2cap_build_conf_req(chan, req), req);
2749 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750 break;
2751
2752 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002753 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754 break;
2755
2756 default:
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002757 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758 break;
2759 }
2760
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002761 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 return 0;
2763}
2764
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002765static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002766{
2767 /* FCS is enabled only in ERTM or streaming mode, if one or both
2768 * sides request it.
2769 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002770 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002771 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002772 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002773 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002774}
2775
Al Viro88219a02007-07-29 00:17:25 -07002776static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777{
2778 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2779 u16 dcid, flags;
2780 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002781 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002782 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002783 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784
2785 dcid = __le16_to_cpu(req->dcid);
2786 flags = __le16_to_cpu(req->flags);
2787
2788 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2789
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002790 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002791 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792 return -ENOENT;
2793
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002794 sk = chan->sk;
2795
David S. Miller033b1142011-07-21 13:38:42 -07002796 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002797 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002798
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002799 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2800 rej.scid = cpu_to_le16(chan->scid);
2801 rej.dcid = cpu_to_le16(chan->dcid);
2802
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002803 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2804 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002805 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002806 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002807
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002808 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002809 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002810 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002811 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002812 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002813 L2CAP_CONF_REJECT, flags), rsp);
2814 goto unlock;
2815 }
2816
2817 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002818 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2819 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820
2821 if (flags & 0x0001) {
2822 /* Incomplete config. Send empty response. */
2823 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002824 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002825 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826 goto unlock;
2827 }
2828
2829 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002830 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002831 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002832 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002834 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002836 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002837 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002838
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002839 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002840 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002841
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002842 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002843 goto unlock;
2844
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002845 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002846 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002847
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002848 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002849
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002850 chan->next_tx_seq = 0;
2851 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002852 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002853 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002854 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002855
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02002856 l2cap_chan_ready(chan);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002857 goto unlock;
2858 }
2859
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002860 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002861 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002863 l2cap_build_conf_req(chan, buf), buf);
2864 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865 }
2866
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002867 /* Got Conf Rsp PENDING from remote side and asume we sent
2868 Conf Rsp PENDING in the code above */
2869 if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
2870 test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2871
2872 /* check compatibility */
2873
2874 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2875 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2876
2877 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002878 l2cap_build_conf_rsp(chan, rsp,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002879 L2CAP_CONF_SUCCESS, 0x0000), rsp);
2880 }
2881
Linus Torvalds1da177e2005-04-16 15:20:36 -07002882unlock:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002883 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002884 return 0;
2885}
2886
2887static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2888{
2889 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2890 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002891 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002893 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894
2895 scid = __le16_to_cpu(rsp->scid);
2896 flags = __le16_to_cpu(rsp->flags);
2897 result = __le16_to_cpu(rsp->result);
2898
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002899 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2900 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002902 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002903 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002904 return 0;
2905
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002906 sk = chan->sk;
2907
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908 switch (result) {
2909 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002910 l2cap_conf_rfc_get(chan, rsp->data, len);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002911 clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912 break;
2913
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002914 case L2CAP_CONF_PENDING:
2915 set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
2916
2917 if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2918 char buf[64];
2919
2920 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2921 buf, &result);
2922 if (len < 0) {
2923 l2cap_send_disconn_req(conn, chan, ECONNRESET);
2924 goto done;
2925 }
2926
2927 /* check compatibility */
2928
2929 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2930 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2931
2932 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002933 l2cap_build_conf_rsp(chan, buf,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002934 L2CAP_CONF_SUCCESS, 0x0000), buf);
2935 }
2936 goto done;
2937
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002939 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002940 char req[64];
2941
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002942 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002943 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002944 goto done;
2945 }
2946
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002947 /* throw out any old stored conf requests */
2948 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002949 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2950 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002951 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002952 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002953 goto done;
2954 }
2955
2956 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2957 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002958 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002959 if (result != L2CAP_CONF_SUCCESS)
2960 goto done;
2961 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962 }
2963
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002964 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002965 sk->sk_err = ECONNRESET;
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01002966 __set_chan_timer(chan,
2967 msecs_to_jiffies(L2CAP_DISC_REJ_TIMEOUT));
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002968 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969 goto done;
2970 }
2971
2972 if (flags & 0x01)
2973 goto done;
2974
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002975 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002977 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002978 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002979
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002980 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002981 chan->next_tx_seq = 0;
2982 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002983 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002984 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002985 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002986
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02002987 l2cap_chan_ready(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988 }
2989
2990done:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002991 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002992 return 0;
2993}
2994
2995static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2996{
2997 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2998 struct l2cap_disconn_rsp rsp;
2999 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003000 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001 struct sock *sk;
3002
3003 scid = __le16_to_cpu(req->scid);
3004 dcid = __le16_to_cpu(req->dcid);
3005
3006 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3007
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003008 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003009 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010 return 0;
3011
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003012 sk = chan->sk;
3013
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003014 rsp.dcid = cpu_to_le16(chan->scid);
3015 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3017
3018 sk->sk_shutdown = SHUTDOWN_MASK;
3019
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003020 l2cap_chan_del(chan, ECONNRESET);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003021 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003023 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024 return 0;
3025}
3026
3027static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3028{
3029 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3030 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003031 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032 struct sock *sk;
3033
3034 scid = __le16_to_cpu(rsp->scid);
3035 dcid = __le16_to_cpu(rsp->dcid);
3036
3037 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3038
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003039 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003040 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041 return 0;
3042
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003043 sk = chan->sk;
3044
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003045 l2cap_chan_del(chan, 0);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003046 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003048 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003049 return 0;
3050}
3051
3052static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3053{
3054 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055 u16 type;
3056
3057 type = __le16_to_cpu(req->type);
3058
3059 BT_DBG("type 0x%4.4x", type);
3060
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003061 if (type == L2CAP_IT_FEAT_MASK) {
3062 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003063 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003064 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3065 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3066 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003067 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003068 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3069 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003070 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003071 feat_mask |= L2CAP_FEAT_EXT_FLOW
3072 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003073
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003074 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003075 l2cap_send_cmd(conn, cmd->ident,
3076 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003077 } else if (type == L2CAP_IT_FIXED_CHAN) {
3078 u8 buf[12];
3079 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
Mat Martineau50a147c2011-11-02 16:18:34 -07003080
3081 if (enable_hs)
3082 l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
3083 else
3084 l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
3085
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003086 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3087 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003088 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003089 l2cap_send_cmd(conn, cmd->ident,
3090 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003091 } else {
3092 struct l2cap_info_rsp rsp;
3093 rsp.type = cpu_to_le16(type);
3094 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3095 l2cap_send_cmd(conn, cmd->ident,
3096 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3097 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098
3099 return 0;
3100}
3101
3102static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3103{
3104 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3105 u16 type, result;
3106
3107 type = __le16_to_cpu(rsp->type);
3108 result = __le16_to_cpu(rsp->result);
3109
3110 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3111
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003112 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3113 if (cmd->ident != conn->info_ident ||
3114 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3115 return 0;
3116
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02003117 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003118
Ville Tervoadb08ed2010-08-04 09:43:33 +03003119 if (result != L2CAP_IR_SUCCESS) {
3120 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3121 conn->info_ident = 0;
3122
3123 l2cap_conn_start(conn);
3124
3125 return 0;
3126 }
3127
Marcel Holtmann984947d2009-02-06 23:35:19 +01003128 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003129 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003130
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003131 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003132 struct l2cap_info_req req;
3133 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3134
3135 conn->info_ident = l2cap_get_ident(conn);
3136
3137 l2cap_send_cmd(conn, conn->info_ident,
3138 L2CAP_INFO_REQ, sizeof(req), &req);
3139 } else {
3140 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3141 conn->info_ident = 0;
3142
3143 l2cap_conn_start(conn);
3144 }
3145 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003146 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003147 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003148
3149 l2cap_conn_start(conn);
3150 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003151
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152 return 0;
3153}
3154
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003155static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3156 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3157 void *data)
3158{
3159 struct l2cap_create_chan_req *req = data;
3160 struct l2cap_create_chan_rsp rsp;
3161 u16 psm, scid;
3162
3163 if (cmd_len != sizeof(*req))
3164 return -EPROTO;
3165
3166 if (!enable_hs)
3167 return -EINVAL;
3168
3169 psm = le16_to_cpu(req->psm);
3170 scid = le16_to_cpu(req->scid);
3171
3172 BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3173
3174 /* Placeholder: Always reject */
3175 rsp.dcid = 0;
3176 rsp.scid = cpu_to_le16(scid);
3177 rsp.result = L2CAP_CR_NO_MEM;
3178 rsp.status = L2CAP_CS_NO_INFO;
3179
3180 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3181 sizeof(rsp), &rsp);
3182
3183 return 0;
3184}
3185
3186static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3187 struct l2cap_cmd_hdr *cmd, void *data)
3188{
3189 BT_DBG("conn %p", conn);
3190
3191 return l2cap_connect_rsp(conn, cmd, data);
3192}
3193
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003194static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
3195 u16 icid, u16 result)
3196{
3197 struct l2cap_move_chan_rsp rsp;
3198
3199 BT_DBG("icid %d, result %d", icid, result);
3200
3201 rsp.icid = cpu_to_le16(icid);
3202 rsp.result = cpu_to_le16(result);
3203
3204 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
3205}
3206
3207static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
3208 struct l2cap_chan *chan, u16 icid, u16 result)
3209{
3210 struct l2cap_move_chan_cfm cfm;
3211 u8 ident;
3212
3213 BT_DBG("icid %d, result %d", icid, result);
3214
3215 ident = l2cap_get_ident(conn);
3216 if (chan)
3217 chan->ident = ident;
3218
3219 cfm.icid = cpu_to_le16(icid);
3220 cfm.result = cpu_to_le16(result);
3221
3222 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
3223}
3224
3225static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
3226 u16 icid)
3227{
3228 struct l2cap_move_chan_cfm_rsp rsp;
3229
3230 BT_DBG("icid %d", icid);
3231
3232 rsp.icid = cpu_to_le16(icid);
3233 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
3234}
3235
3236static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
3237 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3238{
3239 struct l2cap_move_chan_req *req = data;
3240 u16 icid = 0;
3241 u16 result = L2CAP_MR_NOT_ALLOWED;
3242
3243 if (cmd_len != sizeof(*req))
3244 return -EPROTO;
3245
3246 icid = le16_to_cpu(req->icid);
3247
3248 BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
3249
3250 if (!enable_hs)
3251 return -EINVAL;
3252
3253 /* Placeholder: Always refuse */
3254 l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
3255
3256 return 0;
3257}
3258
3259static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
3260 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3261{
3262 struct l2cap_move_chan_rsp *rsp = data;
3263 u16 icid, result;
3264
3265 if (cmd_len != sizeof(*rsp))
3266 return -EPROTO;
3267
3268 icid = le16_to_cpu(rsp->icid);
3269 result = le16_to_cpu(rsp->result);
3270
3271 BT_DBG("icid %d, result %d", icid, result);
3272
3273 /* Placeholder: Always unconfirmed */
3274 l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
3275
3276 return 0;
3277}
3278
3279static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
3280 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3281{
3282 struct l2cap_move_chan_cfm *cfm = data;
3283 u16 icid, result;
3284
3285 if (cmd_len != sizeof(*cfm))
3286 return -EPROTO;
3287
3288 icid = le16_to_cpu(cfm->icid);
3289 result = le16_to_cpu(cfm->result);
3290
3291 BT_DBG("icid %d, result %d", icid, result);
3292
3293 l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
3294
3295 return 0;
3296}
3297
3298static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
3299 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3300{
3301 struct l2cap_move_chan_cfm_rsp *rsp = data;
3302 u16 icid;
3303
3304 if (cmd_len != sizeof(*rsp))
3305 return -EPROTO;
3306
3307 icid = le16_to_cpu(rsp->icid);
3308
3309 BT_DBG("icid %d", icid);
3310
3311 return 0;
3312}
3313
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003314static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02003315 u16 to_multiplier)
3316{
3317 u16 max_latency;
3318
3319 if (min > max || min < 6 || max > 3200)
3320 return -EINVAL;
3321
3322 if (to_multiplier < 10 || to_multiplier > 3200)
3323 return -EINVAL;
3324
3325 if (max >= to_multiplier * 8)
3326 return -EINVAL;
3327
3328 max_latency = (to_multiplier * 8 / max) - 1;
3329 if (latency > 499 || latency > max_latency)
3330 return -EINVAL;
3331
3332 return 0;
3333}
3334
3335static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3336 struct l2cap_cmd_hdr *cmd, u8 *data)
3337{
3338 struct hci_conn *hcon = conn->hcon;
3339 struct l2cap_conn_param_update_req *req;
3340 struct l2cap_conn_param_update_rsp rsp;
3341 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003342 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02003343
3344 if (!(hcon->link_mode & HCI_LM_MASTER))
3345 return -EINVAL;
3346
3347 cmd_len = __le16_to_cpu(cmd->len);
3348 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3349 return -EPROTO;
3350
3351 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003352 min = __le16_to_cpu(req->min);
3353 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02003354 latency = __le16_to_cpu(req->latency);
3355 to_multiplier = __le16_to_cpu(req->to_multiplier);
3356
3357 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3358 min, max, latency, to_multiplier);
3359
3360 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003361
3362 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
3363 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02003364 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3365 else
3366 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3367
3368 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3369 sizeof(rsp), &rsp);
3370
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003371 if (!err)
3372 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
3373
Claudio Takahaside731152011-02-11 19:28:55 -02003374 return 0;
3375}
3376
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003377static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
3378 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
3379{
3380 int err = 0;
3381
3382 switch (cmd->code) {
3383 case L2CAP_COMMAND_REJ:
3384 l2cap_command_rej(conn, cmd, data);
3385 break;
3386
3387 case L2CAP_CONN_REQ:
3388 err = l2cap_connect_req(conn, cmd, data);
3389 break;
3390
3391 case L2CAP_CONN_RSP:
3392 err = l2cap_connect_rsp(conn, cmd, data);
3393 break;
3394
3395 case L2CAP_CONF_REQ:
3396 err = l2cap_config_req(conn, cmd, cmd_len, data);
3397 break;
3398
3399 case L2CAP_CONF_RSP:
3400 err = l2cap_config_rsp(conn, cmd, data);
3401 break;
3402
3403 case L2CAP_DISCONN_REQ:
3404 err = l2cap_disconnect_req(conn, cmd, data);
3405 break;
3406
3407 case L2CAP_DISCONN_RSP:
3408 err = l2cap_disconnect_rsp(conn, cmd, data);
3409 break;
3410
3411 case L2CAP_ECHO_REQ:
3412 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3413 break;
3414
3415 case L2CAP_ECHO_RSP:
3416 break;
3417
3418 case L2CAP_INFO_REQ:
3419 err = l2cap_information_req(conn, cmd, data);
3420 break;
3421
3422 case L2CAP_INFO_RSP:
3423 err = l2cap_information_rsp(conn, cmd, data);
3424 break;
3425
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003426 case L2CAP_CREATE_CHAN_REQ:
3427 err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3428 break;
3429
3430 case L2CAP_CREATE_CHAN_RSP:
3431 err = l2cap_create_channel_rsp(conn, cmd, data);
3432 break;
3433
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003434 case L2CAP_MOVE_CHAN_REQ:
3435 err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
3436 break;
3437
3438 case L2CAP_MOVE_CHAN_RSP:
3439 err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
3440 break;
3441
3442 case L2CAP_MOVE_CHAN_CFM:
3443 err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
3444 break;
3445
3446 case L2CAP_MOVE_CHAN_CFM_RSP:
3447 err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
3448 break;
3449
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003450 default:
3451 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3452 err = -EINVAL;
3453 break;
3454 }
3455
3456 return err;
3457}
3458
3459static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3460 struct l2cap_cmd_hdr *cmd, u8 *data)
3461{
3462 switch (cmd->code) {
3463 case L2CAP_COMMAND_REJ:
3464 return 0;
3465
3466 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003467 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003468
3469 case L2CAP_CONN_PARAM_UPDATE_RSP:
3470 return 0;
3471
3472 default:
3473 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3474 return -EINVAL;
3475 }
3476}
3477
3478static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3479 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003480{
3481 u8 *data = skb->data;
3482 int len = skb->len;
3483 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003484 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003485
3486 l2cap_raw_recv(conn, skb);
3487
3488 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003489 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003490 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3491 data += L2CAP_CMD_HDR_SIZE;
3492 len -= L2CAP_CMD_HDR_SIZE;
3493
Al Viro88219a02007-07-29 00:17:25 -07003494 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003495
Al Viro88219a02007-07-29 00:17:25 -07003496 BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003497
Al Viro88219a02007-07-29 00:17:25 -07003498 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003499 BT_DBG("corrupted command");
3500 break;
3501 }
3502
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003503 if (conn->hcon->type == LE_LINK)
3504 err = l2cap_le_sig_cmd(conn, &cmd, data);
3505 else
3506 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507
3508 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003509 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003510
3511 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512
3513 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003514 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003515 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3516 }
3517
Al Viro88219a02007-07-29 00:17:25 -07003518 data += cmd_len;
3519 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520 }
3521
3522 kfree_skb(skb);
3523}
3524
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003525static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003526{
3527 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003528 int hdr_size;
3529
3530 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3531 hdr_size = L2CAP_EXT_HDR_SIZE;
3532 else
3533 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003534
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003535 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003536 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003537 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3538 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3539
3540 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003541 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003542 }
3543 return 0;
3544}
3545
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003546static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003547{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003548 u32 control = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003549
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003550 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003551
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003552 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003553
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003554 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003555 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003556 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003557 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003558 }
3559
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003560 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003561 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003562
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003563 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003564
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003565 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003566 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003567 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003568 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003569 }
3570}
3571
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003572static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u16 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003573{
3574 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003575 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003576
3577 bt_cb(skb)->tx_seq = tx_seq;
3578 bt_cb(skb)->sar = sar;
3579
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003580 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003581
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003582 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003583
Szymon Janc039d9572011-11-16 09:32:19 +01003584 while (next_skb) {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003585 if (bt_cb(next_skb)->tx_seq == tx_seq)
3586 return -EINVAL;
3587
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003588 next_tx_seq_offset = __seq_offset(chan,
3589 bt_cb(next_skb)->tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003590
3591 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003592 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003593 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003594 }
3595
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003596 if (skb_queue_is_last(&chan->srej_q, next_skb))
Szymon Janc039d9572011-11-16 09:32:19 +01003597 next_skb = NULL;
3598 else
3599 next_skb = skb_queue_next(&chan->srej_q, next_skb);
3600 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003601
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003602 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003603
3604 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003605}
3606
Mat Martineau84084a32011-07-22 14:54:00 -07003607static void append_skb_frag(struct sk_buff *skb,
3608 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003609{
Mat Martineau84084a32011-07-22 14:54:00 -07003610 /* skb->len reflects data in skb as well as all fragments
3611 * skb->data_len reflects only data in fragments
3612 */
3613 if (!skb_has_frag_list(skb))
3614 skb_shinfo(skb)->frag_list = new_frag;
3615
3616 new_frag->next = NULL;
3617
3618 (*last_frag)->next = new_frag;
3619 *last_frag = new_frag;
3620
3621 skb->len += new_frag->len;
3622 skb->data_len += new_frag->len;
3623 skb->truesize += new_frag->truesize;
3624}
3625
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003626static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
Mat Martineau84084a32011-07-22 14:54:00 -07003627{
3628 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003629
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003630 switch (__get_ctrl_sar(chan, control)) {
3631 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003632 if (chan->sdu)
3633 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003634
Mat Martineau84084a32011-07-22 14:54:00 -07003635 err = chan->ops->recv(chan->data, skb);
3636 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003637
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003638 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003639 if (chan->sdu)
3640 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003641
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003642 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003643 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003644
Mat Martineau84084a32011-07-22 14:54:00 -07003645 if (chan->sdu_len > chan->imtu) {
3646 err = -EMSGSIZE;
3647 break;
3648 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003649
Mat Martineau84084a32011-07-22 14:54:00 -07003650 if (skb->len >= chan->sdu_len)
3651 break;
3652
3653 chan->sdu = skb;
3654 chan->sdu_last_frag = skb;
3655
3656 skb = NULL;
3657 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003658 break;
3659
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003660 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003661 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003662 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003663
Mat Martineau84084a32011-07-22 14:54:00 -07003664 append_skb_frag(chan->sdu, skb,
3665 &chan->sdu_last_frag);
3666 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003667
Mat Martineau84084a32011-07-22 14:54:00 -07003668 if (chan->sdu->len >= chan->sdu_len)
3669 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003670
Mat Martineau84084a32011-07-22 14:54:00 -07003671 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003672 break;
3673
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003674 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003675 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003676 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003677
Mat Martineau84084a32011-07-22 14:54:00 -07003678 append_skb_frag(chan->sdu, skb,
3679 &chan->sdu_last_frag);
3680 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003681
Mat Martineau84084a32011-07-22 14:54:00 -07003682 if (chan->sdu->len != chan->sdu_len)
3683 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003684
Mat Martineau84084a32011-07-22 14:54:00 -07003685 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003686
Mat Martineau84084a32011-07-22 14:54:00 -07003687 if (!err) {
3688 /* Reassembly complete */
3689 chan->sdu = NULL;
3690 chan->sdu_last_frag = NULL;
3691 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003692 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003693 break;
3694 }
3695
Mat Martineau84084a32011-07-22 14:54:00 -07003696 if (err) {
3697 kfree_skb(skb);
3698 kfree_skb(chan->sdu);
3699 chan->sdu = NULL;
3700 chan->sdu_last_frag = NULL;
3701 chan->sdu_len = 0;
3702 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003703
Mat Martineau84084a32011-07-22 14:54:00 -07003704 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003705}
3706
Mat Martineau26f880d2011-07-07 09:39:01 -07003707static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003708{
Mat Martineau26f880d2011-07-07 09:39:01 -07003709 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003710
Mat Martineau26f880d2011-07-07 09:39:01 -07003711 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3712
Szymon Janc77f918b2012-01-11 10:59:48 +01003713 __set_ack_timer(chan);
Mat Martineau26f880d2011-07-07 09:39:01 -07003714}
3715
3716static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3717{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003718 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003719
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003720 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003721 goto done;
3722
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003723 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003724 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003725 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003726 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003727 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003728
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003729 __clear_retrans_timer(chan);
3730 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003731
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003732 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003733
3734done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003735 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3736 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003737
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003738 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003739}
3740
Mat Martineaue3281402011-07-07 09:39:02 -07003741void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003742{
Mat Martineaue3281402011-07-07 09:39:02 -07003743 if (chan->mode == L2CAP_MODE_ERTM) {
3744 if (busy)
3745 l2cap_ertm_enter_local_busy(chan);
3746 else
3747 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003748 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003749}
3750
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003751static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003752{
3753 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003754 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003755
Mat Martineaue3281402011-07-07 09:39:02 -07003756 while ((skb = skb_peek(&chan->srej_q)) &&
3757 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3758 int err;
3759
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003760 if (bt_cb(skb)->tx_seq != tx_seq)
3761 break;
3762
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003763 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003764 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003765 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003766
3767 if (err < 0) {
3768 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3769 break;
3770 }
3771
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003772 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
3773 tx_seq = __next_seq(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003774 }
3775}
3776
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003777static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003778{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003779 struct srej_list *l, *tmp;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003780 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003781
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003782 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003783 if (l->tx_seq == tx_seq) {
3784 list_del(&l->list);
3785 kfree(l);
3786 return;
3787 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003788 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003789 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003790 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003791 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003792 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003793 }
3794}
3795
Szymon Jancaef89f22011-11-16 09:32:18 +01003796static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003797{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003798 struct srej_list *new;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003799 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003800
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003801 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003802 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003803 control |= __set_reqseq(chan, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003804 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003805
3806 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Szymon Jancaef89f22011-11-16 09:32:18 +01003807 if (!new)
3808 return -ENOMEM;
3809
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003810 new->tx_seq = chan->expected_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003811
3812 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
3813
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003814 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003815 }
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003816
3817 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Szymon Jancaef89f22011-11-16 09:32:18 +01003818
3819 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003820}
3821
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003822static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003823{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003824 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003825 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003826 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003827 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003828 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003829 int err = 0;
3830
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003831 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%8.8x", chan, skb->len,
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003832 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003833
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003834 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003835 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003836 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003837 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003838 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003839 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003840 }
3841
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003842 chan->expected_ack_seq = req_seq;
3843 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003844
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003845 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003846
3847 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003848 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003849 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003850 goto drop;
3851 }
3852
Szymon Janc77f918b2012-01-11 10:59:48 +01003853 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3854 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
3855 l2cap_send_ack(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003856 goto drop;
Szymon Janc77f918b2012-01-11 10:59:48 +01003857 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003858
Mat Martineau02f1b642011-06-29 14:35:19 -07003859 if (tx_seq == chan->expected_tx_seq)
3860 goto expected;
3861
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003862 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003863 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003864
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003865 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003866 struct srej_list, list);
3867 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003868 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003869 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003870
3871 list_del(&first->list);
3872 kfree(first);
3873
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003874 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003875 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003876 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003877 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003878 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003879 }
3880 } else {
3881 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003882
3883 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003884 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003885 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003886
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003887 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003888 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003889 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003890 return 0;
3891 }
3892 }
Szymon Jancaef89f22011-11-16 09:32:18 +01003893
3894 err = l2cap_send_srejframe(chan, tx_seq);
3895 if (err < 0) {
3896 l2cap_send_disconn_req(chan->conn, chan, -err);
3897 return err;
3898 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003899 }
3900 } else {
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003901 expected_tx_seq_offset = __seq_offset(chan,
3902 chan->expected_tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003903
3904 /* duplicated tx_seq */
3905 if (tx_seq_offset < expected_tx_seq_offset)
3906 goto drop;
3907
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003908 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003909
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003910 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003911
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003912 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003913 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003914
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003915 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003916 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003917
Szymon Janc0ef3ef02012-01-11 10:59:46 +01003918 /* Set P-bit only if there are some I-frames to ack. */
3919 if (__clear_ack_timer(chan))
3920 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003921
Szymon Jancaef89f22011-11-16 09:32:18 +01003922 err = l2cap_send_srejframe(chan, tx_seq);
3923 if (err < 0) {
3924 l2cap_send_disconn_req(chan->conn, chan, -err);
3925 return err;
3926 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003927 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003928 return 0;
3929
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003930expected:
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003931 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003932
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003933 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003934 bt_cb(skb)->tx_seq = tx_seq;
3935 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003936 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003937 return 0;
3938 }
3939
Mat Martineau84084a32011-07-22 14:54:00 -07003940 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003941 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
3942
Mat Martineaue3281402011-07-07 09:39:02 -07003943 if (err < 0) {
3944 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3945 return err;
3946 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003947
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003948 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003949 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003950 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003951 }
3952
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003953
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003954 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3955 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003956 l2cap_send_ack(chan);
Gustavo F. Padovan4d611e42011-06-23 19:30:48 -03003957 else
3958 __set_ack_timer(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003959
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003960 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003961
3962drop:
3963 kfree_skb(skb);
3964 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003965}
3966
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003967static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003968{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003969 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003970 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003971
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003972 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003973 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003974
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003975 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003976 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3977 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3978 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003979 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003980 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003981
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003982 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003983 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003984 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003985 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003986 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003987
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003988 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003989 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003990
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003991 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003992 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003993
3994 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003995 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003996 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003997 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003998
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003999 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4000 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004001 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02004002 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004003 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004004 }
4005}
4006
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004007static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004008{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004009 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004010
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004011 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004012
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004013 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004014
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004015 chan->expected_ack_seq = tx_seq;
4016 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004017
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004018 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004019 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004020 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004021 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004022 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004023
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004024 if (test_bit(CONN_WAIT_F, &chan->conn_state))
4025 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004026 }
4027}
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004028static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004029{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004030 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004031
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004032 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004033
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004034 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004035
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004036 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004037 chan->expected_ack_seq = tx_seq;
4038 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004039
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004040 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004041 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004042
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004043 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004044
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004045 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004046 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004047 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004048 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004049 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004050 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004051 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004052 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004053 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004054 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004055 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004056 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004057 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004058 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004059 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004060 }
4061 }
4062}
4063
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004064static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004065{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004066 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004067
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004068 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004069
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004070 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004071 chan->expected_ack_seq = tx_seq;
4072 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004073
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004074 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004075 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004076
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004077 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004078 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004079 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004080 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004081 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004082 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004083
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004084 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004085 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004086 } else {
4087 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4088 l2cap_send_sframe(chan, rx_control);
4089 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004090}
4091
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004092static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004093{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004094 BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004095
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004096 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004097 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004098 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004099 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004100 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004101 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004102 }
4103
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004104 switch (__get_ctrl_super(chan, rx_control)) {
4105 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004106 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004107 break;
4108
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004109 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004110 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004111 break;
4112
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004113 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004114 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004115 break;
4116
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004117 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004118 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004119 break;
4120 }
4121
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004122 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004123 return 0;
4124}
4125
Szymon Janccad8f1d02012-01-23 10:06:05 +01004126static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004127{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004128 u32 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004129 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004130 int len, next_tx_seq_offset, req_seq_offset;
4131
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004132 control = __get_control(chan, skb->data);
4133 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004134 len = skb->len;
4135
4136 /*
4137 * We can just drop the corrupted I-frame here.
4138 * Receiver will miss it and start proper recovery
4139 * procedures and ask retransmission.
4140 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004141 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004142 goto drop;
4143
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004144 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004145 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004146
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004147 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004148 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004149
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004150 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004151 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004152 goto drop;
4153 }
4154
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004155 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004156
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004157 req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4158
4159 next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4160 chan->expected_ack_seq);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004161
4162 /* check for invalid req-seq */
4163 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004164 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004165 goto drop;
4166 }
4167
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004168 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004169 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004170 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004171 goto drop;
4172 }
4173
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004174 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004175 } else {
4176 if (len != 0) {
4177 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004178 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004179 goto drop;
4180 }
4181
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004182 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004183 }
4184
4185 return 0;
4186
4187drop:
4188 kfree_skb(skb);
4189 return 0;
4190}
4191
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4193{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004194 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07004195 struct sock *sk = NULL;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004196 u32 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004197 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004198 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004200 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004201 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202 BT_DBG("unknown cid 0x%4.4x", cid);
4203 goto drop;
4204 }
4205
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004206 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004207
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004208 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004210 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004211 goto drop;
4212
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004213 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004214 case L2CAP_MODE_BASIC:
4215 /* If socket recv buffers overflows we drop data here
4216 * which is *bad* because L2CAP has to be reliable.
4217 * But we don't have any other choice. L2CAP doesn't
4218 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004219
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004220 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004221 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004223 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004224 goto done;
4225 break;
4226
4227 case L2CAP_MODE_ERTM:
Andrei Emeltchenko5ef8cb92012-01-13 17:21:42 +02004228 l2cap_ertm_data_rcv(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004229
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004230 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004231
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004232 case L2CAP_MODE_STREAMING:
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004233 control = __get_control(chan, skb->data);
4234 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004235 len = skb->len;
4236
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004237 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004238 goto drop;
4239
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004240 if (__is_sar_start(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004241 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004242
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004243 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004244 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004245
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004246 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004247 goto drop;
4248
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004249 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004250
Mat Martineau84084a32011-07-22 14:54:00 -07004251 if (chan->expected_tx_seq != tx_seq) {
4252 /* Frame(s) missing - must discard partial SDU */
4253 kfree_skb(chan->sdu);
4254 chan->sdu = NULL;
4255 chan->sdu_last_frag = NULL;
4256 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004257
Mat Martineau84084a32011-07-22 14:54:00 -07004258 /* TODO: Notify userland of missing data */
4259 }
4260
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004261 chan->expected_tx_seq = __next_seq(chan, tx_seq);
Mat Martineau84084a32011-07-22 14:54:00 -07004262
4263 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
4264 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004265
4266 goto done;
4267
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004268 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004269 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004270 break;
4271 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004272
4273drop:
4274 kfree_skb(skb);
4275
4276done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004277 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004278 release_sock(sk);
Marcel Holtmann01394182006-07-03 10:02:46 +02004279
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280 return 0;
4281}
4282
Al Viro8e036fc2007-07-29 00:16:36 -07004283static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004284{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004285 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004286 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004287
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004288 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
4289 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004290 goto drop;
4291
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004292 sk = chan->sk;
4293
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004294 lock_sock(sk);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00004295
Linus Torvalds1da177e2005-04-16 15:20:36 -07004296 BT_DBG("sk %p, len %d", sk, skb->len);
4297
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004298 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299 goto drop;
4300
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004301 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004302 goto drop;
4303
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004304 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305 goto done;
4306
4307drop:
4308 kfree_skb(skb);
4309
4310done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004311 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004312 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004313 return 0;
4314}
4315
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004316static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
4317{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004318 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004319 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004320
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004321 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
4322 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004323 goto drop;
4324
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004325 sk = chan->sk;
4326
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004327 lock_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004328
4329 BT_DBG("sk %p, len %d", sk, skb->len);
4330
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004331 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004332 goto drop;
4333
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004334 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004335 goto drop;
4336
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004337 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004338 goto done;
4339
4340drop:
4341 kfree_skb(skb);
4342
4343done:
4344 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004345 release_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004346 return 0;
4347}
4348
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4350{
4351 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004352 u16 cid, len;
4353 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354
4355 skb_pull(skb, L2CAP_HDR_SIZE);
4356 cid = __le16_to_cpu(lh->cid);
4357 len = __le16_to_cpu(lh->len);
4358
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004359 if (len != skb->len) {
4360 kfree_skb(skb);
4361 return;
4362 }
4363
Linus Torvalds1da177e2005-04-16 15:20:36 -07004364 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4365
4366 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004367 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004368 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369 l2cap_sig_channel(conn, skb);
4370 break;
4371
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004372 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004373 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374 skb_pull(skb, 2);
4375 l2cap_conless_channel(conn, psm, skb);
4376 break;
4377
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004378 case L2CAP_CID_LE_DATA:
4379 l2cap_att_channel(conn, cid, skb);
4380 break;
4381
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004382 case L2CAP_CID_SMP:
4383 if (smp_sig_channel(conn, skb))
4384 l2cap_conn_del(conn->hcon, EACCES);
4385 break;
4386
Linus Torvalds1da177e2005-04-16 15:20:36 -07004387 default:
4388 l2cap_data_channel(conn, cid, skb);
4389 break;
4390 }
4391}
4392
4393/* ---- L2CAP interface with lower layer (HCI) ---- */
4394
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004395int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396{
4397 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004398 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004399
Linus Torvalds1da177e2005-04-16 15:20:36 -07004400 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4401
4402 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004403 read_lock(&chan_list_lock);
4404 list_for_each_entry(c, &chan_list, global_l) {
4405 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004406
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004407 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004408 continue;
4409
4410 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004411 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004412 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004413 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004415 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4416 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004417 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004418 lm2 |= HCI_LM_MASTER;
4419 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004421 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422
4423 return exact ? lm1 : lm2;
4424}
4425
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004426int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427{
Marcel Holtmann01394182006-07-03 10:02:46 +02004428 struct l2cap_conn *conn;
4429
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4431
Linus Torvalds1da177e2005-04-16 15:20:36 -07004432 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004433 conn = l2cap_conn_add(hcon, status);
4434 if (conn)
4435 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004436 } else
Joe Perchese1750722011-06-29 18:18:29 -07004437 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438
4439 return 0;
4440}
4441
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004442int l2cap_disconn_ind(struct hci_conn *hcon)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004443{
4444 struct l2cap_conn *conn = hcon->l2cap_data;
4445
4446 BT_DBG("hcon %p", hcon);
4447
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004448 if (!conn)
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02004449 return HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01004450 return conn->disc_reason;
4451}
4452
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004453int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454{
4455 BT_DBG("hcon %p reason %d", hcon, reason);
4456
Joe Perchese1750722011-06-29 18:18:29 -07004457 l2cap_conn_del(hcon, bt_to_errno(reason));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004458 return 0;
4459}
4460
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004461static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004462{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004463 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004464 return;
4465
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004466 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004467 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004468 __clear_chan_timer(chan);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004469 __set_chan_timer(chan,
4470 msecs_to_jiffies(L2CAP_ENC_TIMEOUT));
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004471 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004472 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004473 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004474 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004475 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004476 }
4477}
4478
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004479int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004480{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004481 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004482 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004483
Marcel Holtmann01394182006-07-03 10:02:46 +02004484 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004485 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004486
Linus Torvalds1da177e2005-04-16 15:20:36 -07004487 BT_DBG("conn %p", conn);
4488
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004489 if (hcon->type == LE_LINK) {
4490 smp_distribute_keys(conn, 0);
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02004491 cancel_delayed_work(&conn->security_timer);
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004492 }
4493
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02004494 rcu_read_lock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004495
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02004496 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004497 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004498
Linus Torvalds1da177e2005-04-16 15:20:36 -07004499 bh_lock_sock(sk);
4500
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004501 BT_DBG("chan->scid %d", chan->scid);
4502
4503 if (chan->scid == L2CAP_CID_LE_DATA) {
4504 if (!status && encrypt) {
4505 chan->sec_level = hcon->sec_level;
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02004506 l2cap_chan_ready(chan);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004507 }
4508
4509 bh_unlock_sock(sk);
4510 continue;
4511 }
4512
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004513 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004514 bh_unlock_sock(sk);
4515 continue;
4516 }
4517
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004518 if (!status && (chan->state == BT_CONNECTED ||
4519 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004520 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004521 bh_unlock_sock(sk);
4522 continue;
4523 }
4524
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004525 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004526 if (!status) {
4527 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004528 req.scid = cpu_to_le16(chan->scid);
4529 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004530
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004531 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004532 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004533
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004534 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004535 L2CAP_CONN_REQ, sizeof(req), &req);
4536 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004537 __clear_chan_timer(chan);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004538 __set_chan_timer(chan,
4539 msecs_to_jiffies(L2CAP_DISC_TIMEOUT));
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004540 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004541 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004542 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004543 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004544
4545 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004546 if (bt_sk(sk)->defer_setup) {
4547 struct sock *parent = bt_sk(sk)->parent;
4548 res = L2CAP_CR_PEND;
4549 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004550 if (parent)
4551 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004552 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004553 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004554 res = L2CAP_CR_SUCCESS;
4555 stat = L2CAP_CS_NO_INFO;
4556 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004557 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004558 l2cap_state_change(chan, BT_DISCONN);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004559 __set_chan_timer(chan,
4560 msecs_to_jiffies(L2CAP_DISC_TIMEOUT));
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004561 res = L2CAP_CR_SEC_BLOCK;
4562 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004563 }
4564
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004565 rsp.scid = cpu_to_le16(chan->dcid);
4566 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004567 rsp.result = cpu_to_le16(res);
4568 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004569 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4570 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004571 }
4572
Linus Torvalds1da177e2005-04-16 15:20:36 -07004573 bh_unlock_sock(sk);
4574 }
4575
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02004576 rcu_read_unlock();
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004577
Linus Torvalds1da177e2005-04-16 15:20:36 -07004578 return 0;
4579}
4580
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004581int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004582{
4583 struct l2cap_conn *conn = hcon->l2cap_data;
4584
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004585 if (!conn)
4586 conn = l2cap_conn_add(hcon, 0);
4587
4588 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004589 goto drop;
4590
4591 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4592
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004593 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004594 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004595 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004596 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004597 int len;
4598
4599 if (conn->rx_len) {
4600 BT_ERR("Unexpected start frame (len %d)", skb->len);
4601 kfree_skb(conn->rx_skb);
4602 conn->rx_skb = NULL;
4603 conn->rx_len = 0;
4604 l2cap_conn_unreliable(conn, ECOMM);
4605 }
4606
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004607 /* Start fragment always begin with Basic L2CAP header */
4608 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004609 BT_ERR("Frame is too short (len %d)", skb->len);
4610 l2cap_conn_unreliable(conn, ECOMM);
4611 goto drop;
4612 }
4613
4614 hdr = (struct l2cap_hdr *) skb->data;
4615 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004616 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004617
4618 if (len == skb->len) {
4619 /* Complete frame received */
4620 l2cap_recv_frame(conn, skb);
4621 return 0;
4622 }
4623
4624 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4625
4626 if (skb->len > len) {
4627 BT_ERR("Frame is too long (len %d, expected len %d)",
4628 skb->len, len);
4629 l2cap_conn_unreliable(conn, ECOMM);
4630 goto drop;
4631 }
4632
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004633 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004634
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004635 if (chan && chan->sk) {
4636 struct sock *sk = chan->sk;
4637
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004638 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004639 BT_ERR("Frame exceeding recv MTU (len %d, "
4640 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004641 chan->imtu);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004642 release_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004643 l2cap_conn_unreliable(conn, ECOMM);
4644 goto drop;
4645 }
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004646 release_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004647 }
4648
Linus Torvalds1da177e2005-04-16 15:20:36 -07004649 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004650 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4651 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004652 goto drop;
4653
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004654 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004655 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004656 conn->rx_len = len - skb->len;
4657 } else {
4658 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4659
4660 if (!conn->rx_len) {
4661 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4662 l2cap_conn_unreliable(conn, ECOMM);
4663 goto drop;
4664 }
4665
4666 if (skb->len > conn->rx_len) {
4667 BT_ERR("Fragment is too long (len %d, expected %d)",
4668 skb->len, conn->rx_len);
4669 kfree_skb(conn->rx_skb);
4670 conn->rx_skb = NULL;
4671 conn->rx_len = 0;
4672 l2cap_conn_unreliable(conn, ECOMM);
4673 goto drop;
4674 }
4675
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004676 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004677 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004678 conn->rx_len -= skb->len;
4679
4680 if (!conn->rx_len) {
4681 /* Complete frame received */
4682 l2cap_recv_frame(conn, conn->rx_skb);
4683 conn->rx_skb = NULL;
4684 }
4685 }
4686
4687drop:
4688 kfree_skb(skb);
4689 return 0;
4690}
4691
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004692static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004693{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004694 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004695
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02004696 read_lock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004697
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004698 list_for_each_entry(c, &chan_list, global_l) {
4699 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004700
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004701 seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004702 batostr(&bt_sk(sk)->src),
4703 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004704 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004705 c->scid, c->dcid, c->imtu, c->omtu,
4706 c->sec_level, c->mode);
Andrei Emeltchenko61e1b4b2012-01-19 11:19:50 +02004707 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004708
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02004709 read_unlock(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004710
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004711 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004712}
4713
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004714static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4715{
4716 return single_open(file, l2cap_debugfs_show, inode->i_private);
4717}
4718
4719static const struct file_operations l2cap_debugfs_fops = {
4720 .open = l2cap_debugfs_open,
4721 .read = seq_read,
4722 .llseek = seq_lseek,
4723 .release = single_release,
4724};
4725
4726static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004727
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004728int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004729{
4730 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004731
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004732 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004733 if (err < 0)
4734 return err;
4735
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004736 if (bt_debugfs) {
4737 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4738 bt_debugfs, NULL, &l2cap_debugfs_fops);
4739 if (!l2cap_debugfs)
4740 BT_ERR("Failed to create L2CAP debug file");
4741 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004742
Linus Torvalds1da177e2005-04-16 15:20:36 -07004743 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004744}
4745
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004746void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004747{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004748 debugfs_remove(l2cap_debugfs);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004749 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004750}
4751
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004752module_param(disable_ertm, bool, 0644);
4753MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");