blob: 8e8e9e93fb343bb7a25253348b3ee8b67395636f [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
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300202static void l2cap_state_change(struct l2cap_chan *chan, int state)
203{
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
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300211static void l2cap_chan_timeout(struct work_struct *work)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300212{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300213 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
214 chan_timer.work);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200215 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300216 struct sock *sk = chan->sk;
217 int reason;
218
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200219 BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300220
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200221 mutex_lock(&conn->chan_lock);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300222 lock_sock(sk);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300223
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300224 if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300225 reason = ECONNREFUSED;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300226 else if (chan->state == BT_CONNECT &&
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300227 chan->sec_level != BT_SECURITY_SDP)
228 reason = ECONNREFUSED;
229 else
230 reason = ETIMEDOUT;
231
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300232 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300233
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300234 release_sock(sk);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300235
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300236 chan->ops->close(chan->data);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200237 mutex_unlock(&conn->chan_lock);
238
Ulisses Furquim371fd832011-12-21 20:02:36 -0200239 l2cap_chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300240}
241
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300242struct l2cap_chan *l2cap_chan_create(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200243{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300244 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200245
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300246 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
247 if (!chan)
248 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200249
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300250 chan->sk = sk;
251
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200252 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300253 list_add(&chan->global_l, &chan_list);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200254 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300255
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300256 INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300257
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300258 chan->state = BT_OPEN;
259
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300260 atomic_set(&chan->refcnt, 1);
261
Szymon Jancabc545b2011-11-03 16:05:44 +0100262 BT_DBG("sk %p chan %p", sk, chan);
263
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300264 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200265}
266
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300267void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300268{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200269 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300270 list_del(&chan->global_l);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200271 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300272
Ulisses Furquim371fd832011-12-21 20:02:36 -0200273 l2cap_chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300274}
275
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200276static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200277{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300278 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300279 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200280
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +0200281 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +0100282
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300283 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200284
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200285 switch (chan->chan_type) {
286 case L2CAP_CHAN_CONN_ORIENTED:
Ville Tervob62f3282011-02-10 22:38:50 -0300287 if (conn->hcon->type == LE_LINK) {
288 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300289 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300290 chan->scid = L2CAP_CID_LE_DATA;
291 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300292 } else {
293 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300294 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300295 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300296 }
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200297 break;
298
299 case L2CAP_CHAN_CONN_LESS:
Marcel Holtmann01394182006-07-03 10:02:46 +0200300 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300301 chan->scid = L2CAP_CID_CONN_LESS;
302 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300303 chan->omtu = L2CAP_DEFAULT_MTU;
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200304 break;
305
306 default:
Marcel Holtmann01394182006-07-03 10:02:46 +0200307 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300308 chan->scid = L2CAP_CID_SIGNALING;
309 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300310 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200311 }
312
Andrei Emeltchenko8f7975b2011-10-13 16:18:54 +0300313 chan->local_id = L2CAP_BESTEFFORT_ID;
314 chan->local_stype = L2CAP_SERV_BESTEFFORT;
315 chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
316 chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
317 chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
318 chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
319
Ulisses Furquim371fd832011-12-21 20:02:36 -0200320 l2cap_chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300321
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200322 mutex_lock(&conn->chan_lock);
323 list_add(&chan->list, &conn->chan_l);
324 mutex_unlock(&conn->chan_lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200325}
326
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900327/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200328 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300329static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200330{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300331 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300332 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200333 struct sock *parent = bt_sk(sk)->parent;
334
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300335 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200336
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300337 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200338
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900339 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300340 /* Delete from channel list */
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200341 list_del(&chan->list);
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200342
Ulisses Furquim371fd832011-12-21 20:02:36 -0200343 l2cap_chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300344
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300345 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200346 hci_conn_put(conn->hcon);
347 }
348
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300349 l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200350 sock_set_flag(sk, SOCK_ZAPPED);
351
352 if (err)
353 sk->sk_err = err;
354
355 if (parent) {
356 bt_accept_unlink(sk);
357 parent->sk_data_ready(parent, 0);
358 } else
359 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300360
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300361 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
362 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300363 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300364
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300365 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300366
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300367 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300368 struct srej_list *l, *tmp;
369
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300370 __clear_retrans_timer(chan);
371 __clear_monitor_timer(chan);
372 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300373
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300374 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300375
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300376 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300377 list_del(&l->list);
378 kfree(l);
379 }
380 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200381}
382
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300383static void l2cap_chan_cleanup_listen(struct sock *parent)
384{
385 struct sock *sk;
386
387 BT_DBG("parent %p", parent);
388
389 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300390 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300391 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200392
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300393 __clear_chan_timer(chan);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300394 lock_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300395 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300396 release_sock(sk);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200397
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300398 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300399 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300400}
401
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300402void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300403{
404 struct l2cap_conn *conn = chan->conn;
405 struct sock *sk = chan->sk;
406
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200407 BT_DBG("chan %p state %s sk %p", chan,
408 state_to_string(chan->state), sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300409
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300410 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300411 case BT_LISTEN:
412 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300413
414 l2cap_state_change(chan, BT_CLOSED);
415 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300416 break;
417
418 case BT_CONNECTED:
419 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300420 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300421 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300422 __clear_chan_timer(chan);
423 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300424 l2cap_send_disconn_req(conn, chan, reason);
425 } else
426 l2cap_chan_del(chan, reason);
427 break;
428
429 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300430 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300431 conn->hcon->type == ACL_LINK) {
432 struct l2cap_conn_rsp rsp;
433 __u16 result;
434
435 if (bt_sk(sk)->defer_setup)
436 result = L2CAP_CR_SEC_BLOCK;
437 else
438 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300439 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300440
441 rsp.scid = cpu_to_le16(chan->dcid);
442 rsp.dcid = cpu_to_le16(chan->scid);
443 rsp.result = cpu_to_le16(result);
444 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
445 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
446 sizeof(rsp), &rsp);
447 }
448
449 l2cap_chan_del(chan, reason);
450 break;
451
452 case BT_CONNECT:
453 case BT_DISCONN:
454 l2cap_chan_del(chan, reason);
455 break;
456
457 default:
458 sock_set_flag(sk, SOCK_ZAPPED);
459 break;
460 }
461}
462
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300463static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530464{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300465 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300466 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530467 case BT_SECURITY_HIGH:
468 return HCI_AT_DEDICATED_BONDING_MITM;
469 case BT_SECURITY_MEDIUM:
470 return HCI_AT_DEDICATED_BONDING;
471 default:
472 return HCI_AT_NO_BONDING;
473 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300474 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300475 if (chan->sec_level == BT_SECURITY_LOW)
476 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530477
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300478 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530479 return HCI_AT_NO_BONDING_MITM;
480 else
481 return HCI_AT_NO_BONDING;
482 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300483 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530484 case BT_SECURITY_HIGH:
485 return HCI_AT_GENERAL_BONDING_MITM;
486 case BT_SECURITY_MEDIUM:
487 return HCI_AT_GENERAL_BONDING;
488 default:
489 return HCI_AT_NO_BONDING;
490 }
491 }
492}
493
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200494/* Service level security */
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200495int l2cap_chan_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200496{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300497 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100498 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200499
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300500 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100501
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300502 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200503}
504
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200505static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200506{
507 u8 id;
508
509 /* Get next available identificator.
510 * 1 - 128 are used by kernel.
511 * 129 - 199 are reserved.
512 * 200 - 254 are used by utilities like l2ping, etc.
513 */
514
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200515 spin_lock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200516
517 if (++conn->tx_ident > 128)
518 conn->tx_ident = 1;
519
520 id = conn->tx_ident;
521
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200522 spin_unlock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200523
524 return id;
525}
526
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300527static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200528{
529 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200530 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200531
532 BT_DBG("code 0x%2.2x", code);
533
534 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300535 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200536
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200537 if (lmp_no_flush_capable(conn->hcon->hdev))
538 flags = ACL_START_NO_FLUSH;
539 else
540 flags = ACL_START;
541
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700542 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +0200543 skb->priority = HCI_PRIO_MAX;
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700544
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200545 hci_send_acl(conn->hchan, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200546}
547
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200548static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
549{
550 struct hci_conn *hcon = chan->conn->hcon;
551 u16 flags;
552
553 BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
554 skb->priority);
555
556 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
557 lmp_no_flush_capable(hcon->hdev))
558 flags = ACL_START_NO_FLUSH;
559 else
560 flags = ACL_START;
561
562 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
563 hci_send_acl(chan->conn->hchan, skb, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564}
565
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300566static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300567{
568 struct sk_buff *skb;
569 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300570 struct l2cap_conn *conn = chan->conn;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300571 int count, hlen;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300572
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300573 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300574 return;
575
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300576 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
577 hlen = L2CAP_EXT_HDR_SIZE;
578 else
579 hlen = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300580
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300581 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300582 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300583
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300584 BT_DBG("chan %p, control 0x%8.8x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300585
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300586 count = min_t(unsigned int, conn->mtu, hlen);
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +0300587
588 control |= __set_sframe(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300589
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300590 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +0300591 control |= __set_ctrl_final(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300592
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300593 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +0300594 control |= __set_ctrl_poll(chan);
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300595
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300596 skb = bt_skb_alloc(count, GFP_ATOMIC);
597 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300598 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300599
600 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300601 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300602 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300603
604 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300605
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300606 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300607 u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
608 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300609 }
610
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200611 skb->priority = HCI_PRIO_MAX;
612 l2cap_do_send(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300613}
614
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300615static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300616{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300617 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300618 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300619 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300620 } else
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300621 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300622
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300623 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300624
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300625 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300626}
627
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300628static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300629{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300630 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300631}
632
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300633static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200634{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300635 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200636
637 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100638 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
639 return;
640
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200641 if (l2cap_chan_check_security(chan) &&
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300642 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200643 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300644 req.scid = cpu_to_le16(chan->scid);
645 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200646
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300647 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300648 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200649
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300650 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
651 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200652 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200653 } else {
654 struct l2cap_info_req req;
655 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
656
657 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
658 conn->info_ident = l2cap_get_ident(conn);
659
Gustavo F. Padovan030013d2011-12-20 10:57:28 -0200660 schedule_delayed_work(&conn->info_timer,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200661 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
662
663 l2cap_send_cmd(conn, conn->info_ident,
664 L2CAP_INFO_REQ, sizeof(req), &req);
665 }
666}
667
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300668static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
669{
670 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300671 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300672 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
673
674 switch (mode) {
675 case L2CAP_MODE_ERTM:
676 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
677 case L2CAP_MODE_STREAMING:
678 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
679 default:
680 return 0x00;
681 }
682}
683
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300684static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300685{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300686 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300687 struct l2cap_disconn_req req;
688
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300689 if (!conn)
690 return;
691
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300692 sk = chan->sk;
693
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300694 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300695 __clear_retrans_timer(chan);
696 __clear_monitor_timer(chan);
697 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300698 }
699
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300700 req.dcid = cpu_to_le16(chan->dcid);
701 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300702 l2cap_send_cmd(conn, l2cap_get_ident(conn),
703 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300704
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300705 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300706 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300707}
708
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200710static void l2cap_conn_start(struct l2cap_conn *conn)
711{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200712 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200713
714 BT_DBG("conn %p", conn);
715
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200716 mutex_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200717
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200718 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300719 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300720
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200721 bh_lock_sock(sk);
722
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300723 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200724 bh_unlock_sock(sk);
725 continue;
726 }
727
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300728 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300729 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300730
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200731 if (!l2cap_chan_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300732 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300733 bh_unlock_sock(sk);
734 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200735 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300736
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300737 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
738 && test_bit(CONF_STATE2_DEVICE,
739 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300740 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300741 * so release the lock */
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300742 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300743 bh_unlock_sock(sk);
744 continue;
745 }
746
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300747 req.scid = cpu_to_le16(chan->scid);
748 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300749
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300750 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300751 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300752
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300753 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
754 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300755
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300756 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200757 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300758 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300759 rsp.scid = cpu_to_le16(chan->dcid);
760 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200761
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200762 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100763 if (bt_sk(sk)->defer_setup) {
764 struct sock *parent = bt_sk(sk)->parent;
765 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
766 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +0000767 if (parent)
768 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100769
770 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300771 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100772 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
773 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
774 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200775 } else {
776 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
777 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
778 }
779
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300780 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
781 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300782
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300783 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300784 rsp.result != L2CAP_CR_SUCCESS) {
785 bh_unlock_sock(sk);
786 continue;
787 }
788
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300789 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300790 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300791 l2cap_build_conf_req(chan, buf), buf);
792 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200793 }
794
795 bh_unlock_sock(sk);
796 }
797
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200798 mutex_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200799}
800
Ville Tervob62f3282011-02-10 22:38:50 -0300801/* Find socket with cid and source bdaddr.
802 * Returns closest match, locked.
803 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300804static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300805{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300806 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300807
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300808 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300809
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300810 list_for_each_entry(c, &chan_list, global_l) {
811 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300812
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300813 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300814 continue;
815
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300816 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300817 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300818 if (!bacmp(&bt_sk(sk)->src, src)) {
819 read_unlock(&chan_list_lock);
820 return c;
821 }
Ville Tervob62f3282011-02-10 22:38:50 -0300822
823 /* Closest match */
824 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300825 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300826 }
827 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300828
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300829 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300830
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300831 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300832}
833
834static void l2cap_le_conn_ready(struct l2cap_conn *conn)
835{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300836 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300837 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300838
839 BT_DBG("");
840
841 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300842 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300843 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300844 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300845 return;
846
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300847 parent = pchan->sk;
848
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300849 lock_sock(parent);
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300850
Ville Tervob62f3282011-02-10 22:38:50 -0300851 /* Check for backlog size */
852 if (sk_acceptq_is_full(parent)) {
853 BT_DBG("backlog full %d", parent->sk_ack_backlog);
854 goto clean;
855 }
856
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300857 chan = pchan->ops->new_connection(pchan->data);
858 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300859 goto clean;
860
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300861 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300862
Ville Tervob62f3282011-02-10 22:38:50 -0300863 hci_conn_hold(conn->hcon);
864
Ville Tervob62f3282011-02-10 22:38:50 -0300865 bacpy(&bt_sk(sk)->src, conn->src);
866 bacpy(&bt_sk(sk)->dst, conn->dst);
867
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300868 bt_accept_enqueue(parent, sk);
869
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200870 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300871
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300872 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300873
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300874 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300875 parent->sk_data_ready(parent, 0);
876
Ville Tervob62f3282011-02-10 22:38:50 -0300877clean:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300878 release_sock(parent);
Ville Tervob62f3282011-02-10 22:38:50 -0300879}
880
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +0200881static void l2cap_chan_ready(struct l2cap_chan *chan)
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300882{
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +0200883 struct sock *sk = chan->sk;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300884 struct sock *parent = bt_sk(sk)->parent;
885
886 BT_DBG("sk %p, parent %p", sk, parent);
887
888 chan->conf_state = 0;
889 __clear_chan_timer(chan);
890
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300891 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300892 sk->sk_state_change(sk);
893
894 if (parent)
895 parent->sk_data_ready(parent, 0);
896}
897
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200898static void l2cap_conn_ready(struct l2cap_conn *conn)
899{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300900 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200901
902 BT_DBG("conn %p", conn);
903
Ville Tervob62f3282011-02-10 22:38:50 -0300904 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
905 l2cap_le_conn_ready(conn);
906
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -0300907 if (conn->hcon->out && conn->hcon->type == LE_LINK)
908 smp_conn_security(conn, conn->hcon->pending_sec_level);
909
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200910 mutex_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200911
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200912 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300913 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300914
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200915 bh_lock_sock(sk);
916
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300917 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300918 if (smp_conn_security(conn, chan->sec_level))
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +0200919 l2cap_chan_ready(chan);
Ville Tervoacd7d372011-02-10 22:38:49 -0300920
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300921 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300922 __clear_chan_timer(chan);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300923 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200924 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300925
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300926 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300927 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200928
929 bh_unlock_sock(sk);
930 }
931
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200932 mutex_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200933}
934
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200935/* Notify sockets that we cannot guaranty reliability anymore */
936static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
937{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300938 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200939
940 BT_DBG("conn %p", conn);
941
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200942 mutex_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200943
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200944 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300945 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300946
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +0300947 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200948 sk->sk_err = err;
949 }
950
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200951 mutex_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200952}
953
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -0200954static void l2cap_info_timeout(struct work_struct *work)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200955{
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -0200956 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
Gustavo F. Padovan030013d2011-12-20 10:57:28 -0200957 info_timer.work);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200958
Marcel Holtmann984947d2009-02-06 23:35:19 +0100959 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100960 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100961
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200962 l2cap_conn_start(conn);
963}
964
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300965static void l2cap_conn_del(struct hci_conn *hcon, int err)
966{
967 struct l2cap_conn *conn = hcon->l2cap_data;
968 struct l2cap_chan *chan, *l;
969 struct sock *sk;
970
971 if (!conn)
972 return;
973
974 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
975
976 kfree_skb(conn->rx_skb);
977
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200978 mutex_lock(&conn->chan_lock);
979
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300980 /* Kill channels */
981 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
982 sk = chan->sk;
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300983 lock_sock(sk);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300984 l2cap_chan_del(chan, err);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300985 release_sock(sk);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300986 chan->ops->close(chan->data);
987 }
988
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200989 mutex_unlock(&conn->chan_lock);
990
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200991 hci_chan_del(conn->hchan);
992
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300993 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
Ulisses Furquim127074b2012-01-30 18:26:29 -0200994 cancel_delayed_work_sync(&conn->info_timer);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300995
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200996 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
Ulisses Furquim127074b2012-01-30 18:26:29 -0200997 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300998 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300999 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001000
1001 hcon->l2cap_data = NULL;
1002 kfree(conn);
1003}
1004
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001005static void security_timeout(struct work_struct *work)
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001006{
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001007 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1008 security_timer.work);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001009
1010 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1011}
1012
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1014{
Marcel Holtmann01394182006-07-03 10:02:46 +02001015 struct l2cap_conn *conn = hcon->l2cap_data;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001016 struct hci_chan *hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017
Marcel Holtmann01394182006-07-03 10:02:46 +02001018 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 return conn;
1020
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001021 hchan = hci_chan_create(hcon);
1022 if (!hchan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001025 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1026 if (!conn) {
1027 hci_chan_del(hchan);
1028 return NULL;
1029 }
1030
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 hcon->l2cap_data = conn;
1032 conn->hcon = hcon;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001033 conn->hchan = hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001035 BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
Marcel Holtmann01394182006-07-03 10:02:46 +02001036
Ville Tervoacd7d372011-02-10 22:38:49 -03001037 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1038 conn->mtu = hcon->hdev->le_mtu;
1039 else
1040 conn->mtu = hcon->hdev->acl_mtu;
1041
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 conn->src = &hcon->hdev->bdaddr;
1043 conn->dst = &hcon->dst;
1044
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001045 conn->feat_mask = 0;
1046
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 spin_lock_init(&conn->lock);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001048 mutex_init(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001049
1050 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001052 if (hcon->type == LE_LINK)
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001053 INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001054 else
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02001055 INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
Dave Young45054dc2009-10-18 20:28:30 +00001056
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001057 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01001058
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 return conn;
1060}
1061
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063
1064/* Find socket with psm and source bdaddr.
1065 * Returns closest match.
1066 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001067static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001069 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001071 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001072
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001073 list_for_each_entry(c, &chan_list, global_l) {
1074 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001075
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001076 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 continue;
1078
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001079 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001081 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001082 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001083 return c;
1084 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085
1086 /* Closest match */
1087 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001088 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 }
1090 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001092 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001093
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001094 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095}
1096
Johan Hedbergcbe8fed2012-01-08 22:51:16 +02001097int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001099 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 bdaddr_t *src = &bt_sk(sk)->src;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 struct l2cap_conn *conn;
1102 struct hci_conn *hcon;
1103 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001104 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001105 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001107 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001108 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001110 hdev = hci_get_route(dst, src);
1111 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 return -EHOSTUNREACH;
1113
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001114 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001116 lock_sock(sk);
1117
1118 /* PSM must be odd and lsb of upper byte must be 0 */
1119 if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
1120 chan->chan_type != L2CAP_CHAN_RAW) {
1121 err = -EINVAL;
1122 goto done;
1123 }
1124
1125 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
1126 err = -EINVAL;
1127 goto done;
1128 }
1129
1130 switch (chan->mode) {
1131 case L2CAP_MODE_BASIC:
1132 break;
1133 case L2CAP_MODE_ERTM:
1134 case L2CAP_MODE_STREAMING:
1135 if (!disable_ertm)
1136 break;
1137 /* fall through */
1138 default:
1139 err = -ENOTSUPP;
1140 goto done;
1141 }
1142
1143 switch (sk->sk_state) {
1144 case BT_CONNECT:
1145 case BT_CONNECT2:
1146 case BT_CONFIG:
1147 /* Already connecting */
1148 err = 0;
1149 goto done;
1150
1151 case BT_CONNECTED:
1152 /* Already connected */
1153 err = -EISCONN;
1154 goto done;
1155
1156 case BT_OPEN:
1157 case BT_BOUND:
1158 /* Can connect */
1159 break;
1160
1161 default:
1162 err = -EBADFD;
1163 goto done;
1164 }
1165
1166 /* Set destination address and psm */
Gustavo F. Padovan9219b2a2012-01-02 20:08:04 -02001167 bacpy(&bt_sk(sk)->dst, dst);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001168 chan->psm = psm;
1169 chan->dcid = cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001171 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001172
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001173 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001174 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001175 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001176 else
1177 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001178 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001179
Ville Tervo30e76272011-02-22 16:10:53 -03001180 if (IS_ERR(hcon)) {
1181 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001183 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184
1185 conn = l2cap_conn_add(hcon, 0);
1186 if (!conn) {
1187 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001188 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 goto done;
1190 }
1191
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 /* Update source addr of the socket */
1193 bacpy(src, conn->src);
1194
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001195 l2cap_chan_add(conn, chan);
1196
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001197 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001198 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199
1200 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001201 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001202 __clear_chan_timer(chan);
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001203 if (l2cap_chan_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001204 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001205 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001206 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 }
1208
Ville Tervo30e76272011-02-22 16:10:53 -03001209 err = 0;
1210
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001212 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 hci_dev_put(hdev);
1214 return err;
1215}
1216
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001217int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001218{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001219 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001220 DECLARE_WAITQUEUE(wait, current);
1221 int err = 0;
1222 int timeo = HZ/5;
1223
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001224 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001225 set_current_state(TASK_INTERRUPTIBLE);
1226 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001227 if (!timeo)
1228 timeo = HZ/5;
1229
1230 if (signal_pending(current)) {
1231 err = sock_intr_errno(timeo);
1232 break;
1233 }
1234
1235 release_sock(sk);
1236 timeo = schedule_timeout(timeo);
1237 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001238 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001239
1240 err = sock_error(sk);
1241 if (err)
1242 break;
1243 }
1244 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001245 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001246 return err;
1247}
1248
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001249static void l2cap_monitor_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001250{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001251 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1252 monitor_timer.work);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001253 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001254
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001255 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001256
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001257 lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001258 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001259 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001260 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001261 return;
1262 }
1263
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001264 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001265 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001266
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001267 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001268 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001269}
1270
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001271static void l2cap_retrans_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 retrans_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. Padovan49208c92011-04-04 15:59:54 -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. Padovan6a026612011-04-01 00:38:50 -03001280 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001281 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001282
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001283 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001284
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001285 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001286 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001287}
1288
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001289static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001290{
1291 struct sk_buff *skb;
1292
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001293 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001294 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001295 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001296 break;
1297
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001298 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001299 kfree_skb(skb);
1300
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001301 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001302 }
1303
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001304 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001305 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001306}
1307
Szymon Janc67c9e842011-07-28 16:24:33 +02001308static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001309{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001310 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001311 u32 control;
1312 u16 fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001313
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001314 while ((skb = skb_dequeue(&chan->tx_q))) {
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001315 control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001316 control |= __set_txseq(chan, chan->next_tx_seq);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001317 __put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001318
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001319 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001320 fcs = crc16(0, (u8 *)skb->data,
1321 skb->len - L2CAP_FCS_SIZE);
1322 put_unaligned_le16(fcs,
1323 skb->data + skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001324 }
1325
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001326 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001327
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001328 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001329 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001330}
1331
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001332static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001333{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001334 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001335 u16 fcs;
1336 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001337
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001338 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001339 if (!skb)
1340 return;
1341
Szymon Jancd1726b62011-11-16 09:32:20 +01001342 while (bt_cb(skb)->tx_seq != tx_seq) {
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001343 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001344 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001345
Szymon Jancd1726b62011-11-16 09:32:20 +01001346 skb = skb_queue_next(&chan->tx_q, skb);
1347 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001348
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001349 if (chan->remote_max_tx &&
1350 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001351 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001352 return;
1353 }
1354
1355 tx_skb = skb_clone(skb, GFP_ATOMIC);
1356 bt_cb(skb)->retries++;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001357
1358 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001359 control &= __get_sar_mask(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001360
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001361 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001362 control |= __set_ctrl_final(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001363
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001364 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001365 control |= __set_txseq(chan, tx_seq);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001366
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001367 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001368
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001369 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001370 fcs = crc16(0, (u8 *)tx_skb->data,
1371 tx_skb->len - L2CAP_FCS_SIZE);
1372 put_unaligned_le16(fcs,
1373 tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001374 }
1375
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001376 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001377}
1378
Szymon Janc67c9e842011-07-28 16:24:33 +02001379static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001380{
1381 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001382 u16 fcs;
1383 u32 control;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001384 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001385
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001386 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001387 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001388
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001389 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001390
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001391 if (chan->remote_max_tx &&
1392 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001393 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001394 break;
1395 }
1396
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001397 tx_skb = skb_clone(skb, GFP_ATOMIC);
1398
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001399 bt_cb(skb)->retries++;
1400
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001401 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001402 control &= __get_sar_mask(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001403
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001404 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001405 control |= __set_ctrl_final(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001406
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001407 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001408 control |= __set_txseq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001409
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001410 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001411
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001412 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001413 fcs = crc16(0, (u8 *)skb->data,
1414 tx_skb->len - L2CAP_FCS_SIZE);
1415 put_unaligned_le16(fcs, skb->data +
1416 tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001417 }
1418
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001419 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001420
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001421 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001422
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001423 bt_cb(skb)->tx_seq = chan->next_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001424
1425 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001426
Szymon Janc8ed7a0a2012-02-07 15:43:01 +01001427 if (bt_cb(skb)->retries == 1) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001428 chan->unacked_frames++;
Szymon Janc930fa4a2012-02-07 15:43:02 +01001429
1430 if (!nsent++)
1431 __clear_ack_timer(chan);
Szymon Janc8ed7a0a2012-02-07 15:43:01 +01001432 }
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301433
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001434 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001435
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001436 if (skb_queue_is_last(&chan->tx_q, skb))
1437 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001438 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001439 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001440 }
1441
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001442 return nsent;
1443}
1444
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001445static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001446{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001447 int ret;
1448
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001449 if (!skb_queue_empty(&chan->tx_q))
1450 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001451
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001452 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001453 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001454 return ret;
1455}
1456
Szymon Jancb17e73b2012-01-11 10:59:47 +01001457static void __l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001458{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001459 u32 control = 0;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001460
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001461 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001462
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001463 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001464 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001465 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001466 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001467 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001468 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001469
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001470 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001471 return;
1472
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001473 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001474 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001475}
1476
Szymon Jancb17e73b2012-01-11 10:59:47 +01001477static void l2cap_send_ack(struct l2cap_chan *chan)
1478{
1479 __clear_ack_timer(chan);
1480 __l2cap_send_ack(chan);
1481}
1482
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001483static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001484{
1485 struct srej_list *tail;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001486 u32 control;
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001487
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001488 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001489 control |= __set_ctrl_final(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001490
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001491 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001492 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001493
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001494 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001495}
1496
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001497static 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 -07001498{
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001499 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001500 struct sk_buff **frag;
1501 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001503 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001504 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505
1506 sent += count;
1507 len -= count;
1508
1509 /* Continuation fragments (no L2CAP header) */
1510 frag = &skb_shinfo(skb)->frag_list;
1511 while (len) {
1512 count = min_t(unsigned int, conn->mtu, len);
1513
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001514 *frag = chan->ops->alloc_skb(chan, count,
1515 msg->msg_flags & MSG_DONTWAIT, &err);
1516
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001518 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001519 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1520 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001522 (*frag)->priority = skb->priority;
1523
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 sent += count;
1525 len -= count;
1526
1527 frag = &(*frag)->next;
1528 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529
1530 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001531}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001533static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
1534 struct msghdr *msg, size_t len,
1535 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001536{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001537 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001538 struct sk_buff *skb;
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001539 int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001540 struct l2cap_hdr *lh;
1541
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001542 BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001543
1544 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001545
1546 skb = chan->ops->alloc_skb(chan, count + hlen,
1547 msg->msg_flags & MSG_DONTWAIT, &err);
1548
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001549 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001550 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001551
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001552 skb->priority = priority;
1553
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001554 /* Create L2CAP header */
1555 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001556 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001557 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001558 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001559
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001560 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001561 if (unlikely(err < 0)) {
1562 kfree_skb(skb);
1563 return ERR_PTR(err);
1564 }
1565 return skb;
1566}
1567
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001568static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
1569 struct msghdr *msg, size_t len,
1570 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001571{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001572 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001573 struct sk_buff *skb;
1574 int err, count, hlen = L2CAP_HDR_SIZE;
1575 struct l2cap_hdr *lh;
1576
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001577 BT_DBG("chan %p len %d", chan, (int)len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001578
1579 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001580
1581 skb = chan->ops->alloc_skb(chan, count + hlen,
1582 msg->msg_flags & MSG_DONTWAIT, &err);
1583
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001584 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001585 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001586
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001587 skb->priority = priority;
1588
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001589 /* Create L2CAP header */
1590 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001591 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001592 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1593
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001594 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001595 if (unlikely(err < 0)) {
1596 kfree_skb(skb);
1597 return ERR_PTR(err);
1598 }
1599 return skb;
1600}
1601
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001602static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1603 struct msghdr *msg, size_t len,
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001604 u32 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001605{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001606 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001607 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001608 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001609 struct l2cap_hdr *lh;
1610
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001611 BT_DBG("chan %p len %d", chan, (int)len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001612
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001613 if (!conn)
1614 return ERR_PTR(-ENOTCONN);
1615
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001616 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1617 hlen = L2CAP_EXT_HDR_SIZE;
1618 else
1619 hlen = L2CAP_ENH_HDR_SIZE;
1620
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001621 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001622 hlen += L2CAP_SDULEN_SIZE;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001623
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001624 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001625 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001626
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001627 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001628
1629 skb = chan->ops->alloc_skb(chan, count + hlen,
1630 msg->msg_flags & MSG_DONTWAIT, &err);
1631
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001632 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001633 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001634
1635 /* Create L2CAP header */
1636 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001637 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001638 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001639
1640 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
1641
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001642 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001643 put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001644
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001645 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001646 if (unlikely(err < 0)) {
1647 kfree_skb(skb);
1648 return ERR_PTR(err);
1649 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001650
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001651 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001652 put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001653
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001654 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001655 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656}
1657
Szymon Janc67c9e842011-07-28 16:24:33 +02001658static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001659{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001660 struct sk_buff *skb;
1661 struct sk_buff_head sar_queue;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001662 u32 control;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001663 size_t size = 0;
1664
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001665 skb_queue_head_init(&sar_queue);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001666 control = __set_ctrl_sar(chan, L2CAP_SAR_START);
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001667 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001668 if (IS_ERR(skb))
1669 return PTR_ERR(skb);
1670
1671 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001672 len -= chan->remote_mps;
1673 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001674
1675 while (len > 0) {
1676 size_t buflen;
1677
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001678 if (len > chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001679 control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001680 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001681 } else {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001682 control = __set_ctrl_sar(chan, L2CAP_SAR_END);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001683 buflen = len;
1684 }
1685
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001686 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001687 if (IS_ERR(skb)) {
1688 skb_queue_purge(&sar_queue);
1689 return PTR_ERR(skb);
1690 }
1691
1692 __skb_queue_tail(&sar_queue, skb);
1693 len -= buflen;
1694 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001695 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001696 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1697 if (chan->tx_send_head == NULL)
1698 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001699
1700 return size;
1701}
1702
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001703int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
1704 u32 priority)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001705{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001706 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001707 u32 control;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001708 int err;
1709
1710 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001711 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001712 skb = l2cap_create_connless_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001713 if (IS_ERR(skb))
1714 return PTR_ERR(skb);
1715
1716 l2cap_do_send(chan, skb);
1717 return len;
1718 }
1719
1720 switch (chan->mode) {
1721 case L2CAP_MODE_BASIC:
1722 /* Check outgoing MTU */
1723 if (len > chan->omtu)
1724 return -EMSGSIZE;
1725
1726 /* Create a basic PDU */
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001727 skb = l2cap_create_basic_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001728 if (IS_ERR(skb))
1729 return PTR_ERR(skb);
1730
1731 l2cap_do_send(chan, skb);
1732 err = len;
1733 break;
1734
1735 case L2CAP_MODE_ERTM:
1736 case L2CAP_MODE_STREAMING:
1737 /* Entire SDU fits into one PDU */
1738 if (len <= chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001739 control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001740 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1741 0);
1742 if (IS_ERR(skb))
1743 return PTR_ERR(skb);
1744
1745 __skb_queue_tail(&chan->tx_q, skb);
1746
1747 if (chan->tx_send_head == NULL)
1748 chan->tx_send_head = skb;
1749
1750 } else {
1751 /* Segment SDU into multiples PDUs */
1752 err = l2cap_sar_segment_sdu(chan, msg, len);
1753 if (err < 0)
1754 return err;
1755 }
1756
1757 if (chan->mode == L2CAP_MODE_STREAMING) {
1758 l2cap_streaming_send(chan);
1759 err = len;
1760 break;
1761 }
1762
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001763 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1764 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001765 err = len;
1766 break;
1767 }
1768
1769 err = l2cap_ertm_send(chan);
1770 if (err >= 0)
1771 err = len;
1772
1773 break;
1774
1775 default:
1776 BT_DBG("bad state %1.1x", chan->mode);
1777 err = -EBADFD;
1778 }
1779
1780 return err;
1781}
1782
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783/* Copy frame to all raw sockets on that connection */
1784static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1785{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001787 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788
1789 BT_DBG("conn %p", conn);
1790
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001791 mutex_lock(&conn->chan_lock);
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001792
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001793 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001794 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001795 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 continue;
1797
1798 /* Don't send frame to the socket it came from */
1799 if (skb->sk == sk)
1800 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001801 nskb = skb_clone(skb, GFP_ATOMIC);
1802 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 continue;
1804
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001805 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 kfree_skb(nskb);
1807 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001808
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001809 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810}
1811
1812/* ---- L2CAP signalling commands ---- */
1813static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1814 u8 code, u8 ident, u16 dlen, void *data)
1815{
1816 struct sk_buff *skb, **frag;
1817 struct l2cap_cmd_hdr *cmd;
1818 struct l2cap_hdr *lh;
1819 int len, count;
1820
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001821 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1822 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823
1824 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1825 count = min_t(unsigned int, conn->mtu, len);
1826
1827 skb = bt_skb_alloc(count, GFP_ATOMIC);
1828 if (!skb)
1829 return NULL;
1830
1831 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001832 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001833
1834 if (conn->hcon->type == LE_LINK)
1835 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1836 else
1837 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838
1839 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1840 cmd->code = code;
1841 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001842 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843
1844 if (dlen) {
1845 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1846 memcpy(skb_put(skb, count), data, count);
1847 data += count;
1848 }
1849
1850 len -= skb->len;
1851
1852 /* Continuation fragments (no L2CAP header) */
1853 frag = &skb_shinfo(skb)->frag_list;
1854 while (len) {
1855 count = min_t(unsigned int, conn->mtu, len);
1856
1857 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1858 if (!*frag)
1859 goto fail;
1860
1861 memcpy(skb_put(*frag, count), data, count);
1862
1863 len -= count;
1864 data += count;
1865
1866 frag = &(*frag)->next;
1867 }
1868
1869 return skb;
1870
1871fail:
1872 kfree_skb(skb);
1873 return NULL;
1874}
1875
1876static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1877{
1878 struct l2cap_conf_opt *opt = *ptr;
1879 int len;
1880
1881 len = L2CAP_CONF_OPT_SIZE + opt->len;
1882 *ptr += len;
1883
1884 *type = opt->type;
1885 *olen = opt->len;
1886
1887 switch (opt->len) {
1888 case 1:
1889 *val = *((u8 *) opt->val);
1890 break;
1891
1892 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001893 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894 break;
1895
1896 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001897 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 break;
1899
1900 default:
1901 *val = (unsigned long) opt->val;
1902 break;
1903 }
1904
1905 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1906 return len;
1907}
1908
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1910{
1911 struct l2cap_conf_opt *opt = *ptr;
1912
1913 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1914
1915 opt->type = type;
1916 opt->len = len;
1917
1918 switch (len) {
1919 case 1:
1920 *((u8 *) opt->val) = val;
1921 break;
1922
1923 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001924 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925 break;
1926
1927 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001928 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929 break;
1930
1931 default:
1932 memcpy(opt->val, (void *) val, len);
1933 break;
1934 }
1935
1936 *ptr += L2CAP_CONF_OPT_SIZE + len;
1937}
1938
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001939static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
1940{
1941 struct l2cap_conf_efs efs;
1942
Szymon Janc1ec918c2011-11-16 09:32:21 +01001943 switch (chan->mode) {
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001944 case L2CAP_MODE_ERTM:
1945 efs.id = chan->local_id;
1946 efs.stype = chan->local_stype;
1947 efs.msdu = cpu_to_le16(chan->local_msdu);
1948 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1949 efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
1950 efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
1951 break;
1952
1953 case L2CAP_MODE_STREAMING:
1954 efs.id = 1;
1955 efs.stype = L2CAP_SERV_BESTEFFORT;
1956 efs.msdu = cpu_to_le16(chan->local_msdu);
1957 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1958 efs.acc_lat = 0;
1959 efs.flush_to = 0;
1960 break;
1961
1962 default:
1963 return;
1964 }
1965
1966 l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
1967 (unsigned long) &efs);
1968}
1969
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001970static void l2cap_ack_timeout(struct work_struct *work)
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001971{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001972 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1973 ack_timer.work);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001974
Gustavo F. Padovan2fb9b3d2011-12-22 16:56:05 -02001975 BT_DBG("chan %p", chan);
1976
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001977 lock_sock(chan->sk);
Szymon Jancb17e73b2012-01-11 10:59:47 +01001978 __l2cap_send_ack(chan);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001979 release_sock(chan->sk);
Szymon Janc09bfb2e2012-01-11 10:59:49 +01001980
1981 l2cap_chan_put(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001982}
1983
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001984static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001985{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001986 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001987 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001988 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001989 chan->num_acked = 0;
1990 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001991
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001992 INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
1993 INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
1994 INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001995
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001996 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001997
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001998 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001999}
2000
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002001static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2002{
2003 switch (mode) {
2004 case L2CAP_MODE_STREAMING:
2005 case L2CAP_MODE_ERTM:
2006 if (l2cap_mode_supported(mode, remote_feat_mask))
2007 return mode;
2008 /* fall through */
2009 default:
2010 return L2CAP_MODE_BASIC;
2011 }
2012}
2013
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002014static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
2015{
2016 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
2017}
2018
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002019static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2020{
2021 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2022}
2023
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002024static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
2025{
2026 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002027 __l2cap_ews_supported(chan)) {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002028 /* use extended control field */
2029 set_bit(FLAG_EXT_CTRL, &chan->flags);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002030 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2031 } else {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002032 chan->tx_win = min_t(u16, chan->tx_win,
2033 L2CAP_DEFAULT_TX_WINDOW);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002034 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2035 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002036}
2037
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002038static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002041 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042 void *ptr = req->data;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002043 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002045 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002047 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002048 goto done;
2049
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002050 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002051 case L2CAP_MODE_STREAMING:
2052 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002053 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002054 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002055
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002056 if (__l2cap_efs_supported(chan))
2057 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2058
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002059 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002060 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002061 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002062 break;
2063 }
2064
2065done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002066 if (chan->imtu != L2CAP_DEFAULT_MTU)
2067 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002068
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002069 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002070 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002071 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2072 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002073 break;
2074
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002075 rfc.mode = L2CAP_MODE_BASIC;
2076 rfc.txwin_size = 0;
2077 rfc.max_transmit = 0;
2078 rfc.retrans_timeout = 0;
2079 rfc.monitor_timeout = 0;
2080 rfc.max_pdu_size = 0;
2081
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002082 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2083 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002084 break;
2085
2086 case L2CAP_MODE_ERTM:
2087 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002088 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002089 rfc.retrans_timeout = 0;
2090 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002091
2092 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2093 L2CAP_EXT_HDR_SIZE -
2094 L2CAP_SDULEN_SIZE -
2095 L2CAP_FCS_SIZE);
2096 rfc.max_pdu_size = cpu_to_le16(size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002097
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002098 l2cap_txwin_setup(chan);
2099
2100 rfc.txwin_size = min_t(u16, chan->tx_win,
2101 L2CAP_DEFAULT_TX_WINDOW);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002102
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002103 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2104 (unsigned long) &rfc);
2105
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002106 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2107 l2cap_add_opt_efs(&ptr, chan);
2108
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002109 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002110 break;
2111
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002112 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002113 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002114 chan->fcs = L2CAP_FCS_NONE;
2115 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002116 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002117
2118 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2119 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2120 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002121 break;
2122
2123 case L2CAP_MODE_STREAMING:
2124 rfc.mode = L2CAP_MODE_STREAMING;
2125 rfc.txwin_size = 0;
2126 rfc.max_transmit = 0;
2127 rfc.retrans_timeout = 0;
2128 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002129
2130 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2131 L2CAP_EXT_HDR_SIZE -
2132 L2CAP_SDULEN_SIZE -
2133 L2CAP_FCS_SIZE);
2134 rfc.max_pdu_size = cpu_to_le16(size);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002135
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002136 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2137 (unsigned long) &rfc);
2138
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002139 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2140 l2cap_add_opt_efs(&ptr, chan);
2141
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002142 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002143 break;
2144
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002145 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002146 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002147 chan->fcs = L2CAP_FCS_NONE;
2148 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002149 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002150 break;
2151 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002153 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002154 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155
2156 return ptr - data;
2157}
2158
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002159static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002161 struct l2cap_conf_rsp *rsp = data;
2162 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002163 void *req = chan->conf_req;
2164 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002165 int type, hint, olen;
2166 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002167 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002168 struct l2cap_conf_efs efs;
2169 u8 remote_efs = 0;
Marcel Holtmann861d6882007-10-20 13:37:06 +02002170 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002171 u16 result = L2CAP_CONF_SUCCESS;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002172 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002174 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002175
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002176 while (len >= L2CAP_CONF_OPT_SIZE) {
2177 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002179 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002180 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002181
2182 switch (type) {
2183 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002184 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002185 break;
2186
2187 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002188 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002189 break;
2190
2191 case L2CAP_CONF_QOS:
2192 break;
2193
Marcel Holtmann6464f352007-10-20 13:39:51 +02002194 case L2CAP_CONF_RFC:
2195 if (olen == sizeof(rfc))
2196 memcpy(&rfc, (void *) val, olen);
2197 break;
2198
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002199 case L2CAP_CONF_FCS:
2200 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002201 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002202 break;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002203
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002204 case L2CAP_CONF_EFS:
2205 remote_efs = 1;
2206 if (olen == sizeof(efs))
2207 memcpy(&efs, (void *) val, olen);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002208 break;
2209
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002210 case L2CAP_CONF_EWS:
2211 if (!enable_hs)
2212 return -ECONNREFUSED;
2213
2214 set_bit(FLAG_EXT_CTRL, &chan->flags);
2215 set_bit(CONF_EWS_RECV, &chan->conf_state);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002216 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002217 chan->remote_tx_win = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002218 break;
2219
2220 default:
2221 if (hint)
2222 break;
2223
2224 result = L2CAP_CONF_UNKNOWN;
2225 *((u8 *) ptr++) = type;
2226 break;
2227 }
2228 }
2229
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002230 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002231 goto done;
2232
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002233 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002234 case L2CAP_MODE_STREAMING:
2235 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002236 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002237 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002238 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002239 break;
2240 }
2241
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002242 if (remote_efs) {
2243 if (__l2cap_efs_supported(chan))
2244 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2245 else
2246 return -ECONNREFUSED;
2247 }
2248
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002249 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002250 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002251
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002252 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002253 }
2254
2255done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002256 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002257 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002258 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002259
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002260 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002261 return -ECONNREFUSED;
2262
2263 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2264 sizeof(rfc), (unsigned long) &rfc);
2265 }
2266
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002267 if (result == L2CAP_CONF_SUCCESS) {
2268 /* Configure output options and let the other side know
2269 * which ones we don't like. */
2270
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002271 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2272 result = L2CAP_CONF_UNACCEPT;
2273 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002274 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002275 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002276 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002277 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002278
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002279 if (remote_efs) {
2280 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2281 efs.stype != L2CAP_SERV_NOTRAFIC &&
2282 efs.stype != chan->local_stype) {
2283
2284 result = L2CAP_CONF_UNACCEPT;
2285
2286 if (chan->num_conf_req >= 1)
2287 return -ECONNREFUSED;
2288
2289 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002290 sizeof(efs),
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002291 (unsigned long) &efs);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002292 } else {
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002293 /* Send PENDING Conf Rsp */
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002294 result = L2CAP_CONF_PENDING;
2295 set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002296 }
2297 }
2298
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002299 switch (rfc.mode) {
2300 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002301 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002302 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002303 break;
2304
2305 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002306 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2307 chan->remote_tx_win = rfc.txwin_size;
2308 else
2309 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2310
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002311 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002312
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002313 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2314 chan->conn->mtu -
2315 L2CAP_EXT_HDR_SIZE -
2316 L2CAP_SDULEN_SIZE -
2317 L2CAP_FCS_SIZE);
2318 rfc.max_pdu_size = cpu_to_le16(size);
2319 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002320
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002321 rfc.retrans_timeout =
2322 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2323 rfc.monitor_timeout =
2324 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002325
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002326 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002327
2328 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2329 sizeof(rfc), (unsigned long) &rfc);
2330
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002331 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2332 chan->remote_id = efs.id;
2333 chan->remote_stype = efs.stype;
2334 chan->remote_msdu = le16_to_cpu(efs.msdu);
2335 chan->remote_flush_to =
2336 le32_to_cpu(efs.flush_to);
2337 chan->remote_acc_lat =
2338 le32_to_cpu(efs.acc_lat);
2339 chan->remote_sdu_itime =
2340 le32_to_cpu(efs.sdu_itime);
2341 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2342 sizeof(efs), (unsigned long) &efs);
2343 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002344 break;
2345
2346 case L2CAP_MODE_STREAMING:
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002347 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2348 chan->conn->mtu -
2349 L2CAP_EXT_HDR_SIZE -
2350 L2CAP_SDULEN_SIZE -
2351 L2CAP_FCS_SIZE);
2352 rfc.max_pdu_size = cpu_to_le16(size);
2353 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002354
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002355 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002356
2357 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2358 sizeof(rfc), (unsigned long) &rfc);
2359
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002360 break;
2361
2362 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002363 result = L2CAP_CONF_UNACCEPT;
2364
2365 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002366 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002367 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002368
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002369 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002370 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002371 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002372 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002373 rsp->result = cpu_to_le16(result);
2374 rsp->flags = cpu_to_le16(0x0000);
2375
2376 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377}
2378
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002379static 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 -03002380{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002381 struct l2cap_conf_req *req = data;
2382 void *ptr = req->data;
2383 int type, olen;
2384 unsigned long val;
Mat Martineau36e999a2011-12-08 17:23:21 -08002385 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002386 struct l2cap_conf_efs efs;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002387
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002388 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002389
2390 while (len >= L2CAP_CONF_OPT_SIZE) {
2391 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2392
2393 switch (type) {
2394 case L2CAP_CONF_MTU:
2395 if (val < L2CAP_DEFAULT_MIN_MTU) {
2396 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002397 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002398 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002399 chan->imtu = val;
2400 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002401 break;
2402
2403 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002404 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002405 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002406 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002407 break;
2408
2409 case L2CAP_CONF_RFC:
2410 if (olen == sizeof(rfc))
2411 memcpy(&rfc, (void *)val, olen);
2412
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002413 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002414 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002415 return -ECONNREFUSED;
2416
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002417 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002418
2419 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2420 sizeof(rfc), (unsigned long) &rfc);
2421 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002422
2423 case L2CAP_CONF_EWS:
2424 chan->tx_win = min_t(u16, val,
2425 L2CAP_DEFAULT_EXT_WINDOW);
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002426 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2427 chan->tx_win);
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002428 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002429
2430 case L2CAP_CONF_EFS:
2431 if (olen == sizeof(efs))
2432 memcpy(&efs, (void *)val, olen);
2433
2434 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2435 efs.stype != L2CAP_SERV_NOTRAFIC &&
2436 efs.stype != chan->local_stype)
2437 return -ECONNREFUSED;
2438
2439 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2440 sizeof(efs), (unsigned long) &efs);
2441 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002442 }
2443 }
2444
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002445 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002446 return -ECONNREFUSED;
2447
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002448 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002449
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002450 if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002451 switch (rfc.mode) {
2452 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002453 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2454 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2455 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002456
2457 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2458 chan->local_msdu = le16_to_cpu(efs.msdu);
2459 chan->local_sdu_itime =
2460 le32_to_cpu(efs.sdu_itime);
2461 chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
2462 chan->local_flush_to =
2463 le32_to_cpu(efs.flush_to);
2464 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002465 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002466
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002467 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002468 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002469 }
2470 }
2471
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002472 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002473 req->flags = cpu_to_le16(0x0000);
2474
2475 return ptr - data;
2476}
2477
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002478static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479{
2480 struct l2cap_conf_rsp *rsp = data;
2481 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002483 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002485 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002486 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002487 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488
2489 return ptr - data;
2490}
2491
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002492void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002493{
2494 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002495 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002496 u8 buf[128];
2497
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002498 rsp.scid = cpu_to_le16(chan->dcid);
2499 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002500 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2501 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2502 l2cap_send_cmd(conn, chan->ident,
2503 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2504
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002505 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002506 return;
2507
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002508 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2509 l2cap_build_conf_req(chan, buf), buf);
2510 chan->num_conf_req++;
2511}
2512
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002513static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002514{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002515 int type, olen;
2516 unsigned long val;
2517 struct l2cap_conf_rfc rfc;
2518
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002519 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002520
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002521 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002522 return;
2523
2524 while (len >= L2CAP_CONF_OPT_SIZE) {
2525 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2526
2527 switch (type) {
2528 case L2CAP_CONF_RFC:
2529 if (olen == sizeof(rfc))
2530 memcpy(&rfc, (void *)val, olen);
2531 goto done;
2532 }
2533 }
2534
Mat Martineau36e999a2011-12-08 17:23:21 -08002535 /* Use sane default values in case a misbehaving remote device
2536 * did not send an RFC option.
2537 */
2538 rfc.mode = chan->mode;
2539 rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
2540 rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
2541 rfc.max_pdu_size = cpu_to_le16(chan->imtu);
2542
2543 BT_ERR("Expected RFC option was not found, using defaults");
2544
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002545done:
2546 switch (rfc.mode) {
2547 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002548 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2549 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2550 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002551 break;
2552 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002553 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002554 }
2555}
2556
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002557static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2558{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002559 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002560
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002561 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002562 return 0;
2563
2564 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2565 cmd->ident == conn->info_ident) {
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02002566 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002567
2568 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002569 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002570
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002571 l2cap_conn_start(conn);
2572 }
2573
2574 return 0;
2575}
2576
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2578{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2580 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002581 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002582 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002583 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584
2585 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002586 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587
2588 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2589
2590 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002591 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2592 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593 result = L2CAP_CR_BAD_PSM;
2594 goto sendresp;
2595 }
2596
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002597 parent = pchan->sk;
2598
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002599 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002600 lock_sock(parent);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002601
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002602 /* Check if the ACL is secure enough (if not SDP) */
2603 if (psm != cpu_to_le16(0x0001) &&
2604 !hci_conn_check_link_mode(conn->hcon)) {
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002605 conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002606 result = L2CAP_CR_SEC_BLOCK;
2607 goto response;
2608 }
2609
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610 result = L2CAP_CR_NO_MEM;
2611
2612 /* Check for backlog size */
2613 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002614 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615 goto response;
2616 }
2617
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002618 chan = pchan->ops->new_connection(pchan->data);
2619 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 goto response;
2621
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002622 sk = chan->sk;
2623
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002625 if (__l2cap_get_chan_by_dcid(conn, scid)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002627 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628 goto response;
2629 }
2630
2631 hci_conn_hold(conn->hcon);
2632
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633 bacpy(&bt_sk(sk)->src, conn->src);
2634 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002635 chan->psm = psm;
2636 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002638 bt_accept_enqueue(parent, sk);
2639
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02002640 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002641
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002642 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002644 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002646 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647
Marcel Holtmann984947d2009-02-06 23:35:19 +01002648 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02002649 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002650 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002651 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002652 result = L2CAP_CR_PEND;
2653 status = L2CAP_CS_AUTHOR_PEND;
2654 parent->sk_data_ready(parent, 0);
2655 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002656 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002657 result = L2CAP_CR_SUCCESS;
2658 status = L2CAP_CS_NO_INFO;
2659 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002660 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002661 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002662 result = L2CAP_CR_PEND;
2663 status = L2CAP_CS_AUTHEN_PEND;
2664 }
2665 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002666 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002667 result = L2CAP_CR_PEND;
2668 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669 }
2670
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671response:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002672 release_sock(parent);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002673 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674
2675sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002676 rsp.scid = cpu_to_le16(scid);
2677 rsp.dcid = cpu_to_le16(dcid);
2678 rsp.result = cpu_to_le16(result);
2679 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002681
2682 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2683 struct l2cap_info_req info;
2684 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2685
2686 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2687 conn->info_ident = l2cap_get_ident(conn);
2688
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02002689 schedule_delayed_work(&conn->info_timer,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002690 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2691
2692 l2cap_send_cmd(conn, conn->info_ident,
2693 L2CAP_INFO_REQ, sizeof(info), &info);
2694 }
2695
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002696 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002697 result == L2CAP_CR_SUCCESS) {
2698 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002699 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002700 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002701 l2cap_build_conf_req(chan, buf), buf);
2702 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002703 }
2704
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705 return 0;
2706}
2707
2708static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2709{
2710 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2711 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002712 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713 struct sock *sk;
2714 u8 req[128];
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002715 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716
2717 scid = __le16_to_cpu(rsp->scid);
2718 dcid = __le16_to_cpu(rsp->dcid);
2719 result = __le16_to_cpu(rsp->result);
2720 status = __le16_to_cpu(rsp->status);
2721
Andrei Emeltchenko1b009c92012-02-21 12:54:54 +02002722 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
2723 dcid, scid, result, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002725 mutex_lock(&conn->chan_lock);
2726
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727 if (scid) {
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002728 chan = __l2cap_get_chan_by_scid(conn, scid);
2729 if (!chan) {
2730 err = -EFAULT;
2731 goto unlock;
2732 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 } else {
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002734 chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
2735 if (!chan) {
2736 err = -EFAULT;
2737 goto unlock;
2738 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 }
2740
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002741 err = 0;
2742
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002743 sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002744 lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002745
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746 switch (result) {
2747 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002748 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002749 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002750 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002751 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002752
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002753 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002754 break;
2755
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002757 l2cap_build_conf_req(chan, req), req);
2758 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 break;
2760
2761 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002762 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763 break;
2764
2765 default:
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002766 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 break;
2768 }
2769
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002770 release_sock(sk);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002771
2772unlock:
2773 mutex_unlock(&conn->chan_lock);
2774
2775 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776}
2777
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002778static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002779{
2780 /* FCS is enabled only in ERTM or streaming mode, if one or both
2781 * sides request it.
2782 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002783 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002784 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002785 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002786 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002787}
2788
Al Viro88219a02007-07-29 00:17:25 -07002789static 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 -07002790{
2791 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2792 u16 dcid, flags;
2793 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002794 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002796 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797
2798 dcid = __le16_to_cpu(req->dcid);
2799 flags = __le16_to_cpu(req->flags);
2800
2801 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2802
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002803 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002804 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805 return -ENOENT;
2806
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002807 sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002808 lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002809
David S. Miller033b1142011-07-21 13:38:42 -07002810 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002811 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002812
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002813 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2814 rej.scid = cpu_to_le16(chan->scid);
2815 rej.dcid = cpu_to_le16(chan->dcid);
2816
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002817 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2818 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002819 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002820 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002821
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002822 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002823 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002824 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002825 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002826 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002827 L2CAP_CONF_REJECT, flags), rsp);
2828 goto unlock;
2829 }
2830
2831 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002832 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2833 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834
2835 if (flags & 0x0001) {
2836 /* Incomplete config. Send empty response. */
2837 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002838 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002839 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840 goto unlock;
2841 }
2842
2843 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002844 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002845 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002846 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002848 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002850 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002851 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002852
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002853 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002854 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002855
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002856 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002857 goto unlock;
2858
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002859 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002860 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002861
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002862 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002863
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002864 chan->next_tx_seq = 0;
2865 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002866 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002867 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002868 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002869
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02002870 l2cap_chan_ready(chan);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002871 goto unlock;
2872 }
2873
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002874 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002875 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002876 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002877 l2cap_build_conf_req(chan, buf), buf);
2878 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879 }
2880
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002881 /* Got Conf Rsp PENDING from remote side and asume we sent
2882 Conf Rsp PENDING in the code above */
2883 if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
2884 test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2885
2886 /* check compatibility */
2887
2888 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2889 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2890
2891 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002892 l2cap_build_conf_rsp(chan, rsp,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002893 L2CAP_CONF_SUCCESS, 0x0000), rsp);
2894 }
2895
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896unlock:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002897 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002898 return 0;
2899}
2900
2901static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2902{
2903 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2904 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002905 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002907 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908
2909 scid = __le16_to_cpu(rsp->scid);
2910 flags = __le16_to_cpu(rsp->flags);
2911 result = __le16_to_cpu(rsp->result);
2912
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002913 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2914 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002916 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002917 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002918 return 0;
2919
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002920 sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002921 lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002922
Linus Torvalds1da177e2005-04-16 15:20:36 -07002923 switch (result) {
2924 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002925 l2cap_conf_rfc_get(chan, rsp->data, len);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002926 clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002927 break;
2928
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002929 case L2CAP_CONF_PENDING:
2930 set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
2931
2932 if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2933 char buf[64];
2934
2935 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2936 buf, &result);
2937 if (len < 0) {
2938 l2cap_send_disconn_req(conn, chan, ECONNRESET);
2939 goto done;
2940 }
2941
2942 /* check compatibility */
2943
2944 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2945 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2946
2947 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002948 l2cap_build_conf_rsp(chan, buf,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002949 L2CAP_CONF_SUCCESS, 0x0000), buf);
2950 }
2951 goto done;
2952
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002954 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002955 char req[64];
2956
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002957 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002958 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002959 goto done;
2960 }
2961
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002962 /* throw out any old stored conf requests */
2963 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002964 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2965 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002966 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002967 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002968 goto done;
2969 }
2970
2971 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2972 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002973 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002974 if (result != L2CAP_CONF_SUCCESS)
2975 goto done;
2976 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977 }
2978
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002979 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002980 sk->sk_err = ECONNRESET;
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01002981 __set_chan_timer(chan,
2982 msecs_to_jiffies(L2CAP_DISC_REJ_TIMEOUT));
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002983 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002984 goto done;
2985 }
2986
2987 if (flags & 0x01)
2988 goto done;
2989
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002990 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002992 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002993 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002994
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002995 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002996 chan->next_tx_seq = 0;
2997 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002998 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002999 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003000 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003001
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02003002 l2cap_chan_ready(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003 }
3004
3005done:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003006 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 return 0;
3008}
3009
3010static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3011{
3012 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3013 struct l2cap_disconn_rsp rsp;
3014 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003015 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016 struct sock *sk;
3017
3018 scid = __le16_to_cpu(req->scid);
3019 dcid = __le16_to_cpu(req->dcid);
3020
3021 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3022
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003023 mutex_lock(&conn->chan_lock);
3024
3025 chan = __l2cap_get_chan_by_scid(conn, dcid);
3026 if (!chan) {
3027 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028 return 0;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003029 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003031 sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003032 lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003033
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003034 rsp.dcid = cpu_to_le16(chan->scid);
3035 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003036 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3037
3038 sk->sk_shutdown = SHUTDOWN_MASK;
3039
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003040 l2cap_chan_del(chan, ECONNRESET);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003041 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003042
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003043 chan->ops->close(chan->data);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003044
3045 mutex_unlock(&conn->chan_lock);
3046
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047 return 0;
3048}
3049
3050static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3051{
3052 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3053 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003054 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055 struct sock *sk;
3056
3057 scid = __le16_to_cpu(rsp->scid);
3058 dcid = __le16_to_cpu(rsp->dcid);
3059
3060 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3061
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003062 mutex_lock(&conn->chan_lock);
3063
3064 chan = __l2cap_get_chan_by_scid(conn, scid);
3065 if (!chan) {
3066 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067 return 0;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003068 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003070 sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003071 lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003072
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003073 l2cap_chan_del(chan, 0);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003074 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003076 chan->ops->close(chan->data);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003077
3078 mutex_unlock(&conn->chan_lock);
3079
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080 return 0;
3081}
3082
3083static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3084{
3085 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003086 u16 type;
3087
3088 type = __le16_to_cpu(req->type);
3089
3090 BT_DBG("type 0x%4.4x", type);
3091
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003092 if (type == L2CAP_IT_FEAT_MASK) {
3093 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003094 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003095 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3096 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3097 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003098 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003099 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3100 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003101 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003102 feat_mask |= L2CAP_FEAT_EXT_FLOW
3103 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003104
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003105 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003106 l2cap_send_cmd(conn, cmd->ident,
3107 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003108 } else if (type == L2CAP_IT_FIXED_CHAN) {
3109 u8 buf[12];
3110 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
Mat Martineau50a147c2011-11-02 16:18:34 -07003111
3112 if (enable_hs)
3113 l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
3114 else
3115 l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
3116
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003117 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3118 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003119 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003120 l2cap_send_cmd(conn, cmd->ident,
3121 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003122 } else {
3123 struct l2cap_info_rsp rsp;
3124 rsp.type = cpu_to_le16(type);
3125 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3126 l2cap_send_cmd(conn, cmd->ident,
3127 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3128 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129
3130 return 0;
3131}
3132
3133static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3134{
3135 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3136 u16 type, result;
3137
3138 type = __le16_to_cpu(rsp->type);
3139 result = __le16_to_cpu(rsp->result);
3140
3141 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3142
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003143 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3144 if (cmd->ident != conn->info_ident ||
3145 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3146 return 0;
3147
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02003148 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003149
Ville Tervoadb08ed2010-08-04 09:43:33 +03003150 if (result != L2CAP_IR_SUCCESS) {
3151 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3152 conn->info_ident = 0;
3153
3154 l2cap_conn_start(conn);
3155
3156 return 0;
3157 }
3158
Marcel Holtmann984947d2009-02-06 23:35:19 +01003159 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003160 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003161
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003162 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003163 struct l2cap_info_req req;
3164 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3165
3166 conn->info_ident = l2cap_get_ident(conn);
3167
3168 l2cap_send_cmd(conn, conn->info_ident,
3169 L2CAP_INFO_REQ, sizeof(req), &req);
3170 } else {
3171 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3172 conn->info_ident = 0;
3173
3174 l2cap_conn_start(conn);
3175 }
3176 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003177 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003178 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003179
3180 l2cap_conn_start(conn);
3181 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003182
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183 return 0;
3184}
3185
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003186static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3187 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3188 void *data)
3189{
3190 struct l2cap_create_chan_req *req = data;
3191 struct l2cap_create_chan_rsp rsp;
3192 u16 psm, scid;
3193
3194 if (cmd_len != sizeof(*req))
3195 return -EPROTO;
3196
3197 if (!enable_hs)
3198 return -EINVAL;
3199
3200 psm = le16_to_cpu(req->psm);
3201 scid = le16_to_cpu(req->scid);
3202
3203 BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3204
3205 /* Placeholder: Always reject */
3206 rsp.dcid = 0;
3207 rsp.scid = cpu_to_le16(scid);
3208 rsp.result = L2CAP_CR_NO_MEM;
3209 rsp.status = L2CAP_CS_NO_INFO;
3210
3211 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3212 sizeof(rsp), &rsp);
3213
3214 return 0;
3215}
3216
3217static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3218 struct l2cap_cmd_hdr *cmd, void *data)
3219{
3220 BT_DBG("conn %p", conn);
3221
3222 return l2cap_connect_rsp(conn, cmd, data);
3223}
3224
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003225static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
3226 u16 icid, u16 result)
3227{
3228 struct l2cap_move_chan_rsp rsp;
3229
3230 BT_DBG("icid %d, result %d", icid, result);
3231
3232 rsp.icid = cpu_to_le16(icid);
3233 rsp.result = cpu_to_le16(result);
3234
3235 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
3236}
3237
3238static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
3239 struct l2cap_chan *chan, u16 icid, u16 result)
3240{
3241 struct l2cap_move_chan_cfm cfm;
3242 u8 ident;
3243
3244 BT_DBG("icid %d, result %d", icid, result);
3245
3246 ident = l2cap_get_ident(conn);
3247 if (chan)
3248 chan->ident = ident;
3249
3250 cfm.icid = cpu_to_le16(icid);
3251 cfm.result = cpu_to_le16(result);
3252
3253 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
3254}
3255
3256static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
3257 u16 icid)
3258{
3259 struct l2cap_move_chan_cfm_rsp rsp;
3260
3261 BT_DBG("icid %d", icid);
3262
3263 rsp.icid = cpu_to_le16(icid);
3264 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
3265}
3266
3267static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
3268 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3269{
3270 struct l2cap_move_chan_req *req = data;
3271 u16 icid = 0;
3272 u16 result = L2CAP_MR_NOT_ALLOWED;
3273
3274 if (cmd_len != sizeof(*req))
3275 return -EPROTO;
3276
3277 icid = le16_to_cpu(req->icid);
3278
3279 BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
3280
3281 if (!enable_hs)
3282 return -EINVAL;
3283
3284 /* Placeholder: Always refuse */
3285 l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
3286
3287 return 0;
3288}
3289
3290static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
3291 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3292{
3293 struct l2cap_move_chan_rsp *rsp = data;
3294 u16 icid, result;
3295
3296 if (cmd_len != sizeof(*rsp))
3297 return -EPROTO;
3298
3299 icid = le16_to_cpu(rsp->icid);
3300 result = le16_to_cpu(rsp->result);
3301
3302 BT_DBG("icid %d, result %d", icid, result);
3303
3304 /* Placeholder: Always unconfirmed */
3305 l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
3306
3307 return 0;
3308}
3309
3310static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
3311 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3312{
3313 struct l2cap_move_chan_cfm *cfm = data;
3314 u16 icid, result;
3315
3316 if (cmd_len != sizeof(*cfm))
3317 return -EPROTO;
3318
3319 icid = le16_to_cpu(cfm->icid);
3320 result = le16_to_cpu(cfm->result);
3321
3322 BT_DBG("icid %d, result %d", icid, result);
3323
3324 l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
3325
3326 return 0;
3327}
3328
3329static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
3330 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3331{
3332 struct l2cap_move_chan_cfm_rsp *rsp = data;
3333 u16 icid;
3334
3335 if (cmd_len != sizeof(*rsp))
3336 return -EPROTO;
3337
3338 icid = le16_to_cpu(rsp->icid);
3339
3340 BT_DBG("icid %d", icid);
3341
3342 return 0;
3343}
3344
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003345static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02003346 u16 to_multiplier)
3347{
3348 u16 max_latency;
3349
3350 if (min > max || min < 6 || max > 3200)
3351 return -EINVAL;
3352
3353 if (to_multiplier < 10 || to_multiplier > 3200)
3354 return -EINVAL;
3355
3356 if (max >= to_multiplier * 8)
3357 return -EINVAL;
3358
3359 max_latency = (to_multiplier * 8 / max) - 1;
3360 if (latency > 499 || latency > max_latency)
3361 return -EINVAL;
3362
3363 return 0;
3364}
3365
3366static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3367 struct l2cap_cmd_hdr *cmd, u8 *data)
3368{
3369 struct hci_conn *hcon = conn->hcon;
3370 struct l2cap_conn_param_update_req *req;
3371 struct l2cap_conn_param_update_rsp rsp;
3372 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003373 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02003374
3375 if (!(hcon->link_mode & HCI_LM_MASTER))
3376 return -EINVAL;
3377
3378 cmd_len = __le16_to_cpu(cmd->len);
3379 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3380 return -EPROTO;
3381
3382 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003383 min = __le16_to_cpu(req->min);
3384 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02003385 latency = __le16_to_cpu(req->latency);
3386 to_multiplier = __le16_to_cpu(req->to_multiplier);
3387
3388 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3389 min, max, latency, to_multiplier);
3390
3391 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003392
3393 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
3394 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02003395 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3396 else
3397 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3398
3399 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3400 sizeof(rsp), &rsp);
3401
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003402 if (!err)
3403 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
3404
Claudio Takahaside731152011-02-11 19:28:55 -02003405 return 0;
3406}
3407
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003408static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
3409 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
3410{
3411 int err = 0;
3412
3413 switch (cmd->code) {
3414 case L2CAP_COMMAND_REJ:
3415 l2cap_command_rej(conn, cmd, data);
3416 break;
3417
3418 case L2CAP_CONN_REQ:
3419 err = l2cap_connect_req(conn, cmd, data);
3420 break;
3421
3422 case L2CAP_CONN_RSP:
3423 err = l2cap_connect_rsp(conn, cmd, data);
3424 break;
3425
3426 case L2CAP_CONF_REQ:
3427 err = l2cap_config_req(conn, cmd, cmd_len, data);
3428 break;
3429
3430 case L2CAP_CONF_RSP:
3431 err = l2cap_config_rsp(conn, cmd, data);
3432 break;
3433
3434 case L2CAP_DISCONN_REQ:
3435 err = l2cap_disconnect_req(conn, cmd, data);
3436 break;
3437
3438 case L2CAP_DISCONN_RSP:
3439 err = l2cap_disconnect_rsp(conn, cmd, data);
3440 break;
3441
3442 case L2CAP_ECHO_REQ:
3443 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3444 break;
3445
3446 case L2CAP_ECHO_RSP:
3447 break;
3448
3449 case L2CAP_INFO_REQ:
3450 err = l2cap_information_req(conn, cmd, data);
3451 break;
3452
3453 case L2CAP_INFO_RSP:
3454 err = l2cap_information_rsp(conn, cmd, data);
3455 break;
3456
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003457 case L2CAP_CREATE_CHAN_REQ:
3458 err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3459 break;
3460
3461 case L2CAP_CREATE_CHAN_RSP:
3462 err = l2cap_create_channel_rsp(conn, cmd, data);
3463 break;
3464
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003465 case L2CAP_MOVE_CHAN_REQ:
3466 err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
3467 break;
3468
3469 case L2CAP_MOVE_CHAN_RSP:
3470 err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
3471 break;
3472
3473 case L2CAP_MOVE_CHAN_CFM:
3474 err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
3475 break;
3476
3477 case L2CAP_MOVE_CHAN_CFM_RSP:
3478 err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
3479 break;
3480
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003481 default:
3482 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3483 err = -EINVAL;
3484 break;
3485 }
3486
3487 return err;
3488}
3489
3490static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3491 struct l2cap_cmd_hdr *cmd, u8 *data)
3492{
3493 switch (cmd->code) {
3494 case L2CAP_COMMAND_REJ:
3495 return 0;
3496
3497 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003498 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003499
3500 case L2CAP_CONN_PARAM_UPDATE_RSP:
3501 return 0;
3502
3503 default:
3504 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3505 return -EINVAL;
3506 }
3507}
3508
3509static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3510 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003511{
3512 u8 *data = skb->data;
3513 int len = skb->len;
3514 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003515 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003516
3517 l2cap_raw_recv(conn, skb);
3518
3519 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003520 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3522 data += L2CAP_CMD_HDR_SIZE;
3523 len -= L2CAP_CMD_HDR_SIZE;
3524
Al Viro88219a02007-07-29 00:17:25 -07003525 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003526
Al Viro88219a02007-07-29 00:17:25 -07003527 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 -07003528
Al Viro88219a02007-07-29 00:17:25 -07003529 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003530 BT_DBG("corrupted command");
3531 break;
3532 }
3533
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003534 if (conn->hcon->type == LE_LINK)
3535 err = l2cap_le_sig_cmd(conn, &cmd, data);
3536 else
3537 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003538
3539 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003540 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003541
3542 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003543
3544 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003545 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003546 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3547 }
3548
Al Viro88219a02007-07-29 00:17:25 -07003549 data += cmd_len;
3550 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551 }
3552
3553 kfree_skb(skb);
3554}
3555
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003556static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003557{
3558 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003559 int hdr_size;
3560
3561 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3562 hdr_size = L2CAP_EXT_HDR_SIZE;
3563 else
3564 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003565
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003566 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003567 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003568 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3569 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3570
3571 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003572 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003573 }
3574 return 0;
3575}
3576
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003577static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003578{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003579 u32 control = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003580
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003581 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003582
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003583 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003584
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003585 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003586 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003587 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003588 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003589 }
3590
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003591 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003592 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003593
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003594 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003595
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003596 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003597 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003598 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003599 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003600 }
3601}
3602
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003603static 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 -03003604{
3605 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003606 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003607
3608 bt_cb(skb)->tx_seq = tx_seq;
3609 bt_cb(skb)->sar = sar;
3610
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003611 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003612
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003613 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003614
Szymon Janc039d9572011-11-16 09:32:19 +01003615 while (next_skb) {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003616 if (bt_cb(next_skb)->tx_seq == tx_seq)
3617 return -EINVAL;
3618
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003619 next_tx_seq_offset = __seq_offset(chan,
3620 bt_cb(next_skb)->tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003621
3622 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003623 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003624 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003625 }
3626
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003627 if (skb_queue_is_last(&chan->srej_q, next_skb))
Szymon Janc039d9572011-11-16 09:32:19 +01003628 next_skb = NULL;
3629 else
3630 next_skb = skb_queue_next(&chan->srej_q, next_skb);
3631 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003632
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003633 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003634
3635 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003636}
3637
Mat Martineau84084a32011-07-22 14:54:00 -07003638static void append_skb_frag(struct sk_buff *skb,
3639 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003640{
Mat Martineau84084a32011-07-22 14:54:00 -07003641 /* skb->len reflects data in skb as well as all fragments
3642 * skb->data_len reflects only data in fragments
3643 */
3644 if (!skb_has_frag_list(skb))
3645 skb_shinfo(skb)->frag_list = new_frag;
3646
3647 new_frag->next = NULL;
3648
3649 (*last_frag)->next = new_frag;
3650 *last_frag = new_frag;
3651
3652 skb->len += new_frag->len;
3653 skb->data_len += new_frag->len;
3654 skb->truesize += new_frag->truesize;
3655}
3656
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003657static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
Mat Martineau84084a32011-07-22 14:54:00 -07003658{
3659 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003660
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003661 switch (__get_ctrl_sar(chan, control)) {
3662 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003663 if (chan->sdu)
3664 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003665
Mat Martineau84084a32011-07-22 14:54:00 -07003666 err = chan->ops->recv(chan->data, skb);
3667 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003668
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003669 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003670 if (chan->sdu)
3671 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003672
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003673 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003674 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003675
Mat Martineau84084a32011-07-22 14:54:00 -07003676 if (chan->sdu_len > chan->imtu) {
3677 err = -EMSGSIZE;
3678 break;
3679 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003680
Mat Martineau84084a32011-07-22 14:54:00 -07003681 if (skb->len >= chan->sdu_len)
3682 break;
3683
3684 chan->sdu = skb;
3685 chan->sdu_last_frag = skb;
3686
3687 skb = NULL;
3688 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003689 break;
3690
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003691 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003692 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003693 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003694
Mat Martineau84084a32011-07-22 14:54:00 -07003695 append_skb_frag(chan->sdu, skb,
3696 &chan->sdu_last_frag);
3697 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003698
Mat Martineau84084a32011-07-22 14:54:00 -07003699 if (chan->sdu->len >= chan->sdu_len)
3700 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003701
Mat Martineau84084a32011-07-22 14:54:00 -07003702 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003703 break;
3704
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003705 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003706 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003707 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003708
Mat Martineau84084a32011-07-22 14:54:00 -07003709 append_skb_frag(chan->sdu, skb,
3710 &chan->sdu_last_frag);
3711 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003712
Mat Martineau84084a32011-07-22 14:54:00 -07003713 if (chan->sdu->len != chan->sdu_len)
3714 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003715
Mat Martineau84084a32011-07-22 14:54:00 -07003716 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003717
Mat Martineau84084a32011-07-22 14:54:00 -07003718 if (!err) {
3719 /* Reassembly complete */
3720 chan->sdu = NULL;
3721 chan->sdu_last_frag = NULL;
3722 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003723 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003724 break;
3725 }
3726
Mat Martineau84084a32011-07-22 14:54:00 -07003727 if (err) {
3728 kfree_skb(skb);
3729 kfree_skb(chan->sdu);
3730 chan->sdu = NULL;
3731 chan->sdu_last_frag = NULL;
3732 chan->sdu_len = 0;
3733 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003734
Mat Martineau84084a32011-07-22 14:54:00 -07003735 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003736}
3737
Mat Martineau26f880d2011-07-07 09:39:01 -07003738static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003739{
Mat Martineau26f880d2011-07-07 09:39:01 -07003740 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003741
Mat Martineau26f880d2011-07-07 09:39:01 -07003742 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3743
Szymon Janc77f918b2012-01-11 10:59:48 +01003744 __set_ack_timer(chan);
Mat Martineau26f880d2011-07-07 09:39:01 -07003745}
3746
3747static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3748{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003749 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003750
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003751 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003752 goto done;
3753
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003754 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003755 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003756 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003757 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003758 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003759
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003760 __clear_retrans_timer(chan);
3761 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003762
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003763 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003764
3765done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003766 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3767 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003768
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003769 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003770}
3771
Mat Martineaue3281402011-07-07 09:39:02 -07003772void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003773{
Mat Martineaue3281402011-07-07 09:39:02 -07003774 if (chan->mode == L2CAP_MODE_ERTM) {
3775 if (busy)
3776 l2cap_ertm_enter_local_busy(chan);
3777 else
3778 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003779 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003780}
3781
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003782static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003783{
3784 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003785 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003786
Mat Martineaue3281402011-07-07 09:39:02 -07003787 while ((skb = skb_peek(&chan->srej_q)) &&
3788 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3789 int err;
3790
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003791 if (bt_cb(skb)->tx_seq != tx_seq)
3792 break;
3793
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003794 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003795 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003796 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003797
3798 if (err < 0) {
3799 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3800 break;
3801 }
3802
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003803 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
3804 tx_seq = __next_seq(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003805 }
3806}
3807
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003808static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003809{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003810 struct srej_list *l, *tmp;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003811 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003812
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003813 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003814 if (l->tx_seq == tx_seq) {
3815 list_del(&l->list);
3816 kfree(l);
3817 return;
3818 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003819 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003820 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003821 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003822 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003823 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003824 }
3825}
3826
Szymon Jancaef89f22011-11-16 09:32:18 +01003827static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003828{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003829 struct srej_list *new;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003830 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003831
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003832 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003833 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003834 control |= __set_reqseq(chan, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003835 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003836
3837 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Szymon Jancaef89f22011-11-16 09:32:18 +01003838 if (!new)
3839 return -ENOMEM;
3840
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003841 new->tx_seq = chan->expected_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003842
3843 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
3844
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003845 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003846 }
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003847
3848 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Szymon Jancaef89f22011-11-16 09:32:18 +01003849
3850 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003851}
3852
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003853static 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 -03003854{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003855 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003856 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003857 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003858 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003859 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003860 int err = 0;
3861
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003862 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 -03003863 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003864
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003865 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003866 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003867 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003868 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003869 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003870 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003871 }
3872
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003873 chan->expected_ack_seq = req_seq;
3874 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003875
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003876 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003877
3878 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003879 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003880 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003881 goto drop;
3882 }
3883
Szymon Janc77f918b2012-01-11 10:59:48 +01003884 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3885 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
3886 l2cap_send_ack(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003887 goto drop;
Szymon Janc77f918b2012-01-11 10:59:48 +01003888 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003889
Mat Martineau02f1b642011-06-29 14:35:19 -07003890 if (tx_seq == chan->expected_tx_seq)
3891 goto expected;
3892
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003893 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003894 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003895
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003896 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003897 struct srej_list, list);
3898 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003899 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003900 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003901
3902 list_del(&first->list);
3903 kfree(first);
3904
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003905 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003906 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003907 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003908 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003909 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003910 }
3911 } else {
3912 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003913
3914 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003915 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003916 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003917
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003918 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003919 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003920 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003921 return 0;
3922 }
3923 }
Szymon Jancaef89f22011-11-16 09:32:18 +01003924
3925 err = l2cap_send_srejframe(chan, tx_seq);
3926 if (err < 0) {
3927 l2cap_send_disconn_req(chan->conn, chan, -err);
3928 return err;
3929 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003930 }
3931 } else {
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003932 expected_tx_seq_offset = __seq_offset(chan,
3933 chan->expected_tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003934
3935 /* duplicated tx_seq */
3936 if (tx_seq_offset < expected_tx_seq_offset)
3937 goto drop;
3938
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003939 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003940
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003941 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003942
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003943 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003944 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003945
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003946 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003947 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003948
Szymon Janc0ef3ef02012-01-11 10:59:46 +01003949 /* Set P-bit only if there are some I-frames to ack. */
3950 if (__clear_ack_timer(chan))
3951 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003952
Szymon Jancaef89f22011-11-16 09:32:18 +01003953 err = l2cap_send_srejframe(chan, tx_seq);
3954 if (err < 0) {
3955 l2cap_send_disconn_req(chan->conn, chan, -err);
3956 return err;
3957 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003958 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003959 return 0;
3960
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003961expected:
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003962 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003963
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003964 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003965 bt_cb(skb)->tx_seq = tx_seq;
3966 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003967 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003968 return 0;
3969 }
3970
Mat Martineau84084a32011-07-22 14:54:00 -07003971 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003972 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
3973
Mat Martineaue3281402011-07-07 09:39:02 -07003974 if (err < 0) {
3975 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3976 return err;
3977 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003978
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003979 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003980 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003981 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003982 }
3983
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003984
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003985 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3986 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003987 l2cap_send_ack(chan);
Gustavo F. Padovan4d611e42011-06-23 19:30:48 -03003988 else
3989 __set_ack_timer(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003990
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003991 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003992
3993drop:
3994 kfree_skb(skb);
3995 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003996}
3997
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003998static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003999{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004000 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004001 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004002
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004003 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004004 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004005
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004006 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004007 set_bit(CONN_SEND_FBIT, &chan->conn_state);
4008 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
4009 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004010 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004011 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004012
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004013 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004014 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004015 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004016 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004017 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004018
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004019 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004020 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004021
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004022 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004023 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004024
4025 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004026 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004027 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004028 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004029
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004030 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4031 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004032 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02004033 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004034 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004035 }
4036}
4037
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004038static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004039{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004040 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004041
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004042 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004043
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004044 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004045
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004046 chan->expected_ack_seq = tx_seq;
4047 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004048
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004049 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004050 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004051 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004052 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004053 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004054
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004055 if (test_bit(CONN_WAIT_F, &chan->conn_state))
4056 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004057 }
4058}
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004059static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004060{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004061 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004062
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004063 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004064
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004065 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004066
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004067 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004068 chan->expected_ack_seq = tx_seq;
4069 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004070
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004071 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004072 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004073
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004074 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004075
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004076 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004077 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004078 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004079 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004080 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004081 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004082 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004083 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004084 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004085 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004086 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004087 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004088 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004089 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004090 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004091 }
4092 }
4093}
4094
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004095static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004096{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004097 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004098
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004099 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004100
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004101 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004102 chan->expected_ack_seq = tx_seq;
4103 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004104
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004105 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004106 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004107
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004108 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004109 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004110 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004111 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004112 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004113 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004114
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004115 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004116 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004117 } else {
4118 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4119 l2cap_send_sframe(chan, rx_control);
4120 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004121}
4122
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004123static 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 -03004124{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004125 BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004126
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004127 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004128 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004129 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004130 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004131 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004132 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004133 }
4134
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004135 switch (__get_ctrl_super(chan, rx_control)) {
4136 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004137 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004138 break;
4139
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004140 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004141 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004142 break;
4143
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004144 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004145 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004146 break;
4147
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004148 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004149 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004150 break;
4151 }
4152
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004153 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004154 return 0;
4155}
4156
Szymon Janccad8f1d02012-01-23 10:06:05 +01004157static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004158{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004159 u32 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004160 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004161 int len, next_tx_seq_offset, req_seq_offset;
4162
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004163 control = __get_control(chan, skb->data);
4164 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004165 len = skb->len;
4166
4167 /*
4168 * We can just drop the corrupted I-frame here.
4169 * Receiver will miss it and start proper recovery
4170 * procedures and ask retransmission.
4171 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004172 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004173 goto drop;
4174
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004175 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004176 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004177
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004178 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004179 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004180
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004181 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004182 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004183 goto drop;
4184 }
4185
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004186 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004187
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004188 req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4189
4190 next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4191 chan->expected_ack_seq);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004192
4193 /* check for invalid req-seq */
4194 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004195 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004196 goto drop;
4197 }
4198
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004199 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004200 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004201 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004202 goto drop;
4203 }
4204
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004205 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004206 } else {
4207 if (len != 0) {
4208 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004209 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004210 goto drop;
4211 }
4212
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004213 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004214 }
4215
4216 return 0;
4217
4218drop:
4219 kfree_skb(skb);
4220 return 0;
4221}
4222
Linus Torvalds1da177e2005-04-16 15:20:36 -07004223static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4224{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004225 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07004226 struct sock *sk = NULL;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004227 u32 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004228 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004229 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004231 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004232 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233 BT_DBG("unknown cid 0x%4.4x", cid);
4234 goto drop;
4235 }
4236
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004237 sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004238 lock_sock(sk);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004239
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004240 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004241
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004242 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004243 goto drop;
4244
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004245 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004246 case L2CAP_MODE_BASIC:
4247 /* If socket recv buffers overflows we drop data here
4248 * which is *bad* because L2CAP has to be reliable.
4249 * But we don't have any other choice. L2CAP doesn't
4250 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004251
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004252 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004253 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004255 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004256 goto done;
4257 break;
4258
4259 case L2CAP_MODE_ERTM:
Andrei Emeltchenko5ef8cb92012-01-13 17:21:42 +02004260 l2cap_ertm_data_rcv(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004261
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004262 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004263
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004264 case L2CAP_MODE_STREAMING:
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004265 control = __get_control(chan, skb->data);
4266 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004267 len = skb->len;
4268
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004269 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004270 goto drop;
4271
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004272 if (__is_sar_start(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004273 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004274
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004275 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004276 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004277
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004278 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004279 goto drop;
4280
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004281 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004282
Mat Martineau84084a32011-07-22 14:54:00 -07004283 if (chan->expected_tx_seq != tx_seq) {
4284 /* Frame(s) missing - must discard partial SDU */
4285 kfree_skb(chan->sdu);
4286 chan->sdu = NULL;
4287 chan->sdu_last_frag = NULL;
4288 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004289
Mat Martineau84084a32011-07-22 14:54:00 -07004290 /* TODO: Notify userland of missing data */
4291 }
4292
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004293 chan->expected_tx_seq = __next_seq(chan, tx_seq);
Mat Martineau84084a32011-07-22 14:54:00 -07004294
4295 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
4296 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004297
4298 goto done;
4299
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004300 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004301 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004302 break;
4303 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004304
4305drop:
4306 kfree_skb(skb);
4307
4308done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004309 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004310 release_sock(sk);
Marcel Holtmann01394182006-07-03 10:02:46 +02004311
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312 return 0;
4313}
4314
Al Viro8e036fc2007-07-29 00:16:36 -07004315static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004316{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004317 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004318 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004320 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
4321 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322 goto drop;
4323
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004324 sk = chan->sk;
4325
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004326 lock_sock(sk);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00004327
Linus Torvalds1da177e2005-04-16 15:20:36 -07004328 BT_DBG("sk %p, len %d", sk, skb->len);
4329
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004330 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004331 goto drop;
4332
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004333 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334 goto drop;
4335
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004336 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337 goto done;
4338
4339drop:
4340 kfree_skb(skb);
4341
4342done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004343 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004344 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345 return 0;
4346}
4347
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004348static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
4349{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004350 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004351 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004352
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004353 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
4354 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004355 goto drop;
4356
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004357 sk = chan->sk;
4358
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004359 lock_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004360
4361 BT_DBG("sk %p, len %d", sk, skb->len);
4362
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004363 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004364 goto drop;
4365
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004366 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004367 goto drop;
4368
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004369 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004370 goto done;
4371
4372drop:
4373 kfree_skb(skb);
4374
4375done:
4376 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004377 release_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004378 return 0;
4379}
4380
Linus Torvalds1da177e2005-04-16 15:20:36 -07004381static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4382{
4383 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004384 u16 cid, len;
4385 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004386
4387 skb_pull(skb, L2CAP_HDR_SIZE);
4388 cid = __le16_to_cpu(lh->cid);
4389 len = __le16_to_cpu(lh->len);
4390
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004391 if (len != skb->len) {
4392 kfree_skb(skb);
4393 return;
4394 }
4395
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4397
4398 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004399 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004400 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401 l2cap_sig_channel(conn, skb);
4402 break;
4403
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004404 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004405 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406 skb_pull(skb, 2);
4407 l2cap_conless_channel(conn, psm, skb);
4408 break;
4409
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004410 case L2CAP_CID_LE_DATA:
4411 l2cap_att_channel(conn, cid, skb);
4412 break;
4413
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004414 case L2CAP_CID_SMP:
4415 if (smp_sig_channel(conn, skb))
4416 l2cap_conn_del(conn->hcon, EACCES);
4417 break;
4418
Linus Torvalds1da177e2005-04-16 15:20:36 -07004419 default:
4420 l2cap_data_channel(conn, cid, skb);
4421 break;
4422 }
4423}
4424
4425/* ---- L2CAP interface with lower layer (HCI) ---- */
4426
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004427int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004428{
4429 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004430 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004431
Linus Torvalds1da177e2005-04-16 15:20:36 -07004432 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4433
4434 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004435 read_lock(&chan_list_lock);
4436 list_for_each_entry(c, &chan_list, global_l) {
4437 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004438
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004439 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440 continue;
4441
4442 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004443 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004444 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004445 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004447 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4448 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004449 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004450 lm2 |= HCI_LM_MASTER;
4451 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004453 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454
4455 return exact ? lm1 : lm2;
4456}
4457
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004458int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004459{
Marcel Holtmann01394182006-07-03 10:02:46 +02004460 struct l2cap_conn *conn;
4461
Linus Torvalds1da177e2005-04-16 15:20:36 -07004462 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4463
Linus Torvalds1da177e2005-04-16 15:20:36 -07004464 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004465 conn = l2cap_conn_add(hcon, status);
4466 if (conn)
4467 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004468 } else
Joe Perchese1750722011-06-29 18:18:29 -07004469 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004470
4471 return 0;
4472}
4473
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004474int l2cap_disconn_ind(struct hci_conn *hcon)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004475{
4476 struct l2cap_conn *conn = hcon->l2cap_data;
4477
4478 BT_DBG("hcon %p", hcon);
4479
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004480 if (!conn)
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02004481 return HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01004482 return conn->disc_reason;
4483}
4484
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004485int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004486{
4487 BT_DBG("hcon %p reason %d", hcon, reason);
4488
Joe Perchese1750722011-06-29 18:18:29 -07004489 l2cap_conn_del(hcon, bt_to_errno(reason));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004490 return 0;
4491}
4492
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004493static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004494{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004495 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004496 return;
4497
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004498 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004499 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004500 __clear_chan_timer(chan);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004501 __set_chan_timer(chan,
4502 msecs_to_jiffies(L2CAP_ENC_TIMEOUT));
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004503 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004504 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004505 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004506 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004507 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004508 }
4509}
4510
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004511int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004512{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004513 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004514 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004515
Marcel Holtmann01394182006-07-03 10:02:46 +02004516 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004517 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004518
Linus Torvalds1da177e2005-04-16 15:20:36 -07004519 BT_DBG("conn %p", conn);
4520
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004521 if (hcon->type == LE_LINK) {
4522 smp_distribute_keys(conn, 0);
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02004523 cancel_delayed_work(&conn->security_timer);
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004524 }
4525
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004526 mutex_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004528 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004529 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004530
Linus Torvalds1da177e2005-04-16 15:20:36 -07004531 bh_lock_sock(sk);
4532
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004533 BT_DBG("chan->scid %d", chan->scid);
4534
4535 if (chan->scid == L2CAP_CID_LE_DATA) {
4536 if (!status && encrypt) {
4537 chan->sec_level = hcon->sec_level;
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02004538 l2cap_chan_ready(chan);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004539 }
4540
4541 bh_unlock_sock(sk);
4542 continue;
4543 }
4544
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004545 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004546 bh_unlock_sock(sk);
4547 continue;
4548 }
4549
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004550 if (!status && (chan->state == BT_CONNECTED ||
4551 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004552 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004553 bh_unlock_sock(sk);
4554 continue;
4555 }
4556
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004557 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004558 if (!status) {
4559 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004560 req.scid = cpu_to_le16(chan->scid);
4561 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004562
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004563 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004564 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004565
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004566 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004567 L2CAP_CONN_REQ, sizeof(req), &req);
4568 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004569 __clear_chan_timer(chan);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004570 __set_chan_timer(chan,
4571 msecs_to_jiffies(L2CAP_DISC_TIMEOUT));
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004572 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004573 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004574 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004575 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004576
4577 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004578 if (bt_sk(sk)->defer_setup) {
4579 struct sock *parent = bt_sk(sk)->parent;
4580 res = L2CAP_CR_PEND;
4581 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004582 if (parent)
4583 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004584 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004585 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004586 res = L2CAP_CR_SUCCESS;
4587 stat = L2CAP_CS_NO_INFO;
4588 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004589 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004590 l2cap_state_change(chan, BT_DISCONN);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004591 __set_chan_timer(chan,
4592 msecs_to_jiffies(L2CAP_DISC_TIMEOUT));
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004593 res = L2CAP_CR_SEC_BLOCK;
4594 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004595 }
4596
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004597 rsp.scid = cpu_to_le16(chan->dcid);
4598 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004599 rsp.result = cpu_to_le16(res);
4600 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004601 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4602 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004603 }
4604
Linus Torvalds1da177e2005-04-16 15:20:36 -07004605 bh_unlock_sock(sk);
4606 }
4607
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004608 mutex_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004609
Linus Torvalds1da177e2005-04-16 15:20:36 -07004610 return 0;
4611}
4612
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004613int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004614{
4615 struct l2cap_conn *conn = hcon->l2cap_data;
4616
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004617 if (!conn)
4618 conn = l2cap_conn_add(hcon, 0);
4619
4620 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004621 goto drop;
4622
4623 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4624
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004625 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004626 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004627 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004628 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004629 int len;
4630
4631 if (conn->rx_len) {
4632 BT_ERR("Unexpected start frame (len %d)", skb->len);
4633 kfree_skb(conn->rx_skb);
4634 conn->rx_skb = NULL;
4635 conn->rx_len = 0;
4636 l2cap_conn_unreliable(conn, ECOMM);
4637 }
4638
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004639 /* Start fragment always begin with Basic L2CAP header */
4640 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004641 BT_ERR("Frame is too short (len %d)", skb->len);
4642 l2cap_conn_unreliable(conn, ECOMM);
4643 goto drop;
4644 }
4645
4646 hdr = (struct l2cap_hdr *) skb->data;
4647 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004648 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004649
4650 if (len == skb->len) {
4651 /* Complete frame received */
4652 l2cap_recv_frame(conn, skb);
4653 return 0;
4654 }
4655
4656 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4657
4658 if (skb->len > len) {
4659 BT_ERR("Frame is too long (len %d, expected len %d)",
4660 skb->len, len);
4661 l2cap_conn_unreliable(conn, ECOMM);
4662 goto drop;
4663 }
4664
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004665 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004666
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004667 if (chan && chan->sk) {
4668 struct sock *sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004669 lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004670
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004671 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004672 BT_ERR("Frame exceeding recv MTU (len %d, "
4673 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004674 chan->imtu);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004675 release_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004676 l2cap_conn_unreliable(conn, ECOMM);
4677 goto drop;
4678 }
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004679 release_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004680 }
4681
Linus Torvalds1da177e2005-04-16 15:20:36 -07004682 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004683 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4684 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004685 goto drop;
4686
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004687 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004688 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004689 conn->rx_len = len - skb->len;
4690 } else {
4691 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4692
4693 if (!conn->rx_len) {
4694 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4695 l2cap_conn_unreliable(conn, ECOMM);
4696 goto drop;
4697 }
4698
4699 if (skb->len > conn->rx_len) {
4700 BT_ERR("Fragment is too long (len %d, expected %d)",
4701 skb->len, conn->rx_len);
4702 kfree_skb(conn->rx_skb);
4703 conn->rx_skb = NULL;
4704 conn->rx_len = 0;
4705 l2cap_conn_unreliable(conn, ECOMM);
4706 goto drop;
4707 }
4708
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004709 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004710 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004711 conn->rx_len -= skb->len;
4712
4713 if (!conn->rx_len) {
4714 /* Complete frame received */
4715 l2cap_recv_frame(conn, conn->rx_skb);
4716 conn->rx_skb = NULL;
4717 }
4718 }
4719
4720drop:
4721 kfree_skb(skb);
4722 return 0;
4723}
4724
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004725static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004726{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004727 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004728
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02004729 read_lock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004730
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004731 list_for_each_entry(c, &chan_list, global_l) {
4732 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004733
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004734 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 +01004735 batostr(&bt_sk(sk)->src),
4736 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004737 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004738 c->scid, c->dcid, c->imtu, c->omtu,
4739 c->sec_level, c->mode);
Andrei Emeltchenko61e1b4b2012-01-19 11:19:50 +02004740 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004741
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02004742 read_unlock(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004743
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004744 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004745}
4746
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004747static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4748{
4749 return single_open(file, l2cap_debugfs_show, inode->i_private);
4750}
4751
4752static const struct file_operations l2cap_debugfs_fops = {
4753 .open = l2cap_debugfs_open,
4754 .read = seq_read,
4755 .llseek = seq_lseek,
4756 .release = single_release,
4757};
4758
4759static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004760
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004761int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004762{
4763 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004764
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004765 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004766 if (err < 0)
4767 return err;
4768
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004769 if (bt_debugfs) {
4770 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4771 bt_debugfs, NULL, &l2cap_debugfs_fops);
4772 if (!l2cap_debugfs)
4773 BT_ERR("Failed to create L2CAP debug file");
4774 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004775
Linus Torvalds1da177e2005-04-16 15:20:36 -07004776 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004777}
4778
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004779void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004780{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004781 debugfs_remove(l2cap_debugfs);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004782 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004783}
4784
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004785module_param(disable_ertm, bool, 0644);
4786MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");