blob: c0640b73c62817a790ef6fdf715db8ee1beab289 [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{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020080 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030081
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020082 list_for_each_entry(c, &conn->chan_l, list) {
83 if (c->dcid == cid)
84 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020085 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020086 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +020087}
88
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030089static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020090{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020091 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030092
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020093 list_for_each_entry(c, &conn->chan_l, list) {
94 if (c->scid == cid)
95 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020096 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020097 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +020098}
99
100/* Find channel with given SCID.
101 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300102static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200103{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300104 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300105
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200106 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300107 c = __l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200108 mutex_unlock(&conn->chan_lock);
109
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300110 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200111}
112
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300113static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200114{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200115 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300116
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200117 list_for_each_entry(c, &conn->chan_l, list) {
118 if (c->ident == ident)
119 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200120 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200121 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200122}
123
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300124static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200125{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300126 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300127
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200128 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300129 c = __l2cap_get_chan_by_ident(conn, ident);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200130 mutex_unlock(&conn->chan_lock);
131
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300132 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200133}
134
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300135static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300136{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300137 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300138
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300139 list_for_each_entry(c, &chan_list, global_l) {
140 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Szymon Janc250938c2011-11-16 09:32:22 +0100141 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300142 }
Szymon Janc250938c2011-11-16 09:32:22 +0100143 return NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300144}
145
146int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
147{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300148 int err;
149
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200150 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300151
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300152 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300153 err = -EADDRINUSE;
154 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300155 }
156
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300157 if (psm) {
158 chan->psm = psm;
159 chan->sport = psm;
160 err = 0;
161 } else {
162 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300163
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300164 err = -EINVAL;
165 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300166 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300167 chan->psm = cpu_to_le16(p);
168 chan->sport = cpu_to_le16(p);
169 err = 0;
170 break;
171 }
172 }
173
174done:
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200175 write_unlock(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300176 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300177}
178
179int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
180{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200181 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300182
183 chan->scid = scid;
184
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200185 write_unlock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300186
187 return 0;
188}
189
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300190static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200191{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300192 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200193
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300194 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300195 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200196 return cid;
197 }
198
199 return 0;
200}
201
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200202static void __l2cap_state_change(struct l2cap_chan *chan, int state)
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300203{
Andrei Emeltchenko42d2d872012-02-17 11:40:57 +0200204 BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
Gustavo F. Padovanbadaaa02011-11-23 20:11:46 -0200205 state_to_string(state));
206
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300207 chan->state = state;
208 chan->ops->state_change(chan->data, state);
209}
210
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200211static void l2cap_state_change(struct l2cap_chan *chan, int state)
212{
213 struct sock *sk = chan->sk;
214
215 lock_sock(sk);
216 __l2cap_state_change(chan, state);
217 release_sock(sk);
218}
219
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +0200220static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err)
221{
222 struct sock *sk = chan->sk;
223
224 sk->sk_err = err;
225}
226
227static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
228{
229 struct sock *sk = chan->sk;
230
231 lock_sock(sk);
232 __l2cap_chan_set_err(chan, err);
233 release_sock(sk);
234}
235
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300236static void l2cap_chan_timeout(struct work_struct *work)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300237{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300238 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
239 chan_timer.work);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200240 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300241 struct sock *sk = chan->sk;
242 int reason;
243
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200244 BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300245
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200246 mutex_lock(&conn->chan_lock);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300247 lock_sock(sk);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300248
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300249 if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300250 reason = ECONNREFUSED;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300251 else if (chan->state == BT_CONNECT &&
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300252 chan->sec_level != BT_SECURITY_SDP)
253 reason = ECONNREFUSED;
254 else
255 reason = ETIMEDOUT;
256
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300257 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300258
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300259 release_sock(sk);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300260
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300261 chan->ops->close(chan->data);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200262 mutex_unlock(&conn->chan_lock);
263
Ulisses Furquim371fd832011-12-21 20:02:36 -0200264 l2cap_chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300265}
266
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300267struct l2cap_chan *l2cap_chan_create(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200268{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300269 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200270
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300271 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
272 if (!chan)
273 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200274
Andrei Emeltchenkoc03b3552012-02-21 12:54:56 +0200275 mutex_init(&chan->lock);
276
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300277 chan->sk = sk;
278
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200279 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300280 list_add(&chan->global_l, &chan_list);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200281 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300282
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300283 INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300284
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300285 chan->state = BT_OPEN;
286
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300287 atomic_set(&chan->refcnt, 1);
288
Szymon Jancabc545b2011-11-03 16:05:44 +0100289 BT_DBG("sk %p chan %p", sk, chan);
290
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300291 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200292}
293
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300294void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300295{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200296 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300297 list_del(&chan->global_l);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200298 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300299
Ulisses Furquim371fd832011-12-21 20:02:36 -0200300 l2cap_chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300301}
302
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200303static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200304{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300305 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300306 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200307
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +0200308 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +0100309
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300310 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200311
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200312 switch (chan->chan_type) {
313 case L2CAP_CHAN_CONN_ORIENTED:
Ville Tervob62f3282011-02-10 22:38:50 -0300314 if (conn->hcon->type == LE_LINK) {
315 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300316 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300317 chan->scid = L2CAP_CID_LE_DATA;
318 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300319 } else {
320 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300321 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300322 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300323 }
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200324 break;
325
326 case L2CAP_CHAN_CONN_LESS:
Marcel Holtmann01394182006-07-03 10:02:46 +0200327 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300328 chan->scid = L2CAP_CID_CONN_LESS;
329 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300330 chan->omtu = L2CAP_DEFAULT_MTU;
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200331 break;
332
333 default:
Marcel Holtmann01394182006-07-03 10:02:46 +0200334 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300335 chan->scid = L2CAP_CID_SIGNALING;
336 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300337 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200338 }
339
Andrei Emeltchenko8f7975b2011-10-13 16:18:54 +0300340 chan->local_id = L2CAP_BESTEFFORT_ID;
341 chan->local_stype = L2CAP_SERV_BESTEFFORT;
342 chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
343 chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
344 chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
345 chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
346
Ulisses Furquim371fd832011-12-21 20:02:36 -0200347 l2cap_chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300348
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200349 mutex_lock(&conn->chan_lock);
350 list_add(&chan->list, &conn->chan_l);
351 mutex_unlock(&conn->chan_lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200352}
353
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900354/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200355 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300356static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200357{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300358 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300359 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200360 struct sock *parent = bt_sk(sk)->parent;
361
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300362 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200363
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300364 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200365
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900366 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300367 /* Delete from channel list */
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200368 list_del(&chan->list);
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200369
Ulisses Furquim371fd832011-12-21 20:02:36 -0200370 l2cap_chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300371
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300372 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200373 hci_conn_put(conn->hcon);
374 }
375
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200376 __l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200377 sock_set_flag(sk, SOCK_ZAPPED);
378
379 if (err)
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +0200380 __l2cap_chan_set_err(chan, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200381
382 if (parent) {
383 bt_accept_unlink(sk);
384 parent->sk_data_ready(parent, 0);
385 } else
386 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300387
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300388 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
389 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300390 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300391
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300392 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300393
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300394 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300395 struct srej_list *l, *tmp;
396
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300397 __clear_retrans_timer(chan);
398 __clear_monitor_timer(chan);
399 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300400
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300401 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300402
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300403 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300404 list_del(&l->list);
405 kfree(l);
406 }
407 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200408}
409
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300410static void l2cap_chan_cleanup_listen(struct sock *parent)
411{
412 struct sock *sk;
413
414 BT_DBG("parent %p", parent);
415
416 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300417 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300418 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200419
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300420 __clear_chan_timer(chan);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300421 lock_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300422 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300423 release_sock(sk);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200424
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300425 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300426 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300427}
428
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300429void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300430{
431 struct l2cap_conn *conn = chan->conn;
432 struct sock *sk = chan->sk;
433
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200434 BT_DBG("chan %p state %s sk %p", chan,
435 state_to_string(chan->state), sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300436
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300437 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300438 case BT_LISTEN:
439 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300440
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200441 __l2cap_state_change(chan, BT_CLOSED);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300442 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300443 break;
444
445 case BT_CONNECTED:
446 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300447 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300448 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300449 __clear_chan_timer(chan);
450 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300451 l2cap_send_disconn_req(conn, chan, reason);
452 } else
453 l2cap_chan_del(chan, reason);
454 break;
455
456 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300457 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300458 conn->hcon->type == ACL_LINK) {
459 struct l2cap_conn_rsp rsp;
460 __u16 result;
461
462 if (bt_sk(sk)->defer_setup)
463 result = L2CAP_CR_SEC_BLOCK;
464 else
465 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300466 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300467
468 rsp.scid = cpu_to_le16(chan->dcid);
469 rsp.dcid = cpu_to_le16(chan->scid);
470 rsp.result = cpu_to_le16(result);
471 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
472 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
473 sizeof(rsp), &rsp);
474 }
475
476 l2cap_chan_del(chan, reason);
477 break;
478
479 case BT_CONNECT:
480 case BT_DISCONN:
481 l2cap_chan_del(chan, reason);
482 break;
483
484 default:
485 sock_set_flag(sk, SOCK_ZAPPED);
486 break;
487 }
488}
489
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300490static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530491{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300492 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300493 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530494 case BT_SECURITY_HIGH:
495 return HCI_AT_DEDICATED_BONDING_MITM;
496 case BT_SECURITY_MEDIUM:
497 return HCI_AT_DEDICATED_BONDING;
498 default:
499 return HCI_AT_NO_BONDING;
500 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300501 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300502 if (chan->sec_level == BT_SECURITY_LOW)
503 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530504
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300505 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530506 return HCI_AT_NO_BONDING_MITM;
507 else
508 return HCI_AT_NO_BONDING;
509 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300510 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530511 case BT_SECURITY_HIGH:
512 return HCI_AT_GENERAL_BONDING_MITM;
513 case BT_SECURITY_MEDIUM:
514 return HCI_AT_GENERAL_BONDING;
515 default:
516 return HCI_AT_NO_BONDING;
517 }
518 }
519}
520
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200521/* Service level security */
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200522int l2cap_chan_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200523{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300524 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100525 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200526
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300527 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100528
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300529 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200530}
531
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200532static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200533{
534 u8 id;
535
536 /* Get next available identificator.
537 * 1 - 128 are used by kernel.
538 * 129 - 199 are reserved.
539 * 200 - 254 are used by utilities like l2ping, etc.
540 */
541
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200542 spin_lock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200543
544 if (++conn->tx_ident > 128)
545 conn->tx_ident = 1;
546
547 id = conn->tx_ident;
548
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200549 spin_unlock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200550
551 return id;
552}
553
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300554static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200555{
556 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200557 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200558
559 BT_DBG("code 0x%2.2x", code);
560
561 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300562 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200563
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200564 if (lmp_no_flush_capable(conn->hcon->hdev))
565 flags = ACL_START_NO_FLUSH;
566 else
567 flags = ACL_START;
568
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700569 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +0200570 skb->priority = HCI_PRIO_MAX;
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700571
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200572 hci_send_acl(conn->hchan, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200573}
574
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200575static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
576{
577 struct hci_conn *hcon = chan->conn->hcon;
578 u16 flags;
579
580 BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
581 skb->priority);
582
583 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
584 lmp_no_flush_capable(hcon->hdev))
585 flags = ACL_START_NO_FLUSH;
586 else
587 flags = ACL_START;
588
589 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
590 hci_send_acl(chan->conn->hchan, skb, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591}
592
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300593static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300594{
595 struct sk_buff *skb;
596 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300597 struct l2cap_conn *conn = chan->conn;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300598 int count, hlen;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300599
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300600 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300601 return;
602
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300603 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
604 hlen = L2CAP_EXT_HDR_SIZE;
605 else
606 hlen = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300607
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300608 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300609 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300610
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300611 BT_DBG("chan %p, control 0x%8.8x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300612
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300613 count = min_t(unsigned int, conn->mtu, hlen);
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +0300614
615 control |= __set_sframe(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300616
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300617 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +0300618 control |= __set_ctrl_final(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300619
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300620 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +0300621 control |= __set_ctrl_poll(chan);
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300622
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300623 skb = bt_skb_alloc(count, GFP_ATOMIC);
624 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300625 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300626
627 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300628 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300629 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300630
631 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300632
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300633 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300634 u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
635 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300636 }
637
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200638 skb->priority = HCI_PRIO_MAX;
639 l2cap_do_send(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300640}
641
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300642static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300643{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300644 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300645 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300646 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300647 } else
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300648 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300649
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300650 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300651
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300652 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300653}
654
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300655static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300656{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300657 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300658}
659
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300660static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200661{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300662 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200663
664 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100665 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
666 return;
667
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200668 if (l2cap_chan_check_security(chan) &&
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300669 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200670 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300671 req.scid = cpu_to_le16(chan->scid);
672 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200673
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300674 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300675 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200676
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300677 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
678 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200679 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200680 } else {
681 struct l2cap_info_req req;
682 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
683
684 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
685 conn->info_ident = l2cap_get_ident(conn);
686
Gustavo F. Padovan030013d2011-12-20 10:57:28 -0200687 schedule_delayed_work(&conn->info_timer,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200688 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
689
690 l2cap_send_cmd(conn, conn->info_ident,
691 L2CAP_INFO_REQ, sizeof(req), &req);
692 }
693}
694
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300695static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
696{
697 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300698 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300699 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
700
701 switch (mode) {
702 case L2CAP_MODE_ERTM:
703 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
704 case L2CAP_MODE_STREAMING:
705 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
706 default:
707 return 0x00;
708 }
709}
710
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300711static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300712{
713 struct l2cap_disconn_req req;
714
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300715 if (!conn)
716 return;
717
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300718 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300719 __clear_retrans_timer(chan);
720 __clear_monitor_timer(chan);
721 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300722 }
723
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300724 req.dcid = cpu_to_le16(chan->dcid);
725 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300726 l2cap_send_cmd(conn, l2cap_get_ident(conn),
727 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300728
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200729 __l2cap_state_change(chan, BT_DISCONN);
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +0200730 __l2cap_chan_set_err(chan, err);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300731}
732
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200734static void l2cap_conn_start(struct l2cap_conn *conn)
735{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200736 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200737
738 BT_DBG("conn %p", conn);
739
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200740 mutex_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200741
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200742 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300743 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300744
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200745 bh_lock_sock(sk);
746
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300747 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200748 bh_unlock_sock(sk);
749 continue;
750 }
751
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300752 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300753 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300754
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200755 if (!l2cap_chan_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300756 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300757 bh_unlock_sock(sk);
758 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200759 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300760
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300761 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
762 && test_bit(CONF_STATE2_DEVICE,
763 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300764 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300765 * so release the lock */
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300766 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300767 bh_unlock_sock(sk);
768 continue;
769 }
770
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300771 req.scid = cpu_to_le16(chan->scid);
772 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300773
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300774 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300775 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300776
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300777 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
778 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300779
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300780 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200781 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300782 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300783 rsp.scid = cpu_to_le16(chan->dcid);
784 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200785
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200786 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100787 if (bt_sk(sk)->defer_setup) {
788 struct sock *parent = bt_sk(sk)->parent;
789 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
790 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +0000791 if (parent)
792 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100793
794 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200795 __l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100796 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
797 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
798 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200799 } else {
800 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
801 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
802 }
803
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300804 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
805 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300806
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300807 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300808 rsp.result != L2CAP_CR_SUCCESS) {
809 bh_unlock_sock(sk);
810 continue;
811 }
812
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300813 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300814 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300815 l2cap_build_conf_req(chan, buf), buf);
816 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200817 }
818
819 bh_unlock_sock(sk);
820 }
821
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200822 mutex_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200823}
824
Ville Tervob62f3282011-02-10 22:38:50 -0300825/* Find socket with cid and source bdaddr.
826 * Returns closest match, locked.
827 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300828static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300829{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300830 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300831
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300832 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300833
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300834 list_for_each_entry(c, &chan_list, global_l) {
835 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300836
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300837 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300838 continue;
839
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300840 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300841 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300842 if (!bacmp(&bt_sk(sk)->src, src)) {
843 read_unlock(&chan_list_lock);
844 return c;
845 }
Ville Tervob62f3282011-02-10 22:38:50 -0300846
847 /* Closest match */
848 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300849 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300850 }
851 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300852
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300853 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300854
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300855 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300856}
857
858static void l2cap_le_conn_ready(struct l2cap_conn *conn)
859{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300860 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300861 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300862
863 BT_DBG("");
864
865 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300866 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300867 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300868 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300869 return;
870
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300871 parent = pchan->sk;
872
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300873 lock_sock(parent);
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300874
Ville Tervob62f3282011-02-10 22:38:50 -0300875 /* Check for backlog size */
876 if (sk_acceptq_is_full(parent)) {
877 BT_DBG("backlog full %d", parent->sk_ack_backlog);
878 goto clean;
879 }
880
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300881 chan = pchan->ops->new_connection(pchan->data);
882 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300883 goto clean;
884
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300885 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300886
Ville Tervob62f3282011-02-10 22:38:50 -0300887 hci_conn_hold(conn->hcon);
888
Ville Tervob62f3282011-02-10 22:38:50 -0300889 bacpy(&bt_sk(sk)->src, conn->src);
890 bacpy(&bt_sk(sk)->dst, conn->dst);
891
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300892 bt_accept_enqueue(parent, sk);
893
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200894 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300895
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300896 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300897
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200898 __l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300899 parent->sk_data_ready(parent, 0);
900
Ville Tervob62f3282011-02-10 22:38:50 -0300901clean:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300902 release_sock(parent);
Ville Tervob62f3282011-02-10 22:38:50 -0300903}
904
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +0200905static void l2cap_chan_ready(struct l2cap_chan *chan)
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300906{
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +0200907 struct sock *sk = chan->sk;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300908 struct sock *parent = bt_sk(sk)->parent;
909
910 BT_DBG("sk %p, parent %p", sk, parent);
911
912 chan->conf_state = 0;
913 __clear_chan_timer(chan);
914
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200915 __l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300916 sk->sk_state_change(sk);
917
918 if (parent)
919 parent->sk_data_ready(parent, 0);
920}
921
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200922static void l2cap_conn_ready(struct l2cap_conn *conn)
923{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300924 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200925
926 BT_DBG("conn %p", conn);
927
Ville Tervob62f3282011-02-10 22:38:50 -0300928 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
929 l2cap_le_conn_ready(conn);
930
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -0300931 if (conn->hcon->out && conn->hcon->type == LE_LINK)
932 smp_conn_security(conn, conn->hcon->pending_sec_level);
933
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200934 mutex_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200935
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200936 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300937 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300938
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200939 bh_lock_sock(sk);
940
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300941 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300942 if (smp_conn_security(conn, chan->sec_level))
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +0200943 l2cap_chan_ready(chan);
Ville Tervoacd7d372011-02-10 22:38:49 -0300944
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300945 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300946 __clear_chan_timer(chan);
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200947 __l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200948 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300949
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300950 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300951 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200952
953 bh_unlock_sock(sk);
954 }
955
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200956 mutex_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200957}
958
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200959/* Notify sockets that we cannot guaranty reliability anymore */
960static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
961{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300962 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200963
964 BT_DBG("conn %p", conn);
965
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200966 mutex_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200967
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200968 list_for_each_entry(chan, &conn->chan_l, list) {
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +0300969 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +0200970 __l2cap_chan_set_err(chan, err);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200971 }
972
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200973 mutex_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200974}
975
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -0200976static void l2cap_info_timeout(struct work_struct *work)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200977{
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -0200978 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
Gustavo F. Padovan030013d2011-12-20 10:57:28 -0200979 info_timer.work);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200980
Marcel Holtmann984947d2009-02-06 23:35:19 +0100981 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100982 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100983
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200984 l2cap_conn_start(conn);
985}
986
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300987static void l2cap_conn_del(struct hci_conn *hcon, int err)
988{
989 struct l2cap_conn *conn = hcon->l2cap_data;
990 struct l2cap_chan *chan, *l;
991 struct sock *sk;
992
993 if (!conn)
994 return;
995
996 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
997
998 kfree_skb(conn->rx_skb);
999
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001000 mutex_lock(&conn->chan_lock);
1001
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001002 /* Kill channels */
1003 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
1004 sk = chan->sk;
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001005 lock_sock(sk);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001006 l2cap_chan_del(chan, err);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001007 release_sock(sk);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001008 chan->ops->close(chan->data);
1009 }
1010
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001011 mutex_unlock(&conn->chan_lock);
1012
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001013 hci_chan_del(conn->hchan);
1014
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001015 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
Ulisses Furquim127074b2012-01-30 18:26:29 -02001016 cancel_delayed_work_sync(&conn->info_timer);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001017
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001018 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
Ulisses Furquim127074b2012-01-30 18:26:29 -02001019 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001020 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001021 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001022
1023 hcon->l2cap_data = NULL;
1024 kfree(conn);
1025}
1026
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001027static void security_timeout(struct work_struct *work)
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001028{
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001029 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1030 security_timer.work);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001031
1032 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1033}
1034
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1036{
Marcel Holtmann01394182006-07-03 10:02:46 +02001037 struct l2cap_conn *conn = hcon->l2cap_data;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001038 struct hci_chan *hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039
Marcel Holtmann01394182006-07-03 10:02:46 +02001040 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 return conn;
1042
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001043 hchan = hci_chan_create(hcon);
1044 if (!hchan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001047 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1048 if (!conn) {
1049 hci_chan_del(hchan);
1050 return NULL;
1051 }
1052
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 hcon->l2cap_data = conn;
1054 conn->hcon = hcon;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001055 conn->hchan = hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001057 BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
Marcel Holtmann01394182006-07-03 10:02:46 +02001058
Ville Tervoacd7d372011-02-10 22:38:49 -03001059 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1060 conn->mtu = hcon->hdev->le_mtu;
1061 else
1062 conn->mtu = hcon->hdev->acl_mtu;
1063
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 conn->src = &hcon->hdev->bdaddr;
1065 conn->dst = &hcon->dst;
1066
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001067 conn->feat_mask = 0;
1068
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 spin_lock_init(&conn->lock);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001070 mutex_init(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001071
1072 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001074 if (hcon->type == LE_LINK)
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001075 INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001076 else
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02001077 INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
Dave Young45054dc2009-10-18 20:28:30 +00001078
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001079 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01001080
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 return conn;
1082}
1083
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085
1086/* Find socket with psm and source bdaddr.
1087 * Returns closest match.
1088 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001089static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001091 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001093 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001094
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001095 list_for_each_entry(c, &chan_list, global_l) {
1096 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001097
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001098 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 continue;
1100
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001101 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001103 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001104 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001105 return c;
1106 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107
1108 /* Closest match */
1109 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001110 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 }
1112 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001114 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001115
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001116 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117}
1118
Johan Hedbergcbe8fed2012-01-08 22:51:16 +02001119int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001121 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 bdaddr_t *src = &bt_sk(sk)->src;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 struct l2cap_conn *conn;
1124 struct hci_conn *hcon;
1125 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001126 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001127 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001129 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001130 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001132 hdev = hci_get_route(dst, src);
1133 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 return -EHOSTUNREACH;
1135
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001136 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001138 lock_sock(sk);
1139
1140 /* PSM must be odd and lsb of upper byte must be 0 */
1141 if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
1142 chan->chan_type != L2CAP_CHAN_RAW) {
1143 err = -EINVAL;
1144 goto done;
1145 }
1146
1147 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
1148 err = -EINVAL;
1149 goto done;
1150 }
1151
1152 switch (chan->mode) {
1153 case L2CAP_MODE_BASIC:
1154 break;
1155 case L2CAP_MODE_ERTM:
1156 case L2CAP_MODE_STREAMING:
1157 if (!disable_ertm)
1158 break;
1159 /* fall through */
1160 default:
1161 err = -ENOTSUPP;
1162 goto done;
1163 }
1164
1165 switch (sk->sk_state) {
1166 case BT_CONNECT:
1167 case BT_CONNECT2:
1168 case BT_CONFIG:
1169 /* Already connecting */
1170 err = 0;
1171 goto done;
1172
1173 case BT_CONNECTED:
1174 /* Already connected */
1175 err = -EISCONN;
1176 goto done;
1177
1178 case BT_OPEN:
1179 case BT_BOUND:
1180 /* Can connect */
1181 break;
1182
1183 default:
1184 err = -EBADFD;
1185 goto done;
1186 }
1187
1188 /* Set destination address and psm */
Gustavo F. Padovan9219b2a2012-01-02 20:08:04 -02001189 bacpy(&bt_sk(sk)->dst, dst);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001190 chan->psm = psm;
1191 chan->dcid = cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001193 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001194
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001195 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001196 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001197 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001198 else
1199 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001200 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001201
Ville Tervo30e76272011-02-22 16:10:53 -03001202 if (IS_ERR(hcon)) {
1203 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001205 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206
1207 conn = l2cap_conn_add(hcon, 0);
1208 if (!conn) {
1209 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001210 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 goto done;
1212 }
1213
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 /* Update source addr of the socket */
1215 bacpy(src, conn->src);
1216
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001217 l2cap_chan_add(conn, chan);
1218
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001219 __l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001220 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221
1222 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001223 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001224 __clear_chan_timer(chan);
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001225 if (l2cap_chan_check_security(chan))
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001226 __l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001227 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001228 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 }
1230
Ville Tervo30e76272011-02-22 16:10:53 -03001231 err = 0;
1232
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001234 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 hci_dev_put(hdev);
1236 return err;
1237}
1238
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001239int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001240{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001241 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001242 DECLARE_WAITQUEUE(wait, current);
1243 int err = 0;
1244 int timeo = HZ/5;
1245
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001246 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001247 set_current_state(TASK_INTERRUPTIBLE);
1248 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001249 if (!timeo)
1250 timeo = HZ/5;
1251
1252 if (signal_pending(current)) {
1253 err = sock_intr_errno(timeo);
1254 break;
1255 }
1256
1257 release_sock(sk);
1258 timeo = schedule_timeout(timeo);
1259 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001260 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001261
1262 err = sock_error(sk);
1263 if (err)
1264 break;
1265 }
1266 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001267 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001268 return err;
1269}
1270
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001271static void l2cap_monitor_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001272{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001273 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1274 monitor_timer.work);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001275 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001276
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001277 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001278
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001279 lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001280 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001281 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001282 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001283 return;
1284 }
1285
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001286 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001287 __set_monitor_timer(chan);
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. Padovan721c4182011-06-23 19:29:58 -03001293static void l2cap_retrans_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001294{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001295 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1296 retrans_timer.work);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001297 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001298
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001299 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001300
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001301 lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001302 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001303 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001304
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001305 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001306
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001307 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001308 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001309}
1310
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001311static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001312{
1313 struct sk_buff *skb;
1314
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001315 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001316 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001317 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001318 break;
1319
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001320 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001321 kfree_skb(skb);
1322
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001323 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001324 }
1325
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001326 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001327 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001328}
1329
Szymon Janc67c9e842011-07-28 16:24:33 +02001330static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001331{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001332 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001333 u32 control;
1334 u16 fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001335
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001336 while ((skb = skb_dequeue(&chan->tx_q))) {
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001337 control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001338 control |= __set_txseq(chan, chan->next_tx_seq);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001339 __put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001340
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001341 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001342 fcs = crc16(0, (u8 *)skb->data,
1343 skb->len - L2CAP_FCS_SIZE);
1344 put_unaligned_le16(fcs,
1345 skb->data + skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001346 }
1347
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001348 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001349
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001350 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001351 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001352}
1353
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001354static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001355{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001356 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001357 u16 fcs;
1358 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001359
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001360 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001361 if (!skb)
1362 return;
1363
Szymon Jancd1726b62011-11-16 09:32:20 +01001364 while (bt_cb(skb)->tx_seq != tx_seq) {
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001365 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001366 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001367
Szymon Jancd1726b62011-11-16 09:32:20 +01001368 skb = skb_queue_next(&chan->tx_q, skb);
1369 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001370
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001371 if (chan->remote_max_tx &&
1372 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001373 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001374 return;
1375 }
1376
1377 tx_skb = skb_clone(skb, GFP_ATOMIC);
1378 bt_cb(skb)->retries++;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001379
1380 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001381 control &= __get_sar_mask(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001382
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001383 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001384 control |= __set_ctrl_final(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001385
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001386 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001387 control |= __set_txseq(chan, tx_seq);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001388
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001389 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001390
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001391 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001392 fcs = crc16(0, (u8 *)tx_skb->data,
1393 tx_skb->len - L2CAP_FCS_SIZE);
1394 put_unaligned_le16(fcs,
1395 tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001396 }
1397
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001398 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001399}
1400
Szymon Janc67c9e842011-07-28 16:24:33 +02001401static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001402{
1403 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001404 u16 fcs;
1405 u32 control;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001406 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001407
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001408 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001409 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001410
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001411 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001412
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001413 if (chan->remote_max_tx &&
1414 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001415 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001416 break;
1417 }
1418
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001419 tx_skb = skb_clone(skb, GFP_ATOMIC);
1420
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001421 bt_cb(skb)->retries++;
1422
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001423 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001424 control &= __get_sar_mask(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001425
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001426 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001427 control |= __set_ctrl_final(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001428
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001429 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001430 control |= __set_txseq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001431
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001432 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001433
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001434 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001435 fcs = crc16(0, (u8 *)skb->data,
1436 tx_skb->len - L2CAP_FCS_SIZE);
1437 put_unaligned_le16(fcs, skb->data +
1438 tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001439 }
1440
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001441 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001442
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001443 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001444
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001445 bt_cb(skb)->tx_seq = chan->next_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001446
1447 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001448
Szymon Janc8ed7a0a2012-02-07 15:43:01 +01001449 if (bt_cb(skb)->retries == 1) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001450 chan->unacked_frames++;
Szymon Janc930fa4a2012-02-07 15:43:02 +01001451
1452 if (!nsent++)
1453 __clear_ack_timer(chan);
Szymon Janc8ed7a0a2012-02-07 15:43:01 +01001454 }
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301455
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001456 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001457
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001458 if (skb_queue_is_last(&chan->tx_q, skb))
1459 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001460 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001461 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001462 }
1463
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001464 return nsent;
1465}
1466
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001467static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001468{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001469 int ret;
1470
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001471 if (!skb_queue_empty(&chan->tx_q))
1472 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001473
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001474 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001475 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001476 return ret;
1477}
1478
Szymon Jancb17e73b2012-01-11 10:59:47 +01001479static void __l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001480{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001481 u32 control = 0;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001482
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001483 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001484
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001485 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001486 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001487 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001488 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001489 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001490 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001491
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001492 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001493 return;
1494
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001495 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001496 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001497}
1498
Szymon Jancb17e73b2012-01-11 10:59:47 +01001499static void l2cap_send_ack(struct l2cap_chan *chan)
1500{
1501 __clear_ack_timer(chan);
1502 __l2cap_send_ack(chan);
1503}
1504
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001505static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001506{
1507 struct srej_list *tail;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001508 u32 control;
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001509
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001510 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001511 control |= __set_ctrl_final(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001512
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001513 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001514 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001515
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001516 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001517}
1518
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001519static 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 -07001520{
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001521 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001522 struct sk_buff **frag;
1523 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001525 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001526 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527
1528 sent += count;
1529 len -= count;
1530
1531 /* Continuation fragments (no L2CAP header) */
1532 frag = &skb_shinfo(skb)->frag_list;
1533 while (len) {
1534 count = min_t(unsigned int, conn->mtu, len);
1535
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001536 *frag = chan->ops->alloc_skb(chan, count,
1537 msg->msg_flags & MSG_DONTWAIT, &err);
1538
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001540 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001541 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1542 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001544 (*frag)->priority = skb->priority;
1545
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 sent += count;
1547 len -= count;
1548
1549 frag = &(*frag)->next;
1550 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551
1552 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001553}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001555static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
1556 struct msghdr *msg, size_t len,
1557 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001558{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001559 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001560 struct sk_buff *skb;
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001561 int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001562 struct l2cap_hdr *lh;
1563
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001564 BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001565
1566 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001567
1568 skb = chan->ops->alloc_skb(chan, count + hlen,
1569 msg->msg_flags & MSG_DONTWAIT, &err);
1570
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001571 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001572 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001573
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001574 skb->priority = priority;
1575
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001576 /* Create L2CAP header */
1577 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001578 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001579 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001580 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001581
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001582 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001583 if (unlikely(err < 0)) {
1584 kfree_skb(skb);
1585 return ERR_PTR(err);
1586 }
1587 return skb;
1588}
1589
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001590static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
1591 struct msghdr *msg, size_t len,
1592 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001593{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001594 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001595 struct sk_buff *skb;
1596 int err, count, hlen = L2CAP_HDR_SIZE;
1597 struct l2cap_hdr *lh;
1598
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001599 BT_DBG("chan %p len %d", chan, (int)len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001600
1601 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001602
1603 skb = chan->ops->alloc_skb(chan, count + hlen,
1604 msg->msg_flags & MSG_DONTWAIT, &err);
1605
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001606 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001607 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001608
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001609 skb->priority = priority;
1610
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001611 /* Create L2CAP header */
1612 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001613 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001614 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1615
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001616 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001617 if (unlikely(err < 0)) {
1618 kfree_skb(skb);
1619 return ERR_PTR(err);
1620 }
1621 return skb;
1622}
1623
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001624static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1625 struct msghdr *msg, size_t len,
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001626 u32 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001627{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001628 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001629 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001630 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001631 struct l2cap_hdr *lh;
1632
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001633 BT_DBG("chan %p len %d", chan, (int)len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001634
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001635 if (!conn)
1636 return ERR_PTR(-ENOTCONN);
1637
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001638 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1639 hlen = L2CAP_EXT_HDR_SIZE;
1640 else
1641 hlen = L2CAP_ENH_HDR_SIZE;
1642
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001643 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001644 hlen += L2CAP_SDULEN_SIZE;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001645
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001646 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001647 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001648
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001649 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001650
1651 skb = chan->ops->alloc_skb(chan, count + hlen,
1652 msg->msg_flags & MSG_DONTWAIT, &err);
1653
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001654 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001655 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001656
1657 /* Create L2CAP header */
1658 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001659 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001660 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001661
1662 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
1663
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001664 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001665 put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001666
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001667 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001668 if (unlikely(err < 0)) {
1669 kfree_skb(skb);
1670 return ERR_PTR(err);
1671 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001672
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001673 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001674 put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001675
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001676 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001677 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678}
1679
Szymon Janc67c9e842011-07-28 16:24:33 +02001680static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001681{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001682 struct sk_buff *skb;
1683 struct sk_buff_head sar_queue;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001684 u32 control;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001685 size_t size = 0;
1686
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001687 skb_queue_head_init(&sar_queue);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001688 control = __set_ctrl_sar(chan, L2CAP_SAR_START);
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001689 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001690 if (IS_ERR(skb))
1691 return PTR_ERR(skb);
1692
1693 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001694 len -= chan->remote_mps;
1695 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001696
1697 while (len > 0) {
1698 size_t buflen;
1699
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001700 if (len > chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001701 control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001702 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001703 } else {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001704 control = __set_ctrl_sar(chan, L2CAP_SAR_END);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001705 buflen = len;
1706 }
1707
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001708 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001709 if (IS_ERR(skb)) {
1710 skb_queue_purge(&sar_queue);
1711 return PTR_ERR(skb);
1712 }
1713
1714 __skb_queue_tail(&sar_queue, skb);
1715 len -= buflen;
1716 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001717 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001718 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1719 if (chan->tx_send_head == NULL)
1720 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001721
1722 return size;
1723}
1724
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001725int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
1726 u32 priority)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001727{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001728 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001729 u32 control;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001730 int err;
1731
1732 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001733 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001734 skb = l2cap_create_connless_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001735 if (IS_ERR(skb))
1736 return PTR_ERR(skb);
1737
1738 l2cap_do_send(chan, skb);
1739 return len;
1740 }
1741
1742 switch (chan->mode) {
1743 case L2CAP_MODE_BASIC:
1744 /* Check outgoing MTU */
1745 if (len > chan->omtu)
1746 return -EMSGSIZE;
1747
1748 /* Create a basic PDU */
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001749 skb = l2cap_create_basic_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001750 if (IS_ERR(skb))
1751 return PTR_ERR(skb);
1752
1753 l2cap_do_send(chan, skb);
1754 err = len;
1755 break;
1756
1757 case L2CAP_MODE_ERTM:
1758 case L2CAP_MODE_STREAMING:
1759 /* Entire SDU fits into one PDU */
1760 if (len <= chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001761 control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001762 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1763 0);
1764 if (IS_ERR(skb))
1765 return PTR_ERR(skb);
1766
1767 __skb_queue_tail(&chan->tx_q, skb);
1768
1769 if (chan->tx_send_head == NULL)
1770 chan->tx_send_head = skb;
1771
1772 } else {
1773 /* Segment SDU into multiples PDUs */
1774 err = l2cap_sar_segment_sdu(chan, msg, len);
1775 if (err < 0)
1776 return err;
1777 }
1778
1779 if (chan->mode == L2CAP_MODE_STREAMING) {
1780 l2cap_streaming_send(chan);
1781 err = len;
1782 break;
1783 }
1784
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001785 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1786 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001787 err = len;
1788 break;
1789 }
1790
1791 err = l2cap_ertm_send(chan);
1792 if (err >= 0)
1793 err = len;
1794
1795 break;
1796
1797 default:
1798 BT_DBG("bad state %1.1x", chan->mode);
1799 err = -EBADFD;
1800 }
1801
1802 return err;
1803}
1804
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805/* Copy frame to all raw sockets on that connection */
1806static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1807{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001809 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810
1811 BT_DBG("conn %p", conn);
1812
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001813 mutex_lock(&conn->chan_lock);
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001814
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001815 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001816 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001817 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818 continue;
1819
1820 /* Don't send frame to the socket it came from */
1821 if (skb->sk == sk)
1822 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001823 nskb = skb_clone(skb, GFP_ATOMIC);
1824 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825 continue;
1826
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001827 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828 kfree_skb(nskb);
1829 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001830
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001831 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832}
1833
1834/* ---- L2CAP signalling commands ---- */
1835static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1836 u8 code, u8 ident, u16 dlen, void *data)
1837{
1838 struct sk_buff *skb, **frag;
1839 struct l2cap_cmd_hdr *cmd;
1840 struct l2cap_hdr *lh;
1841 int len, count;
1842
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001843 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1844 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845
1846 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1847 count = min_t(unsigned int, conn->mtu, len);
1848
1849 skb = bt_skb_alloc(count, GFP_ATOMIC);
1850 if (!skb)
1851 return NULL;
1852
1853 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001854 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001855
1856 if (conn->hcon->type == LE_LINK)
1857 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1858 else
1859 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860
1861 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1862 cmd->code = code;
1863 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001864 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865
1866 if (dlen) {
1867 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1868 memcpy(skb_put(skb, count), data, count);
1869 data += count;
1870 }
1871
1872 len -= skb->len;
1873
1874 /* Continuation fragments (no L2CAP header) */
1875 frag = &skb_shinfo(skb)->frag_list;
1876 while (len) {
1877 count = min_t(unsigned int, conn->mtu, len);
1878
1879 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1880 if (!*frag)
1881 goto fail;
1882
1883 memcpy(skb_put(*frag, count), data, count);
1884
1885 len -= count;
1886 data += count;
1887
1888 frag = &(*frag)->next;
1889 }
1890
1891 return skb;
1892
1893fail:
1894 kfree_skb(skb);
1895 return NULL;
1896}
1897
1898static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1899{
1900 struct l2cap_conf_opt *opt = *ptr;
1901 int len;
1902
1903 len = L2CAP_CONF_OPT_SIZE + opt->len;
1904 *ptr += len;
1905
1906 *type = opt->type;
1907 *olen = opt->len;
1908
1909 switch (opt->len) {
1910 case 1:
1911 *val = *((u8 *) opt->val);
1912 break;
1913
1914 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001915 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 break;
1917
1918 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001919 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 break;
1921
1922 default:
1923 *val = (unsigned long) opt->val;
1924 break;
1925 }
1926
1927 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1928 return len;
1929}
1930
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1932{
1933 struct l2cap_conf_opt *opt = *ptr;
1934
1935 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1936
1937 opt->type = type;
1938 opt->len = len;
1939
1940 switch (len) {
1941 case 1:
1942 *((u8 *) opt->val) = val;
1943 break;
1944
1945 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001946 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947 break;
1948
1949 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001950 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951 break;
1952
1953 default:
1954 memcpy(opt->val, (void *) val, len);
1955 break;
1956 }
1957
1958 *ptr += L2CAP_CONF_OPT_SIZE + len;
1959}
1960
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001961static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
1962{
1963 struct l2cap_conf_efs efs;
1964
Szymon Janc1ec918c2011-11-16 09:32:21 +01001965 switch (chan->mode) {
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001966 case L2CAP_MODE_ERTM:
1967 efs.id = chan->local_id;
1968 efs.stype = chan->local_stype;
1969 efs.msdu = cpu_to_le16(chan->local_msdu);
1970 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1971 efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
1972 efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
1973 break;
1974
1975 case L2CAP_MODE_STREAMING:
1976 efs.id = 1;
1977 efs.stype = L2CAP_SERV_BESTEFFORT;
1978 efs.msdu = cpu_to_le16(chan->local_msdu);
1979 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1980 efs.acc_lat = 0;
1981 efs.flush_to = 0;
1982 break;
1983
1984 default:
1985 return;
1986 }
1987
1988 l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
1989 (unsigned long) &efs);
1990}
1991
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001992static void l2cap_ack_timeout(struct work_struct *work)
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001993{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001994 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1995 ack_timer.work);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001996
Gustavo F. Padovan2fb9b3d2011-12-22 16:56:05 -02001997 BT_DBG("chan %p", chan);
1998
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001999 lock_sock(chan->sk);
Szymon Jancb17e73b2012-01-11 10:59:47 +01002000 __l2cap_send_ack(chan);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002001 release_sock(chan->sk);
Szymon Janc09bfb2e2012-01-11 10:59:49 +01002002
2003 l2cap_chan_put(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002004}
2005
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002006static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002007{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002008 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002009 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002010 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002011 chan->num_acked = 0;
2012 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002013
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002014 INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2015 INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2016 INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002017
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002018 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002019
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03002020 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002021}
2022
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002023static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2024{
2025 switch (mode) {
2026 case L2CAP_MODE_STREAMING:
2027 case L2CAP_MODE_ERTM:
2028 if (l2cap_mode_supported(mode, remote_feat_mask))
2029 return mode;
2030 /* fall through */
2031 default:
2032 return L2CAP_MODE_BASIC;
2033 }
2034}
2035
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002036static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
2037{
2038 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
2039}
2040
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002041static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2042{
2043 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2044}
2045
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002046static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
2047{
2048 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002049 __l2cap_ews_supported(chan)) {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002050 /* use extended control field */
2051 set_bit(FLAG_EXT_CTRL, &chan->flags);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002052 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2053 } else {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002054 chan->tx_win = min_t(u16, chan->tx_win,
2055 L2CAP_DEFAULT_TX_WINDOW);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002056 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2057 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002058}
2059
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002060static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002063 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 void *ptr = req->data;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002065 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002067 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002069 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002070 goto done;
2071
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002072 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002073 case L2CAP_MODE_STREAMING:
2074 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002075 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002076 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002077
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002078 if (__l2cap_efs_supported(chan))
2079 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2080
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002081 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002082 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002083 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002084 break;
2085 }
2086
2087done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002088 if (chan->imtu != L2CAP_DEFAULT_MTU)
2089 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002090
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002091 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002092 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002093 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2094 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002095 break;
2096
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002097 rfc.mode = L2CAP_MODE_BASIC;
2098 rfc.txwin_size = 0;
2099 rfc.max_transmit = 0;
2100 rfc.retrans_timeout = 0;
2101 rfc.monitor_timeout = 0;
2102 rfc.max_pdu_size = 0;
2103
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002104 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2105 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002106 break;
2107
2108 case L2CAP_MODE_ERTM:
2109 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002110 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002111 rfc.retrans_timeout = 0;
2112 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002113
2114 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2115 L2CAP_EXT_HDR_SIZE -
2116 L2CAP_SDULEN_SIZE -
2117 L2CAP_FCS_SIZE);
2118 rfc.max_pdu_size = cpu_to_le16(size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002119
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002120 l2cap_txwin_setup(chan);
2121
2122 rfc.txwin_size = min_t(u16, chan->tx_win,
2123 L2CAP_DEFAULT_TX_WINDOW);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002124
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002125 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2126 (unsigned long) &rfc);
2127
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002128 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2129 l2cap_add_opt_efs(&ptr, chan);
2130
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002131 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002132 break;
2133
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002134 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002135 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002136 chan->fcs = L2CAP_FCS_NONE;
2137 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002138 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002139
2140 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2141 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2142 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002143 break;
2144
2145 case L2CAP_MODE_STREAMING:
2146 rfc.mode = L2CAP_MODE_STREAMING;
2147 rfc.txwin_size = 0;
2148 rfc.max_transmit = 0;
2149 rfc.retrans_timeout = 0;
2150 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002151
2152 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2153 L2CAP_EXT_HDR_SIZE -
2154 L2CAP_SDULEN_SIZE -
2155 L2CAP_FCS_SIZE);
2156 rfc.max_pdu_size = cpu_to_le16(size);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002157
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002158 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2159 (unsigned long) &rfc);
2160
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002161 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2162 l2cap_add_opt_efs(&ptr, chan);
2163
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002164 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002165 break;
2166
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002167 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002168 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002169 chan->fcs = L2CAP_FCS_NONE;
2170 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002171 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002172 break;
2173 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002175 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002176 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177
2178 return ptr - data;
2179}
2180
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002181static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002183 struct l2cap_conf_rsp *rsp = data;
2184 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002185 void *req = chan->conf_req;
2186 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002187 int type, hint, olen;
2188 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002189 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002190 struct l2cap_conf_efs efs;
2191 u8 remote_efs = 0;
Marcel Holtmann861d6882007-10-20 13:37:06 +02002192 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002193 u16 result = L2CAP_CONF_SUCCESS;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002194 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002196 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002197
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002198 while (len >= L2CAP_CONF_OPT_SIZE) {
2199 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002201 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002202 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002203
2204 switch (type) {
2205 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002206 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002207 break;
2208
2209 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002210 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002211 break;
2212
2213 case L2CAP_CONF_QOS:
2214 break;
2215
Marcel Holtmann6464f352007-10-20 13:39:51 +02002216 case L2CAP_CONF_RFC:
2217 if (olen == sizeof(rfc))
2218 memcpy(&rfc, (void *) val, olen);
2219 break;
2220
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002221 case L2CAP_CONF_FCS:
2222 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002223 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002224 break;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002225
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002226 case L2CAP_CONF_EFS:
2227 remote_efs = 1;
2228 if (olen == sizeof(efs))
2229 memcpy(&efs, (void *) val, olen);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002230 break;
2231
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002232 case L2CAP_CONF_EWS:
2233 if (!enable_hs)
2234 return -ECONNREFUSED;
2235
2236 set_bit(FLAG_EXT_CTRL, &chan->flags);
2237 set_bit(CONF_EWS_RECV, &chan->conf_state);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002238 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002239 chan->remote_tx_win = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002240 break;
2241
2242 default:
2243 if (hint)
2244 break;
2245
2246 result = L2CAP_CONF_UNKNOWN;
2247 *((u8 *) ptr++) = type;
2248 break;
2249 }
2250 }
2251
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002252 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002253 goto done;
2254
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002255 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002256 case L2CAP_MODE_STREAMING:
2257 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002258 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002259 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002260 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002261 break;
2262 }
2263
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002264 if (remote_efs) {
2265 if (__l2cap_efs_supported(chan))
2266 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2267 else
2268 return -ECONNREFUSED;
2269 }
2270
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002271 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002272 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002273
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002274 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002275 }
2276
2277done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002278 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002279 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002280 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002281
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002282 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002283 return -ECONNREFUSED;
2284
2285 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2286 sizeof(rfc), (unsigned long) &rfc);
2287 }
2288
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002289 if (result == L2CAP_CONF_SUCCESS) {
2290 /* Configure output options and let the other side know
2291 * which ones we don't like. */
2292
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002293 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2294 result = L2CAP_CONF_UNACCEPT;
2295 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002296 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002297 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002298 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002299 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002300
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002301 if (remote_efs) {
2302 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2303 efs.stype != L2CAP_SERV_NOTRAFIC &&
2304 efs.stype != chan->local_stype) {
2305
2306 result = L2CAP_CONF_UNACCEPT;
2307
2308 if (chan->num_conf_req >= 1)
2309 return -ECONNREFUSED;
2310
2311 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002312 sizeof(efs),
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002313 (unsigned long) &efs);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002314 } else {
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002315 /* Send PENDING Conf Rsp */
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002316 result = L2CAP_CONF_PENDING;
2317 set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002318 }
2319 }
2320
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002321 switch (rfc.mode) {
2322 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002323 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002324 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002325 break;
2326
2327 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002328 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2329 chan->remote_tx_win = rfc.txwin_size;
2330 else
2331 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2332
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002333 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002334
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002335 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2336 chan->conn->mtu -
2337 L2CAP_EXT_HDR_SIZE -
2338 L2CAP_SDULEN_SIZE -
2339 L2CAP_FCS_SIZE);
2340 rfc.max_pdu_size = cpu_to_le16(size);
2341 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002342
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002343 rfc.retrans_timeout =
2344 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2345 rfc.monitor_timeout =
2346 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002347
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002348 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002349
2350 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2351 sizeof(rfc), (unsigned long) &rfc);
2352
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002353 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2354 chan->remote_id = efs.id;
2355 chan->remote_stype = efs.stype;
2356 chan->remote_msdu = le16_to_cpu(efs.msdu);
2357 chan->remote_flush_to =
2358 le32_to_cpu(efs.flush_to);
2359 chan->remote_acc_lat =
2360 le32_to_cpu(efs.acc_lat);
2361 chan->remote_sdu_itime =
2362 le32_to_cpu(efs.sdu_itime);
2363 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2364 sizeof(efs), (unsigned long) &efs);
2365 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002366 break;
2367
2368 case L2CAP_MODE_STREAMING:
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002369 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2370 chan->conn->mtu -
2371 L2CAP_EXT_HDR_SIZE -
2372 L2CAP_SDULEN_SIZE -
2373 L2CAP_FCS_SIZE);
2374 rfc.max_pdu_size = cpu_to_le16(size);
2375 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002376
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002377 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002378
2379 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2380 sizeof(rfc), (unsigned long) &rfc);
2381
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002382 break;
2383
2384 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002385 result = L2CAP_CONF_UNACCEPT;
2386
2387 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002388 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002389 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002390
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002391 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002392 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002393 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002394 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002395 rsp->result = cpu_to_le16(result);
2396 rsp->flags = cpu_to_le16(0x0000);
2397
2398 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399}
2400
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002401static 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 -03002402{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002403 struct l2cap_conf_req *req = data;
2404 void *ptr = req->data;
2405 int type, olen;
2406 unsigned long val;
Mat Martineau36e999a2011-12-08 17:23:21 -08002407 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002408 struct l2cap_conf_efs efs;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002409
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002410 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002411
2412 while (len >= L2CAP_CONF_OPT_SIZE) {
2413 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2414
2415 switch (type) {
2416 case L2CAP_CONF_MTU:
2417 if (val < L2CAP_DEFAULT_MIN_MTU) {
2418 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002419 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002420 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002421 chan->imtu = val;
2422 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002423 break;
2424
2425 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002426 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002427 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002428 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002429 break;
2430
2431 case L2CAP_CONF_RFC:
2432 if (olen == sizeof(rfc))
2433 memcpy(&rfc, (void *)val, olen);
2434
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002435 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002436 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002437 return -ECONNREFUSED;
2438
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002439 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002440
2441 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2442 sizeof(rfc), (unsigned long) &rfc);
2443 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002444
2445 case L2CAP_CONF_EWS:
2446 chan->tx_win = min_t(u16, val,
2447 L2CAP_DEFAULT_EXT_WINDOW);
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002448 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2449 chan->tx_win);
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002450 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002451
2452 case L2CAP_CONF_EFS:
2453 if (olen == sizeof(efs))
2454 memcpy(&efs, (void *)val, olen);
2455
2456 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2457 efs.stype != L2CAP_SERV_NOTRAFIC &&
2458 efs.stype != chan->local_stype)
2459 return -ECONNREFUSED;
2460
2461 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2462 sizeof(efs), (unsigned long) &efs);
2463 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002464 }
2465 }
2466
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002467 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002468 return -ECONNREFUSED;
2469
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002470 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002471
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002472 if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002473 switch (rfc.mode) {
2474 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002475 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2476 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2477 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002478
2479 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2480 chan->local_msdu = le16_to_cpu(efs.msdu);
2481 chan->local_sdu_itime =
2482 le32_to_cpu(efs.sdu_itime);
2483 chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
2484 chan->local_flush_to =
2485 le32_to_cpu(efs.flush_to);
2486 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002487 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002488
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002489 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002490 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002491 }
2492 }
2493
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002494 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002495 req->flags = cpu_to_le16(0x0000);
2496
2497 return ptr - data;
2498}
2499
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002500static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501{
2502 struct l2cap_conf_rsp *rsp = data;
2503 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002505 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002507 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002508 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002509 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510
2511 return ptr - data;
2512}
2513
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002514void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002515{
2516 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002517 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002518 u8 buf[128];
2519
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002520 rsp.scid = cpu_to_le16(chan->dcid);
2521 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002522 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2523 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2524 l2cap_send_cmd(conn, chan->ident,
2525 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2526
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002527 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002528 return;
2529
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002530 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2531 l2cap_build_conf_req(chan, buf), buf);
2532 chan->num_conf_req++;
2533}
2534
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002535static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002536{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002537 int type, olen;
2538 unsigned long val;
2539 struct l2cap_conf_rfc rfc;
2540
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002541 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002542
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002543 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002544 return;
2545
2546 while (len >= L2CAP_CONF_OPT_SIZE) {
2547 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2548
2549 switch (type) {
2550 case L2CAP_CONF_RFC:
2551 if (olen == sizeof(rfc))
2552 memcpy(&rfc, (void *)val, olen);
2553 goto done;
2554 }
2555 }
2556
Mat Martineau36e999a2011-12-08 17:23:21 -08002557 /* Use sane default values in case a misbehaving remote device
2558 * did not send an RFC option.
2559 */
2560 rfc.mode = chan->mode;
2561 rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
2562 rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
2563 rfc.max_pdu_size = cpu_to_le16(chan->imtu);
2564
2565 BT_ERR("Expected RFC option was not found, using defaults");
2566
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002567done:
2568 switch (rfc.mode) {
2569 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002570 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2571 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2572 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002573 break;
2574 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002575 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002576 }
2577}
2578
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002579static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2580{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002581 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002582
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002583 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002584 return 0;
2585
2586 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2587 cmd->ident == conn->info_ident) {
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02002588 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002589
2590 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002591 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002592
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002593 l2cap_conn_start(conn);
2594 }
2595
2596 return 0;
2597}
2598
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2600{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2602 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002603 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002604 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002605 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606
2607 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002608 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609
2610 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2611
2612 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002613 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2614 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615 result = L2CAP_CR_BAD_PSM;
2616 goto sendresp;
2617 }
2618
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002619 parent = pchan->sk;
2620
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002621 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002622 lock_sock(parent);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002623
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002624 /* Check if the ACL is secure enough (if not SDP) */
2625 if (psm != cpu_to_le16(0x0001) &&
2626 !hci_conn_check_link_mode(conn->hcon)) {
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002627 conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002628 result = L2CAP_CR_SEC_BLOCK;
2629 goto response;
2630 }
2631
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 result = L2CAP_CR_NO_MEM;
2633
2634 /* Check for backlog size */
2635 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002636 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637 goto response;
2638 }
2639
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002640 chan = pchan->ops->new_connection(pchan->data);
2641 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642 goto response;
2643
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002644 sk = chan->sk;
2645
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002647 if (__l2cap_get_chan_by_dcid(conn, scid)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002649 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650 goto response;
2651 }
2652
2653 hci_conn_hold(conn->hcon);
2654
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655 bacpy(&bt_sk(sk)->src, conn->src);
2656 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002657 chan->psm = psm;
2658 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002660 bt_accept_enqueue(parent, sk);
2661
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02002662 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002663
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002664 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002666 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002668 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669
Marcel Holtmann984947d2009-02-06 23:35:19 +01002670 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02002671 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002672 if (bt_sk(sk)->defer_setup) {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02002673 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002674 result = L2CAP_CR_PEND;
2675 status = L2CAP_CS_AUTHOR_PEND;
2676 parent->sk_data_ready(parent, 0);
2677 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02002678 __l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002679 result = L2CAP_CR_SUCCESS;
2680 status = L2CAP_CS_NO_INFO;
2681 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002682 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02002683 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002684 result = L2CAP_CR_PEND;
2685 status = L2CAP_CS_AUTHEN_PEND;
2686 }
2687 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02002688 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002689 result = L2CAP_CR_PEND;
2690 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691 }
2692
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693response:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002694 release_sock(parent);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002695 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696
2697sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002698 rsp.scid = cpu_to_le16(scid);
2699 rsp.dcid = cpu_to_le16(dcid);
2700 rsp.result = cpu_to_le16(result);
2701 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002703
2704 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2705 struct l2cap_info_req info;
2706 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2707
2708 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2709 conn->info_ident = l2cap_get_ident(conn);
2710
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02002711 schedule_delayed_work(&conn->info_timer,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002712 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2713
2714 l2cap_send_cmd(conn, conn->info_ident,
2715 L2CAP_INFO_REQ, sizeof(info), &info);
2716 }
2717
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002718 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002719 result == L2CAP_CR_SUCCESS) {
2720 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002721 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002722 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002723 l2cap_build_conf_req(chan, buf), buf);
2724 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002725 }
2726
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727 return 0;
2728}
2729
2730static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2731{
2732 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2733 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002734 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735 struct sock *sk;
2736 u8 req[128];
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002737 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738
2739 scid = __le16_to_cpu(rsp->scid);
2740 dcid = __le16_to_cpu(rsp->dcid);
2741 result = __le16_to_cpu(rsp->result);
2742 status = __le16_to_cpu(rsp->status);
2743
Andrei Emeltchenko1b009c92012-02-21 12:54:54 +02002744 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
2745 dcid, scid, result, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002747 mutex_lock(&conn->chan_lock);
2748
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749 if (scid) {
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002750 chan = __l2cap_get_chan_by_scid(conn, scid);
2751 if (!chan) {
2752 err = -EFAULT;
2753 goto unlock;
2754 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755 } else {
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002756 chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
2757 if (!chan) {
2758 err = -EFAULT;
2759 goto unlock;
2760 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 }
2762
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002763 err = 0;
2764
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002765 sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002766 lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002767
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768 switch (result) {
2769 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002770 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002771 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002772 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002773 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002774
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002775 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002776 break;
2777
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002779 l2cap_build_conf_req(chan, req), req);
2780 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781 break;
2782
2783 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002784 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 break;
2786
2787 default:
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002788 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789 break;
2790 }
2791
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002792 release_sock(sk);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002793
2794unlock:
2795 mutex_unlock(&conn->chan_lock);
2796
2797 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798}
2799
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002800static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002801{
2802 /* FCS is enabled only in ERTM or streaming mode, if one or both
2803 * sides request it.
2804 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002805 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002806 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002807 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002808 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002809}
2810
Al Viro88219a02007-07-29 00:17:25 -07002811static 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 -07002812{
2813 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2814 u16 dcid, flags;
2815 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002816 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002818 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819
2820 dcid = __le16_to_cpu(req->dcid);
2821 flags = __le16_to_cpu(req->flags);
2822
2823 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2824
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002825 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002826 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002827 return -ENOENT;
2828
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002829 sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002830 lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002831
David S. Miller033b1142011-07-21 13:38:42 -07002832 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002833 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002834
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002835 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2836 rej.scid = cpu_to_le16(chan->scid);
2837 rej.dcid = cpu_to_le16(chan->dcid);
2838
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002839 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2840 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002841 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002842 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002843
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002844 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002845 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002846 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002847 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002848 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002849 L2CAP_CONF_REJECT, flags), rsp);
2850 goto unlock;
2851 }
2852
2853 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002854 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2855 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856
2857 if (flags & 0x0001) {
2858 /* Incomplete config. Send empty response. */
2859 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002860 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002861 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862 goto unlock;
2863 }
2864
2865 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002866 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002867 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002868 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002870 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002872 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002873 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002874
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002875 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002876 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002877
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002878 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002879 goto unlock;
2880
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002881 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002882 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002883
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002884 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002885
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002886 chan->next_tx_seq = 0;
2887 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002888 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002889 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002890 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002891
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02002892 l2cap_chan_ready(chan);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002893 goto unlock;
2894 }
2895
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002896 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002897 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002898 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002899 l2cap_build_conf_req(chan, buf), buf);
2900 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901 }
2902
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002903 /* Got Conf Rsp PENDING from remote side and asume we sent
2904 Conf Rsp PENDING in the code above */
2905 if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
2906 test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2907
2908 /* check compatibility */
2909
2910 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2911 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2912
2913 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002914 l2cap_build_conf_rsp(chan, rsp,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002915 L2CAP_CONF_SUCCESS, 0x0000), rsp);
2916 }
2917
Linus Torvalds1da177e2005-04-16 15:20:36 -07002918unlock:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002919 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920 return 0;
2921}
2922
2923static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2924{
2925 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2926 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002927 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002929 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930
2931 scid = __le16_to_cpu(rsp->scid);
2932 flags = __le16_to_cpu(rsp->flags);
2933 result = __le16_to_cpu(rsp->result);
2934
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002935 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2936 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002937
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002938 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002939 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940 return 0;
2941
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002942 sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002943 lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002944
Linus Torvalds1da177e2005-04-16 15:20:36 -07002945 switch (result) {
2946 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002947 l2cap_conf_rfc_get(chan, rsp->data, len);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002948 clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949 break;
2950
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002951 case L2CAP_CONF_PENDING:
2952 set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
2953
2954 if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2955 char buf[64];
2956
2957 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2958 buf, &result);
2959 if (len < 0) {
2960 l2cap_send_disconn_req(conn, chan, ECONNRESET);
2961 goto done;
2962 }
2963
2964 /* check compatibility */
2965
2966 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2967 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2968
2969 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002970 l2cap_build_conf_rsp(chan, buf,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002971 L2CAP_CONF_SUCCESS, 0x0000), buf);
2972 }
2973 goto done;
2974
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002976 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002977 char req[64];
2978
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002979 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002980 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002981 goto done;
2982 }
2983
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002984 /* throw out any old stored conf requests */
2985 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002986 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2987 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002988 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002989 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002990 goto done;
2991 }
2992
2993 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2994 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002995 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002996 if (result != L2CAP_CONF_SUCCESS)
2997 goto done;
2998 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999 }
3000
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09003001 default:
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +02003002 __l2cap_chan_set_err(chan, ECONNRESET);
3003
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01003004 __set_chan_timer(chan,
3005 msecs_to_jiffies(L2CAP_DISC_REJ_TIMEOUT));
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003006 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 goto done;
3008 }
3009
3010 if (flags & 0x01)
3011 goto done;
3012
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003013 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003015 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003016 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003017
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003018 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003019 chan->next_tx_seq = 0;
3020 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03003021 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003022 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003023 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003024
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02003025 l2cap_chan_ready(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026 }
3027
3028done:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003029 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030 return 0;
3031}
3032
3033static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3034{
3035 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3036 struct l2cap_disconn_rsp rsp;
3037 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003038 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039 struct sock *sk;
3040
3041 scid = __le16_to_cpu(req->scid);
3042 dcid = __le16_to_cpu(req->dcid);
3043
3044 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3045
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003046 mutex_lock(&conn->chan_lock);
3047
3048 chan = __l2cap_get_chan_by_scid(conn, dcid);
3049 if (!chan) {
3050 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003051 return 0;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003052 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003054 sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003055 lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003056
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003057 rsp.dcid = cpu_to_le16(chan->scid);
3058 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3060
3061 sk->sk_shutdown = SHUTDOWN_MASK;
3062
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003063 l2cap_chan_del(chan, ECONNRESET);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003064 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003066 chan->ops->close(chan->data);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003067
3068 mutex_unlock(&conn->chan_lock);
3069
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070 return 0;
3071}
3072
3073static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3074{
3075 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3076 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003077 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078 struct sock *sk;
3079
3080 scid = __le16_to_cpu(rsp->scid);
3081 dcid = __le16_to_cpu(rsp->dcid);
3082
3083 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3084
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003085 mutex_lock(&conn->chan_lock);
3086
3087 chan = __l2cap_get_chan_by_scid(conn, scid);
3088 if (!chan) {
3089 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003090 return 0;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003091 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003092
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003093 sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003094 lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003095
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003096 l2cap_chan_del(chan, 0);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003097 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003099 chan->ops->close(chan->data);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003100
3101 mutex_unlock(&conn->chan_lock);
3102
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103 return 0;
3104}
3105
3106static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3107{
3108 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109 u16 type;
3110
3111 type = __le16_to_cpu(req->type);
3112
3113 BT_DBG("type 0x%4.4x", type);
3114
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003115 if (type == L2CAP_IT_FEAT_MASK) {
3116 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003117 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003118 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3119 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3120 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003121 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003122 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3123 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003124 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003125 feat_mask |= L2CAP_FEAT_EXT_FLOW
3126 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003127
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003128 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003129 l2cap_send_cmd(conn, cmd->ident,
3130 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003131 } else if (type == L2CAP_IT_FIXED_CHAN) {
3132 u8 buf[12];
3133 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
Mat Martineau50a147c2011-11-02 16:18:34 -07003134
3135 if (enable_hs)
3136 l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
3137 else
3138 l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
3139
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003140 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3141 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003142 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003143 l2cap_send_cmd(conn, cmd->ident,
3144 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003145 } else {
3146 struct l2cap_info_rsp rsp;
3147 rsp.type = cpu_to_le16(type);
3148 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3149 l2cap_send_cmd(conn, cmd->ident,
3150 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3151 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152
3153 return 0;
3154}
3155
3156static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3157{
3158 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3159 u16 type, result;
3160
3161 type = __le16_to_cpu(rsp->type);
3162 result = __le16_to_cpu(rsp->result);
3163
3164 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3165
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003166 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3167 if (cmd->ident != conn->info_ident ||
3168 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3169 return 0;
3170
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02003171 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003172
Ville Tervoadb08ed2010-08-04 09:43:33 +03003173 if (result != L2CAP_IR_SUCCESS) {
3174 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3175 conn->info_ident = 0;
3176
3177 l2cap_conn_start(conn);
3178
3179 return 0;
3180 }
3181
Marcel Holtmann984947d2009-02-06 23:35:19 +01003182 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003183 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003184
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003185 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003186 struct l2cap_info_req req;
3187 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3188
3189 conn->info_ident = l2cap_get_ident(conn);
3190
3191 l2cap_send_cmd(conn, conn->info_ident,
3192 L2CAP_INFO_REQ, sizeof(req), &req);
3193 } else {
3194 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3195 conn->info_ident = 0;
3196
3197 l2cap_conn_start(conn);
3198 }
3199 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003200 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003201 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003202
3203 l2cap_conn_start(conn);
3204 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003205
Linus Torvalds1da177e2005-04-16 15:20:36 -07003206 return 0;
3207}
3208
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003209static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3210 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3211 void *data)
3212{
3213 struct l2cap_create_chan_req *req = data;
3214 struct l2cap_create_chan_rsp rsp;
3215 u16 psm, scid;
3216
3217 if (cmd_len != sizeof(*req))
3218 return -EPROTO;
3219
3220 if (!enable_hs)
3221 return -EINVAL;
3222
3223 psm = le16_to_cpu(req->psm);
3224 scid = le16_to_cpu(req->scid);
3225
3226 BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3227
3228 /* Placeholder: Always reject */
3229 rsp.dcid = 0;
3230 rsp.scid = cpu_to_le16(scid);
3231 rsp.result = L2CAP_CR_NO_MEM;
3232 rsp.status = L2CAP_CS_NO_INFO;
3233
3234 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3235 sizeof(rsp), &rsp);
3236
3237 return 0;
3238}
3239
3240static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3241 struct l2cap_cmd_hdr *cmd, void *data)
3242{
3243 BT_DBG("conn %p", conn);
3244
3245 return l2cap_connect_rsp(conn, cmd, data);
3246}
3247
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003248static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
3249 u16 icid, u16 result)
3250{
3251 struct l2cap_move_chan_rsp rsp;
3252
3253 BT_DBG("icid %d, result %d", icid, result);
3254
3255 rsp.icid = cpu_to_le16(icid);
3256 rsp.result = cpu_to_le16(result);
3257
3258 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
3259}
3260
3261static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
3262 struct l2cap_chan *chan, u16 icid, u16 result)
3263{
3264 struct l2cap_move_chan_cfm cfm;
3265 u8 ident;
3266
3267 BT_DBG("icid %d, result %d", icid, result);
3268
3269 ident = l2cap_get_ident(conn);
3270 if (chan)
3271 chan->ident = ident;
3272
3273 cfm.icid = cpu_to_le16(icid);
3274 cfm.result = cpu_to_le16(result);
3275
3276 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
3277}
3278
3279static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
3280 u16 icid)
3281{
3282 struct l2cap_move_chan_cfm_rsp rsp;
3283
3284 BT_DBG("icid %d", icid);
3285
3286 rsp.icid = cpu_to_le16(icid);
3287 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
3288}
3289
3290static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
3291 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3292{
3293 struct l2cap_move_chan_req *req = data;
3294 u16 icid = 0;
3295 u16 result = L2CAP_MR_NOT_ALLOWED;
3296
3297 if (cmd_len != sizeof(*req))
3298 return -EPROTO;
3299
3300 icid = le16_to_cpu(req->icid);
3301
3302 BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
3303
3304 if (!enable_hs)
3305 return -EINVAL;
3306
3307 /* Placeholder: Always refuse */
3308 l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
3309
3310 return 0;
3311}
3312
3313static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
3314 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3315{
3316 struct l2cap_move_chan_rsp *rsp = data;
3317 u16 icid, result;
3318
3319 if (cmd_len != sizeof(*rsp))
3320 return -EPROTO;
3321
3322 icid = le16_to_cpu(rsp->icid);
3323 result = le16_to_cpu(rsp->result);
3324
3325 BT_DBG("icid %d, result %d", icid, result);
3326
3327 /* Placeholder: Always unconfirmed */
3328 l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
3329
3330 return 0;
3331}
3332
3333static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
3334 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3335{
3336 struct l2cap_move_chan_cfm *cfm = data;
3337 u16 icid, result;
3338
3339 if (cmd_len != sizeof(*cfm))
3340 return -EPROTO;
3341
3342 icid = le16_to_cpu(cfm->icid);
3343 result = le16_to_cpu(cfm->result);
3344
3345 BT_DBG("icid %d, result %d", icid, result);
3346
3347 l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
3348
3349 return 0;
3350}
3351
3352static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
3353 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3354{
3355 struct l2cap_move_chan_cfm_rsp *rsp = data;
3356 u16 icid;
3357
3358 if (cmd_len != sizeof(*rsp))
3359 return -EPROTO;
3360
3361 icid = le16_to_cpu(rsp->icid);
3362
3363 BT_DBG("icid %d", icid);
3364
3365 return 0;
3366}
3367
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003368static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02003369 u16 to_multiplier)
3370{
3371 u16 max_latency;
3372
3373 if (min > max || min < 6 || max > 3200)
3374 return -EINVAL;
3375
3376 if (to_multiplier < 10 || to_multiplier > 3200)
3377 return -EINVAL;
3378
3379 if (max >= to_multiplier * 8)
3380 return -EINVAL;
3381
3382 max_latency = (to_multiplier * 8 / max) - 1;
3383 if (latency > 499 || latency > max_latency)
3384 return -EINVAL;
3385
3386 return 0;
3387}
3388
3389static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3390 struct l2cap_cmd_hdr *cmd, u8 *data)
3391{
3392 struct hci_conn *hcon = conn->hcon;
3393 struct l2cap_conn_param_update_req *req;
3394 struct l2cap_conn_param_update_rsp rsp;
3395 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003396 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02003397
3398 if (!(hcon->link_mode & HCI_LM_MASTER))
3399 return -EINVAL;
3400
3401 cmd_len = __le16_to_cpu(cmd->len);
3402 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3403 return -EPROTO;
3404
3405 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003406 min = __le16_to_cpu(req->min);
3407 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02003408 latency = __le16_to_cpu(req->latency);
3409 to_multiplier = __le16_to_cpu(req->to_multiplier);
3410
3411 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3412 min, max, latency, to_multiplier);
3413
3414 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003415
3416 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
3417 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02003418 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3419 else
3420 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3421
3422 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3423 sizeof(rsp), &rsp);
3424
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003425 if (!err)
3426 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
3427
Claudio Takahaside731152011-02-11 19:28:55 -02003428 return 0;
3429}
3430
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003431static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
3432 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
3433{
3434 int err = 0;
3435
3436 switch (cmd->code) {
3437 case L2CAP_COMMAND_REJ:
3438 l2cap_command_rej(conn, cmd, data);
3439 break;
3440
3441 case L2CAP_CONN_REQ:
3442 err = l2cap_connect_req(conn, cmd, data);
3443 break;
3444
3445 case L2CAP_CONN_RSP:
3446 err = l2cap_connect_rsp(conn, cmd, data);
3447 break;
3448
3449 case L2CAP_CONF_REQ:
3450 err = l2cap_config_req(conn, cmd, cmd_len, data);
3451 break;
3452
3453 case L2CAP_CONF_RSP:
3454 err = l2cap_config_rsp(conn, cmd, data);
3455 break;
3456
3457 case L2CAP_DISCONN_REQ:
3458 err = l2cap_disconnect_req(conn, cmd, data);
3459 break;
3460
3461 case L2CAP_DISCONN_RSP:
3462 err = l2cap_disconnect_rsp(conn, cmd, data);
3463 break;
3464
3465 case L2CAP_ECHO_REQ:
3466 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3467 break;
3468
3469 case L2CAP_ECHO_RSP:
3470 break;
3471
3472 case L2CAP_INFO_REQ:
3473 err = l2cap_information_req(conn, cmd, data);
3474 break;
3475
3476 case L2CAP_INFO_RSP:
3477 err = l2cap_information_rsp(conn, cmd, data);
3478 break;
3479
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003480 case L2CAP_CREATE_CHAN_REQ:
3481 err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3482 break;
3483
3484 case L2CAP_CREATE_CHAN_RSP:
3485 err = l2cap_create_channel_rsp(conn, cmd, data);
3486 break;
3487
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003488 case L2CAP_MOVE_CHAN_REQ:
3489 err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
3490 break;
3491
3492 case L2CAP_MOVE_CHAN_RSP:
3493 err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
3494 break;
3495
3496 case L2CAP_MOVE_CHAN_CFM:
3497 err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
3498 break;
3499
3500 case L2CAP_MOVE_CHAN_CFM_RSP:
3501 err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
3502 break;
3503
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003504 default:
3505 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3506 err = -EINVAL;
3507 break;
3508 }
3509
3510 return err;
3511}
3512
3513static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3514 struct l2cap_cmd_hdr *cmd, u8 *data)
3515{
3516 switch (cmd->code) {
3517 case L2CAP_COMMAND_REJ:
3518 return 0;
3519
3520 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003521 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003522
3523 case L2CAP_CONN_PARAM_UPDATE_RSP:
3524 return 0;
3525
3526 default:
3527 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3528 return -EINVAL;
3529 }
3530}
3531
3532static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3533 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534{
3535 u8 *data = skb->data;
3536 int len = skb->len;
3537 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003538 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539
3540 l2cap_raw_recv(conn, skb);
3541
3542 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003543 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003544 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3545 data += L2CAP_CMD_HDR_SIZE;
3546 len -= L2CAP_CMD_HDR_SIZE;
3547
Al Viro88219a02007-07-29 00:17:25 -07003548 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003549
Al Viro88219a02007-07-29 00:17:25 -07003550 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 -07003551
Al Viro88219a02007-07-29 00:17:25 -07003552 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003553 BT_DBG("corrupted command");
3554 break;
3555 }
3556
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003557 if (conn->hcon->type == LE_LINK)
3558 err = l2cap_le_sig_cmd(conn, &cmd, data);
3559 else
3560 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003561
3562 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003563 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003564
3565 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003566
3567 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003568 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003569 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3570 }
3571
Al Viro88219a02007-07-29 00:17:25 -07003572 data += cmd_len;
3573 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574 }
3575
3576 kfree_skb(skb);
3577}
3578
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003579static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003580{
3581 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003582 int hdr_size;
3583
3584 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3585 hdr_size = L2CAP_EXT_HDR_SIZE;
3586 else
3587 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003588
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003589 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003590 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003591 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3592 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3593
3594 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003595 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003596 }
3597 return 0;
3598}
3599
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003600static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003601{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003602 u32 control = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003603
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003604 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003605
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003606 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003607
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003608 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003609 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003610 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003611 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003612 }
3613
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003614 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003615 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003616
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003617 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003618
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003619 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003620 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003621 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003622 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003623 }
3624}
3625
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003626static 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 -03003627{
3628 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003629 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003630
3631 bt_cb(skb)->tx_seq = tx_seq;
3632 bt_cb(skb)->sar = sar;
3633
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003634 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003635
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003636 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003637
Szymon Janc039d9572011-11-16 09:32:19 +01003638 while (next_skb) {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003639 if (bt_cb(next_skb)->tx_seq == tx_seq)
3640 return -EINVAL;
3641
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003642 next_tx_seq_offset = __seq_offset(chan,
3643 bt_cb(next_skb)->tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003644
3645 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003646 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003647 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003648 }
3649
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003650 if (skb_queue_is_last(&chan->srej_q, next_skb))
Szymon Janc039d9572011-11-16 09:32:19 +01003651 next_skb = NULL;
3652 else
3653 next_skb = skb_queue_next(&chan->srej_q, next_skb);
3654 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003655
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003656 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003657
3658 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003659}
3660
Mat Martineau84084a32011-07-22 14:54:00 -07003661static void append_skb_frag(struct sk_buff *skb,
3662 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003663{
Mat Martineau84084a32011-07-22 14:54:00 -07003664 /* skb->len reflects data in skb as well as all fragments
3665 * skb->data_len reflects only data in fragments
3666 */
3667 if (!skb_has_frag_list(skb))
3668 skb_shinfo(skb)->frag_list = new_frag;
3669
3670 new_frag->next = NULL;
3671
3672 (*last_frag)->next = new_frag;
3673 *last_frag = new_frag;
3674
3675 skb->len += new_frag->len;
3676 skb->data_len += new_frag->len;
3677 skb->truesize += new_frag->truesize;
3678}
3679
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003680static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
Mat Martineau84084a32011-07-22 14:54:00 -07003681{
3682 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003683
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003684 switch (__get_ctrl_sar(chan, control)) {
3685 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003686 if (chan->sdu)
3687 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003688
Mat Martineau84084a32011-07-22 14:54:00 -07003689 err = chan->ops->recv(chan->data, skb);
3690 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003691
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003692 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003693 if (chan->sdu)
3694 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003695
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003696 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003697 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003698
Mat Martineau84084a32011-07-22 14:54:00 -07003699 if (chan->sdu_len > chan->imtu) {
3700 err = -EMSGSIZE;
3701 break;
3702 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003703
Mat Martineau84084a32011-07-22 14:54:00 -07003704 if (skb->len >= chan->sdu_len)
3705 break;
3706
3707 chan->sdu = skb;
3708 chan->sdu_last_frag = skb;
3709
3710 skb = NULL;
3711 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003712 break;
3713
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003714 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003715 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003716 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003717
Mat Martineau84084a32011-07-22 14:54:00 -07003718 append_skb_frag(chan->sdu, skb,
3719 &chan->sdu_last_frag);
3720 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003721
Mat Martineau84084a32011-07-22 14:54:00 -07003722 if (chan->sdu->len >= chan->sdu_len)
3723 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003724
Mat Martineau84084a32011-07-22 14:54:00 -07003725 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003726 break;
3727
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003728 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003729 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003730 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003731
Mat Martineau84084a32011-07-22 14:54:00 -07003732 append_skb_frag(chan->sdu, skb,
3733 &chan->sdu_last_frag);
3734 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003735
Mat Martineau84084a32011-07-22 14:54:00 -07003736 if (chan->sdu->len != chan->sdu_len)
3737 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003738
Mat Martineau84084a32011-07-22 14:54:00 -07003739 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003740
Mat Martineau84084a32011-07-22 14:54:00 -07003741 if (!err) {
3742 /* Reassembly complete */
3743 chan->sdu = NULL;
3744 chan->sdu_last_frag = NULL;
3745 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003746 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003747 break;
3748 }
3749
Mat Martineau84084a32011-07-22 14:54:00 -07003750 if (err) {
3751 kfree_skb(skb);
3752 kfree_skb(chan->sdu);
3753 chan->sdu = NULL;
3754 chan->sdu_last_frag = NULL;
3755 chan->sdu_len = 0;
3756 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003757
Mat Martineau84084a32011-07-22 14:54:00 -07003758 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003759}
3760
Mat Martineau26f880d2011-07-07 09:39:01 -07003761static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003762{
Mat Martineau26f880d2011-07-07 09:39:01 -07003763 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003764
Mat Martineau26f880d2011-07-07 09:39:01 -07003765 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3766
Szymon Janc77f918b2012-01-11 10:59:48 +01003767 __set_ack_timer(chan);
Mat Martineau26f880d2011-07-07 09:39:01 -07003768}
3769
3770static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3771{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003772 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003773
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003774 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003775 goto done;
3776
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003777 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003778 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003779 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003780 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003781 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003782
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003783 __clear_retrans_timer(chan);
3784 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003785
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003786 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003787
3788done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003789 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3790 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003791
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003792 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003793}
3794
Mat Martineaue3281402011-07-07 09:39:02 -07003795void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003796{
Mat Martineaue3281402011-07-07 09:39:02 -07003797 if (chan->mode == L2CAP_MODE_ERTM) {
3798 if (busy)
3799 l2cap_ertm_enter_local_busy(chan);
3800 else
3801 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003802 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003803}
3804
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003805static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003806{
3807 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003808 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003809
Mat Martineaue3281402011-07-07 09:39:02 -07003810 while ((skb = skb_peek(&chan->srej_q)) &&
3811 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3812 int err;
3813
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003814 if (bt_cb(skb)->tx_seq != tx_seq)
3815 break;
3816
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003817 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003818 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003819 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003820
3821 if (err < 0) {
3822 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3823 break;
3824 }
3825
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003826 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
3827 tx_seq = __next_seq(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003828 }
3829}
3830
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003831static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003832{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003833 struct srej_list *l, *tmp;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003834 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003835
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003836 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003837 if (l->tx_seq == tx_seq) {
3838 list_del(&l->list);
3839 kfree(l);
3840 return;
3841 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003842 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003843 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003844 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003845 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003846 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003847 }
3848}
3849
Szymon Jancaef89f22011-11-16 09:32:18 +01003850static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003851{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003852 struct srej_list *new;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003853 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003854
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003855 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003856 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003857 control |= __set_reqseq(chan, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003858 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003859
3860 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Szymon Jancaef89f22011-11-16 09:32:18 +01003861 if (!new)
3862 return -ENOMEM;
3863
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003864 new->tx_seq = chan->expected_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003865
3866 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
3867
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003868 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003869 }
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003870
3871 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Szymon Jancaef89f22011-11-16 09:32:18 +01003872
3873 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003874}
3875
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003876static 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 -03003877{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003878 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003879 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003880 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003881 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003882 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003883 int err = 0;
3884
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003885 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 -03003886 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003887
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003888 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003889 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003890 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003891 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003892 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003893 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003894 }
3895
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003896 chan->expected_ack_seq = req_seq;
3897 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003898
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003899 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003900
3901 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003902 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003903 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003904 goto drop;
3905 }
3906
Szymon Janc77f918b2012-01-11 10:59:48 +01003907 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3908 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
3909 l2cap_send_ack(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003910 goto drop;
Szymon Janc77f918b2012-01-11 10:59:48 +01003911 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003912
Mat Martineau02f1b642011-06-29 14:35:19 -07003913 if (tx_seq == chan->expected_tx_seq)
3914 goto expected;
3915
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003916 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003917 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003918
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003919 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003920 struct srej_list, list);
3921 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003922 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003923 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003924
3925 list_del(&first->list);
3926 kfree(first);
3927
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003928 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003929 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003930 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003931 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003932 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003933 }
3934 } else {
3935 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003936
3937 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003938 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003939 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003940
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003941 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003942 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003943 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003944 return 0;
3945 }
3946 }
Szymon Jancaef89f22011-11-16 09:32:18 +01003947
3948 err = l2cap_send_srejframe(chan, tx_seq);
3949 if (err < 0) {
3950 l2cap_send_disconn_req(chan->conn, chan, -err);
3951 return err;
3952 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003953 }
3954 } else {
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003955 expected_tx_seq_offset = __seq_offset(chan,
3956 chan->expected_tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003957
3958 /* duplicated tx_seq */
3959 if (tx_seq_offset < expected_tx_seq_offset)
3960 goto drop;
3961
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003962 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003963
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003964 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003965
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003966 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003967 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003968
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003969 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003970 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003971
Szymon Janc0ef3ef02012-01-11 10:59:46 +01003972 /* Set P-bit only if there are some I-frames to ack. */
3973 if (__clear_ack_timer(chan))
3974 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003975
Szymon Jancaef89f22011-11-16 09:32:18 +01003976 err = l2cap_send_srejframe(chan, tx_seq);
3977 if (err < 0) {
3978 l2cap_send_disconn_req(chan->conn, chan, -err);
3979 return err;
3980 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003981 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003982 return 0;
3983
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003984expected:
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003985 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003986
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003987 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003988 bt_cb(skb)->tx_seq = tx_seq;
3989 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003990 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003991 return 0;
3992 }
3993
Mat Martineau84084a32011-07-22 14:54:00 -07003994 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003995 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
3996
Mat Martineaue3281402011-07-07 09:39:02 -07003997 if (err < 0) {
3998 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3999 return err;
4000 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03004001
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004002 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004003 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004004 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03004005 }
4006
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03004007
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004008 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
4009 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004010 l2cap_send_ack(chan);
Gustavo F. Padovan4d611e42011-06-23 19:30:48 -03004011 else
4012 __set_ack_timer(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03004013
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004014 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004015
4016drop:
4017 kfree_skb(skb);
4018 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004019}
4020
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004021static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004022{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004023 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004024 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004025
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004026 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004027 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004028
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004029 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004030 set_bit(CONN_SEND_FBIT, &chan->conn_state);
4031 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
4032 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004033 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004034 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004035
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004036 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004037 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004038 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004039 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004040 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004041
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004042 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004043 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004044
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004045 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004046 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004047
4048 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004049 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004050 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004051 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004052
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004053 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4054 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004055 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02004056 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004057 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004058 }
4059}
4060
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004061static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004062{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004063 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004064
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004065 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004066
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004067 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004068
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004069 chan->expected_ack_seq = tx_seq;
4070 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004071
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004072 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004073 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004074 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004075 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004076 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004077
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004078 if (test_bit(CONN_WAIT_F, &chan->conn_state))
4079 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004080 }
4081}
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004082static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004083{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004084 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004085
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004086 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004087
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004088 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004089
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004090 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004091 chan->expected_ack_seq = tx_seq;
4092 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004093
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004094 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004095 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004096
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004097 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004098
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004099 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004100 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004101 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004102 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004103 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004104 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004105 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004106 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004107 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004108 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004109 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004110 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004111 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004112 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004113 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004114 }
4115 }
4116}
4117
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004118static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004119{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004120 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004121
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004122 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004123
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004124 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004125 chan->expected_ack_seq = tx_seq;
4126 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004127
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004128 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004129 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004130
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004131 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004132 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004133 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004134 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004135 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004136 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004137
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004138 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004139 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004140 } else {
4141 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4142 l2cap_send_sframe(chan, rx_control);
4143 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004144}
4145
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004146static 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 -03004147{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004148 BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004149
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004150 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004151 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004152 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004153 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004154 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004155 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004156 }
4157
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004158 switch (__get_ctrl_super(chan, rx_control)) {
4159 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004160 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004161 break;
4162
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004163 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004164 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004165 break;
4166
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004167 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004168 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004169 break;
4170
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004171 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004172 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004173 break;
4174 }
4175
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004176 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004177 return 0;
4178}
4179
Szymon Janccad8f1d02012-01-23 10:06:05 +01004180static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004181{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004182 u32 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004183 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004184 int len, next_tx_seq_offset, req_seq_offset;
4185
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004186 control = __get_control(chan, skb->data);
4187 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004188 len = skb->len;
4189
4190 /*
4191 * We can just drop the corrupted I-frame here.
4192 * Receiver will miss it and start proper recovery
4193 * procedures and ask retransmission.
4194 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004195 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004196 goto drop;
4197
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004198 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004199 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004200
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004201 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004202 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004203
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004204 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004205 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004206 goto drop;
4207 }
4208
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004209 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004210
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004211 req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4212
4213 next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4214 chan->expected_ack_seq);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004215
4216 /* check for invalid req-seq */
4217 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004218 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004219 goto drop;
4220 }
4221
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004222 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004223 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004224 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004225 goto drop;
4226 }
4227
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004228 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004229 } else {
4230 if (len != 0) {
4231 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004232 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004233 goto drop;
4234 }
4235
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004236 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004237 }
4238
4239 return 0;
4240
4241drop:
4242 kfree_skb(skb);
4243 return 0;
4244}
4245
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4247{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004248 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07004249 struct sock *sk = NULL;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004250 u32 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004251 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004252 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004253
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004254 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004255 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004256 BT_DBG("unknown cid 0x%4.4x", cid);
4257 goto drop;
4258 }
4259
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004260 sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004261 lock_sock(sk);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004262
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004263 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004265 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266 goto drop;
4267
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004268 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004269 case L2CAP_MODE_BASIC:
4270 /* If socket recv buffers overflows we drop data here
4271 * which is *bad* because L2CAP has to be reliable.
4272 * But we don't have any other choice. L2CAP doesn't
4273 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004274
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004275 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004276 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004277
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004278 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004279 goto done;
4280 break;
4281
4282 case L2CAP_MODE_ERTM:
Andrei Emeltchenko5ef8cb92012-01-13 17:21:42 +02004283 l2cap_ertm_data_rcv(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004284
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004285 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004286
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004287 case L2CAP_MODE_STREAMING:
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004288 control = __get_control(chan, skb->data);
4289 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004290 len = skb->len;
4291
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004292 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004293 goto drop;
4294
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004295 if (__is_sar_start(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004296 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004297
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004298 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004299 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004300
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004301 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004302 goto drop;
4303
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004304 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004305
Mat Martineau84084a32011-07-22 14:54:00 -07004306 if (chan->expected_tx_seq != tx_seq) {
4307 /* Frame(s) missing - must discard partial SDU */
4308 kfree_skb(chan->sdu);
4309 chan->sdu = NULL;
4310 chan->sdu_last_frag = NULL;
4311 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004312
Mat Martineau84084a32011-07-22 14:54:00 -07004313 /* TODO: Notify userland of missing data */
4314 }
4315
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004316 chan->expected_tx_seq = __next_seq(chan, tx_seq);
Mat Martineau84084a32011-07-22 14:54:00 -07004317
4318 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
4319 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004320
4321 goto done;
4322
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004323 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004324 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004325 break;
4326 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004327
4328drop:
4329 kfree_skb(skb);
4330
4331done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004332 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004333 release_sock(sk);
Marcel Holtmann01394182006-07-03 10:02:46 +02004334
Linus Torvalds1da177e2005-04-16 15:20:36 -07004335 return 0;
4336}
4337
Al Viro8e036fc2007-07-29 00:16:36 -07004338static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004339{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004340 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004341 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004343 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
4344 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345 goto drop;
4346
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004347 sk = chan->sk;
4348
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004349 lock_sock(sk);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00004350
Linus Torvalds1da177e2005-04-16 15:20:36 -07004351 BT_DBG("sk %p, len %d", sk, skb->len);
4352
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004353 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354 goto drop;
4355
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004356 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357 goto drop;
4358
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004359 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004360 goto done;
4361
4362drop:
4363 kfree_skb(skb);
4364
4365done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004366 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004367 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004368 return 0;
4369}
4370
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004371static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
4372{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004373 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004374 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004375
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004376 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
4377 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004378 goto drop;
4379
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004380 sk = chan->sk;
4381
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004382 lock_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004383
4384 BT_DBG("sk %p, len %d", sk, skb->len);
4385
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004386 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004387 goto drop;
4388
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004389 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004390 goto drop;
4391
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004392 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004393 goto done;
4394
4395drop:
4396 kfree_skb(skb);
4397
4398done:
4399 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004400 release_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004401 return 0;
4402}
4403
Linus Torvalds1da177e2005-04-16 15:20:36 -07004404static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4405{
4406 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004407 u16 cid, len;
4408 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004409
4410 skb_pull(skb, L2CAP_HDR_SIZE);
4411 cid = __le16_to_cpu(lh->cid);
4412 len = __le16_to_cpu(lh->len);
4413
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004414 if (len != skb->len) {
4415 kfree_skb(skb);
4416 return;
4417 }
4418
Linus Torvalds1da177e2005-04-16 15:20:36 -07004419 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4420
4421 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004422 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004423 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424 l2cap_sig_channel(conn, skb);
4425 break;
4426
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004427 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004428 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429 skb_pull(skb, 2);
4430 l2cap_conless_channel(conn, psm, skb);
4431 break;
4432
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004433 case L2CAP_CID_LE_DATA:
4434 l2cap_att_channel(conn, cid, skb);
4435 break;
4436
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004437 case L2CAP_CID_SMP:
4438 if (smp_sig_channel(conn, skb))
4439 l2cap_conn_del(conn->hcon, EACCES);
4440 break;
4441
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442 default:
4443 l2cap_data_channel(conn, cid, skb);
4444 break;
4445 }
4446}
4447
4448/* ---- L2CAP interface with lower layer (HCI) ---- */
4449
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004450int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004451{
4452 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004453 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454
Linus Torvalds1da177e2005-04-16 15:20:36 -07004455 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4456
4457 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004458 read_lock(&chan_list_lock);
4459 list_for_each_entry(c, &chan_list, global_l) {
4460 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004461
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004462 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004463 continue;
4464
4465 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004466 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004467 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004468 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004469 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004470 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4471 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004472 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004473 lm2 |= HCI_LM_MASTER;
4474 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004475 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004476 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004477
4478 return exact ? lm1 : lm2;
4479}
4480
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004481int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004482{
Marcel Holtmann01394182006-07-03 10:02:46 +02004483 struct l2cap_conn *conn;
4484
Linus Torvalds1da177e2005-04-16 15:20:36 -07004485 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4486
Linus Torvalds1da177e2005-04-16 15:20:36 -07004487 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004488 conn = l2cap_conn_add(hcon, status);
4489 if (conn)
4490 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004491 } else
Joe Perchese1750722011-06-29 18:18:29 -07004492 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493
4494 return 0;
4495}
4496
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004497int l2cap_disconn_ind(struct hci_conn *hcon)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004498{
4499 struct l2cap_conn *conn = hcon->l2cap_data;
4500
4501 BT_DBG("hcon %p", hcon);
4502
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004503 if (!conn)
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02004504 return HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01004505 return conn->disc_reason;
4506}
4507
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004508int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004509{
4510 BT_DBG("hcon %p reason %d", hcon, reason);
4511
Joe Perchese1750722011-06-29 18:18:29 -07004512 l2cap_conn_del(hcon, bt_to_errno(reason));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004513 return 0;
4514}
4515
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004516static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004517{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004518 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004519 return;
4520
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004521 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004522 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004523 __clear_chan_timer(chan);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004524 __set_chan_timer(chan,
4525 msecs_to_jiffies(L2CAP_ENC_TIMEOUT));
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004526 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004527 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004528 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004529 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004530 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004531 }
4532}
4533
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004534int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004535{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004536 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004537 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004538
Marcel Holtmann01394182006-07-03 10:02:46 +02004539 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004540 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004541
Linus Torvalds1da177e2005-04-16 15:20:36 -07004542 BT_DBG("conn %p", conn);
4543
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004544 if (hcon->type == LE_LINK) {
4545 smp_distribute_keys(conn, 0);
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02004546 cancel_delayed_work(&conn->security_timer);
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004547 }
4548
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004549 mutex_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004551 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004552 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004553
Linus Torvalds1da177e2005-04-16 15:20:36 -07004554 bh_lock_sock(sk);
4555
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004556 BT_DBG("chan->scid %d", chan->scid);
4557
4558 if (chan->scid == L2CAP_CID_LE_DATA) {
4559 if (!status && encrypt) {
4560 chan->sec_level = hcon->sec_level;
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02004561 l2cap_chan_ready(chan);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004562 }
4563
4564 bh_unlock_sock(sk);
4565 continue;
4566 }
4567
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004568 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004569 bh_unlock_sock(sk);
4570 continue;
4571 }
4572
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004573 if (!status && (chan->state == BT_CONNECTED ||
4574 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004575 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004576 bh_unlock_sock(sk);
4577 continue;
4578 }
4579
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004580 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004581 if (!status) {
4582 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004583 req.scid = cpu_to_le16(chan->scid);
4584 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004585
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004586 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004587 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004588
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004589 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004590 L2CAP_CONN_REQ, sizeof(req), &req);
4591 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004592 __clear_chan_timer(chan);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004593 __set_chan_timer(chan,
4594 msecs_to_jiffies(L2CAP_DISC_TIMEOUT));
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004595 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004596 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004597 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004598 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004599
4600 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004601 if (bt_sk(sk)->defer_setup) {
4602 struct sock *parent = bt_sk(sk)->parent;
4603 res = L2CAP_CR_PEND;
4604 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004605 if (parent)
4606 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004607 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02004608 __l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004609 res = L2CAP_CR_SUCCESS;
4610 stat = L2CAP_CS_NO_INFO;
4611 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004612 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02004613 __l2cap_state_change(chan, BT_DISCONN);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004614 __set_chan_timer(chan,
4615 msecs_to_jiffies(L2CAP_DISC_TIMEOUT));
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004616 res = L2CAP_CR_SEC_BLOCK;
4617 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004618 }
4619
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004620 rsp.scid = cpu_to_le16(chan->dcid);
4621 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004622 rsp.result = cpu_to_le16(res);
4623 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004624 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4625 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004626 }
4627
Linus Torvalds1da177e2005-04-16 15:20:36 -07004628 bh_unlock_sock(sk);
4629 }
4630
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004631 mutex_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004632
Linus Torvalds1da177e2005-04-16 15:20:36 -07004633 return 0;
4634}
4635
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004636int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004637{
4638 struct l2cap_conn *conn = hcon->l2cap_data;
4639
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004640 if (!conn)
4641 conn = l2cap_conn_add(hcon, 0);
4642
4643 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004644 goto drop;
4645
4646 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4647
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004648 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004649 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004650 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004651 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004652 int len;
4653
4654 if (conn->rx_len) {
4655 BT_ERR("Unexpected start frame (len %d)", skb->len);
4656 kfree_skb(conn->rx_skb);
4657 conn->rx_skb = NULL;
4658 conn->rx_len = 0;
4659 l2cap_conn_unreliable(conn, ECOMM);
4660 }
4661
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004662 /* Start fragment always begin with Basic L2CAP header */
4663 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004664 BT_ERR("Frame is too short (len %d)", skb->len);
4665 l2cap_conn_unreliable(conn, ECOMM);
4666 goto drop;
4667 }
4668
4669 hdr = (struct l2cap_hdr *) skb->data;
4670 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004671 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004672
4673 if (len == skb->len) {
4674 /* Complete frame received */
4675 l2cap_recv_frame(conn, skb);
4676 return 0;
4677 }
4678
4679 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4680
4681 if (skb->len > len) {
4682 BT_ERR("Frame is too long (len %d, expected len %d)",
4683 skb->len, len);
4684 l2cap_conn_unreliable(conn, ECOMM);
4685 goto drop;
4686 }
4687
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004688 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004689
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004690 if (chan && chan->sk) {
4691 struct sock *sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004692 lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004693
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004694 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004695 BT_ERR("Frame exceeding recv MTU (len %d, "
4696 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004697 chan->imtu);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004698 release_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004699 l2cap_conn_unreliable(conn, ECOMM);
4700 goto drop;
4701 }
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004702 release_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004703 }
4704
Linus Torvalds1da177e2005-04-16 15:20:36 -07004705 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004706 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4707 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004708 goto drop;
4709
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004710 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004711 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004712 conn->rx_len = len - skb->len;
4713 } else {
4714 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4715
4716 if (!conn->rx_len) {
4717 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4718 l2cap_conn_unreliable(conn, ECOMM);
4719 goto drop;
4720 }
4721
4722 if (skb->len > conn->rx_len) {
4723 BT_ERR("Fragment is too long (len %d, expected %d)",
4724 skb->len, conn->rx_len);
4725 kfree_skb(conn->rx_skb);
4726 conn->rx_skb = NULL;
4727 conn->rx_len = 0;
4728 l2cap_conn_unreliable(conn, ECOMM);
4729 goto drop;
4730 }
4731
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004732 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004733 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004734 conn->rx_len -= skb->len;
4735
4736 if (!conn->rx_len) {
4737 /* Complete frame received */
4738 l2cap_recv_frame(conn, conn->rx_skb);
4739 conn->rx_skb = NULL;
4740 }
4741 }
4742
4743drop:
4744 kfree_skb(skb);
4745 return 0;
4746}
4747
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004748static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004749{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004750 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004751
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02004752 read_lock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004753
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004754 list_for_each_entry(c, &chan_list, global_l) {
4755 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004756
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004757 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 +01004758 batostr(&bt_sk(sk)->src),
4759 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004760 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004761 c->scid, c->dcid, c->imtu, c->omtu,
4762 c->sec_level, c->mode);
Andrei Emeltchenko61e1b4b2012-01-19 11:19:50 +02004763 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004764
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02004765 read_unlock(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004766
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004767 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004768}
4769
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004770static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4771{
4772 return single_open(file, l2cap_debugfs_show, inode->i_private);
4773}
4774
4775static const struct file_operations l2cap_debugfs_fops = {
4776 .open = l2cap_debugfs_open,
4777 .read = seq_read,
4778 .llseek = seq_lseek,
4779 .release = single_release,
4780};
4781
4782static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004783
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004784int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004785{
4786 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004787
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004788 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004789 if (err < 0)
4790 return err;
4791
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004792 if (bt_debugfs) {
4793 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4794 bt_debugfs, NULL, &l2cap_debugfs_fops);
4795 if (!l2cap_debugfs)
4796 BT_ERR("Failed to create L2CAP debug file");
4797 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004798
Linus Torvalds1da177e2005-04-16 15:20:36 -07004799 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004800}
4801
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004802void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004803{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004804 debugfs_remove(l2cap_debugfs);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004805 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004806}
4807
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004808module_param(disable_ertm, bool, 0644);
4809MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");