blob: e39eba1ac4da900d690f588f3ee405e3be4e87a4 [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
Andrei Emeltchenkoc03b3552012-02-21 12:54:56 +0200250 mutex_init(&chan->lock);
251
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300252 chan->sk = sk;
253
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200254 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300255 list_add(&chan->global_l, &chan_list);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200256 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300257
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300258 INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300259
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300260 chan->state = BT_OPEN;
261
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300262 atomic_set(&chan->refcnt, 1);
263
Szymon Jancabc545b2011-11-03 16:05:44 +0100264 BT_DBG("sk %p chan %p", sk, chan);
265
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300266 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200267}
268
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300269void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300270{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200271 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300272 list_del(&chan->global_l);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200273 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300274
Ulisses Furquim371fd832011-12-21 20:02:36 -0200275 l2cap_chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300276}
277
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200278static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200279{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300280 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300281 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200282
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +0200283 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +0100284
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300285 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200286
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200287 switch (chan->chan_type) {
288 case L2CAP_CHAN_CONN_ORIENTED:
Ville Tervob62f3282011-02-10 22:38:50 -0300289 if (conn->hcon->type == LE_LINK) {
290 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300291 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300292 chan->scid = L2CAP_CID_LE_DATA;
293 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300294 } else {
295 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300296 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300297 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300298 }
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200299 break;
300
301 case L2CAP_CHAN_CONN_LESS:
Marcel Holtmann01394182006-07-03 10:02:46 +0200302 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300303 chan->scid = L2CAP_CID_CONN_LESS;
304 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300305 chan->omtu = L2CAP_DEFAULT_MTU;
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200306 break;
307
308 default:
Marcel Holtmann01394182006-07-03 10:02:46 +0200309 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300310 chan->scid = L2CAP_CID_SIGNALING;
311 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300312 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200313 }
314
Andrei Emeltchenko8f7975b2011-10-13 16:18:54 +0300315 chan->local_id = L2CAP_BESTEFFORT_ID;
316 chan->local_stype = L2CAP_SERV_BESTEFFORT;
317 chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
318 chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
319 chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
320 chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
321
Ulisses Furquim371fd832011-12-21 20:02:36 -0200322 l2cap_chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300323
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200324 mutex_lock(&conn->chan_lock);
325 list_add(&chan->list, &conn->chan_l);
326 mutex_unlock(&conn->chan_lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200327}
328
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900329/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200330 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300331static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200332{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300333 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300334 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200335 struct sock *parent = bt_sk(sk)->parent;
336
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300337 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200338
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300339 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200340
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900341 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300342 /* Delete from channel list */
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200343 list_del(&chan->list);
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200344
Ulisses Furquim371fd832011-12-21 20:02:36 -0200345 l2cap_chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300346
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300347 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200348 hci_conn_put(conn->hcon);
349 }
350
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300351 l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200352 sock_set_flag(sk, SOCK_ZAPPED);
353
354 if (err)
355 sk->sk_err = err;
356
357 if (parent) {
358 bt_accept_unlink(sk);
359 parent->sk_data_ready(parent, 0);
360 } else
361 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300362
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300363 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
364 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300365 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300366
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300367 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300368
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300369 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300370 struct srej_list *l, *tmp;
371
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300372 __clear_retrans_timer(chan);
373 __clear_monitor_timer(chan);
374 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300375
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300376 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300377
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300378 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300379 list_del(&l->list);
380 kfree(l);
381 }
382 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200383}
384
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300385static void l2cap_chan_cleanup_listen(struct sock *parent)
386{
387 struct sock *sk;
388
389 BT_DBG("parent %p", parent);
390
391 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300392 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300393 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200394
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300395 __clear_chan_timer(chan);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300396 lock_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300397 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300398 release_sock(sk);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200399
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300400 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300401 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300402}
403
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300404void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300405{
406 struct l2cap_conn *conn = chan->conn;
407 struct sock *sk = chan->sk;
408
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200409 BT_DBG("chan %p state %s sk %p", chan,
410 state_to_string(chan->state), sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300411
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300412 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300413 case BT_LISTEN:
414 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300415
416 l2cap_state_change(chan, BT_CLOSED);
417 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300418 break;
419
420 case BT_CONNECTED:
421 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300422 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300423 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300424 __clear_chan_timer(chan);
425 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300426 l2cap_send_disconn_req(conn, chan, reason);
427 } else
428 l2cap_chan_del(chan, reason);
429 break;
430
431 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300432 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300433 conn->hcon->type == ACL_LINK) {
434 struct l2cap_conn_rsp rsp;
435 __u16 result;
436
437 if (bt_sk(sk)->defer_setup)
438 result = L2CAP_CR_SEC_BLOCK;
439 else
440 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300441 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300442
443 rsp.scid = cpu_to_le16(chan->dcid);
444 rsp.dcid = cpu_to_le16(chan->scid);
445 rsp.result = cpu_to_le16(result);
446 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
447 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
448 sizeof(rsp), &rsp);
449 }
450
451 l2cap_chan_del(chan, reason);
452 break;
453
454 case BT_CONNECT:
455 case BT_DISCONN:
456 l2cap_chan_del(chan, reason);
457 break;
458
459 default:
460 sock_set_flag(sk, SOCK_ZAPPED);
461 break;
462 }
463}
464
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300465static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530466{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300467 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300468 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530469 case BT_SECURITY_HIGH:
470 return HCI_AT_DEDICATED_BONDING_MITM;
471 case BT_SECURITY_MEDIUM:
472 return HCI_AT_DEDICATED_BONDING;
473 default:
474 return HCI_AT_NO_BONDING;
475 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300476 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300477 if (chan->sec_level == BT_SECURITY_LOW)
478 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530479
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300480 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530481 return HCI_AT_NO_BONDING_MITM;
482 else
483 return HCI_AT_NO_BONDING;
484 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300485 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530486 case BT_SECURITY_HIGH:
487 return HCI_AT_GENERAL_BONDING_MITM;
488 case BT_SECURITY_MEDIUM:
489 return HCI_AT_GENERAL_BONDING;
490 default:
491 return HCI_AT_NO_BONDING;
492 }
493 }
494}
495
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200496/* Service level security */
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200497int l2cap_chan_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200498{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300499 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100500 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200501
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300502 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100503
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300504 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200505}
506
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200507static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200508{
509 u8 id;
510
511 /* Get next available identificator.
512 * 1 - 128 are used by kernel.
513 * 129 - 199 are reserved.
514 * 200 - 254 are used by utilities like l2ping, etc.
515 */
516
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200517 spin_lock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200518
519 if (++conn->tx_ident > 128)
520 conn->tx_ident = 1;
521
522 id = conn->tx_ident;
523
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200524 spin_unlock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200525
526 return id;
527}
528
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300529static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200530{
531 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200532 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200533
534 BT_DBG("code 0x%2.2x", code);
535
536 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300537 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200538
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200539 if (lmp_no_flush_capable(conn->hcon->hdev))
540 flags = ACL_START_NO_FLUSH;
541 else
542 flags = ACL_START;
543
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700544 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +0200545 skb->priority = HCI_PRIO_MAX;
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700546
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200547 hci_send_acl(conn->hchan, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200548}
549
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200550static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
551{
552 struct hci_conn *hcon = chan->conn->hcon;
553 u16 flags;
554
555 BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
556 skb->priority);
557
558 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
559 lmp_no_flush_capable(hcon->hdev))
560 flags = ACL_START_NO_FLUSH;
561 else
562 flags = ACL_START;
563
564 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
565 hci_send_acl(chan->conn->hchan, skb, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566}
567
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300568static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300569{
570 struct sk_buff *skb;
571 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300572 struct l2cap_conn *conn = chan->conn;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300573 int count, hlen;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300574
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300575 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300576 return;
577
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300578 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
579 hlen = L2CAP_EXT_HDR_SIZE;
580 else
581 hlen = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300582
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300583 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300584 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300585
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300586 BT_DBG("chan %p, control 0x%8.8x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300587
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300588 count = min_t(unsigned int, conn->mtu, hlen);
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +0300589
590 control |= __set_sframe(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300591
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300592 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +0300593 control |= __set_ctrl_final(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300594
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300595 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +0300596 control |= __set_ctrl_poll(chan);
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300597
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300598 skb = bt_skb_alloc(count, GFP_ATOMIC);
599 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300600 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300601
602 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300603 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300604 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300605
606 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300607
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300608 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300609 u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
610 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300611 }
612
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200613 skb->priority = HCI_PRIO_MAX;
614 l2cap_do_send(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300615}
616
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300617static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300618{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300619 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300620 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300621 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300622 } else
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300623 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300624
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300625 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300626
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300627 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300628}
629
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300630static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300631{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300632 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300633}
634
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300635static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200636{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300637 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200638
639 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100640 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
641 return;
642
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200643 if (l2cap_chan_check_security(chan) &&
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300644 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200645 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300646 req.scid = cpu_to_le16(chan->scid);
647 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200648
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300649 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300650 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200651
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300652 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
653 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200654 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200655 } else {
656 struct l2cap_info_req req;
657 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
658
659 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
660 conn->info_ident = l2cap_get_ident(conn);
661
Gustavo F. Padovan030013d2011-12-20 10:57:28 -0200662 schedule_delayed_work(&conn->info_timer,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200663 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
664
665 l2cap_send_cmd(conn, conn->info_ident,
666 L2CAP_INFO_REQ, sizeof(req), &req);
667 }
668}
669
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300670static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
671{
672 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300673 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300674 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
675
676 switch (mode) {
677 case L2CAP_MODE_ERTM:
678 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
679 case L2CAP_MODE_STREAMING:
680 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
681 default:
682 return 0x00;
683 }
684}
685
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300686static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300687{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300688 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300689 struct l2cap_disconn_req req;
690
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300691 if (!conn)
692 return;
693
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300694 sk = chan->sk;
695
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300696 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300697 __clear_retrans_timer(chan);
698 __clear_monitor_timer(chan);
699 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300700 }
701
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300702 req.dcid = cpu_to_le16(chan->dcid);
703 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300704 l2cap_send_cmd(conn, l2cap_get_ident(conn),
705 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300706
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300707 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300708 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300709}
710
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200712static void l2cap_conn_start(struct l2cap_conn *conn)
713{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200714 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200715
716 BT_DBG("conn %p", conn);
717
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200718 mutex_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200719
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200720 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300721 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300722
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200723 bh_lock_sock(sk);
724
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300725 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200726 bh_unlock_sock(sk);
727 continue;
728 }
729
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300730 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300731 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300732
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200733 if (!l2cap_chan_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300734 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300735 bh_unlock_sock(sk);
736 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200737 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300738
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300739 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
740 && test_bit(CONF_STATE2_DEVICE,
741 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300742 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300743 * so release the lock */
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300744 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300745 bh_unlock_sock(sk);
746 continue;
747 }
748
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300749 req.scid = cpu_to_le16(chan->scid);
750 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300751
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300752 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300753 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300754
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300755 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
756 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300757
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300758 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200759 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300760 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300761 rsp.scid = cpu_to_le16(chan->dcid);
762 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200763
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200764 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100765 if (bt_sk(sk)->defer_setup) {
766 struct sock *parent = bt_sk(sk)->parent;
767 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
768 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +0000769 if (parent)
770 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100771
772 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300773 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100774 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
775 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
776 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200777 } else {
778 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
779 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
780 }
781
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300782 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
783 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300784
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300785 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300786 rsp.result != L2CAP_CR_SUCCESS) {
787 bh_unlock_sock(sk);
788 continue;
789 }
790
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300791 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300792 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300793 l2cap_build_conf_req(chan, buf), buf);
794 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200795 }
796
797 bh_unlock_sock(sk);
798 }
799
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200800 mutex_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200801}
802
Ville Tervob62f3282011-02-10 22:38:50 -0300803/* Find socket with cid and source bdaddr.
804 * Returns closest match, locked.
805 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300806static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300807{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300808 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300809
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300810 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300811
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300812 list_for_each_entry(c, &chan_list, global_l) {
813 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300814
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300815 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300816 continue;
817
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300818 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300819 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300820 if (!bacmp(&bt_sk(sk)->src, src)) {
821 read_unlock(&chan_list_lock);
822 return c;
823 }
Ville Tervob62f3282011-02-10 22:38:50 -0300824
825 /* Closest match */
826 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300827 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300828 }
829 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300830
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300831 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300832
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300833 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300834}
835
836static void l2cap_le_conn_ready(struct l2cap_conn *conn)
837{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300838 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300839 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300840
841 BT_DBG("");
842
843 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300844 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300845 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300846 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300847 return;
848
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300849 parent = pchan->sk;
850
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300851 lock_sock(parent);
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300852
Ville Tervob62f3282011-02-10 22:38:50 -0300853 /* Check for backlog size */
854 if (sk_acceptq_is_full(parent)) {
855 BT_DBG("backlog full %d", parent->sk_ack_backlog);
856 goto clean;
857 }
858
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300859 chan = pchan->ops->new_connection(pchan->data);
860 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300861 goto clean;
862
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300863 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300864
Ville Tervob62f3282011-02-10 22:38:50 -0300865 hci_conn_hold(conn->hcon);
866
Ville Tervob62f3282011-02-10 22:38:50 -0300867 bacpy(&bt_sk(sk)->src, conn->src);
868 bacpy(&bt_sk(sk)->dst, conn->dst);
869
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300870 bt_accept_enqueue(parent, sk);
871
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200872 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300873
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300874 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300875
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300876 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300877 parent->sk_data_ready(parent, 0);
878
Ville Tervob62f3282011-02-10 22:38:50 -0300879clean:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300880 release_sock(parent);
Ville Tervob62f3282011-02-10 22:38:50 -0300881}
882
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +0200883static void l2cap_chan_ready(struct l2cap_chan *chan)
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300884{
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +0200885 struct sock *sk = chan->sk;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300886 struct sock *parent = bt_sk(sk)->parent;
887
888 BT_DBG("sk %p, parent %p", sk, parent);
889
890 chan->conf_state = 0;
891 __clear_chan_timer(chan);
892
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300893 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300894 sk->sk_state_change(sk);
895
896 if (parent)
897 parent->sk_data_ready(parent, 0);
898}
899
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200900static void l2cap_conn_ready(struct l2cap_conn *conn)
901{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300902 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200903
904 BT_DBG("conn %p", conn);
905
Ville Tervob62f3282011-02-10 22:38:50 -0300906 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
907 l2cap_le_conn_ready(conn);
908
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -0300909 if (conn->hcon->out && conn->hcon->type == LE_LINK)
910 smp_conn_security(conn, conn->hcon->pending_sec_level);
911
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200912 mutex_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200913
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200914 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300915 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300916
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200917 bh_lock_sock(sk);
918
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300919 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300920 if (smp_conn_security(conn, chan->sec_level))
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +0200921 l2cap_chan_ready(chan);
Ville Tervoacd7d372011-02-10 22:38:49 -0300922
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300923 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300924 __clear_chan_timer(chan);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300925 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200926 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300927
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300928 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300929 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200930
931 bh_unlock_sock(sk);
932 }
933
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200934 mutex_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200935}
936
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200937/* Notify sockets that we cannot guaranty reliability anymore */
938static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
939{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300940 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200941
942 BT_DBG("conn %p", conn);
943
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200944 mutex_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200945
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200946 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300947 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300948
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +0300949 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200950 sk->sk_err = err;
951 }
952
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200953 mutex_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200954}
955
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -0200956static void l2cap_info_timeout(struct work_struct *work)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200957{
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -0200958 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
Gustavo F. Padovan030013d2011-12-20 10:57:28 -0200959 info_timer.work);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200960
Marcel Holtmann984947d2009-02-06 23:35:19 +0100961 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100962 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100963
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200964 l2cap_conn_start(conn);
965}
966
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300967static void l2cap_conn_del(struct hci_conn *hcon, int err)
968{
969 struct l2cap_conn *conn = hcon->l2cap_data;
970 struct l2cap_chan *chan, *l;
971 struct sock *sk;
972
973 if (!conn)
974 return;
975
976 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
977
978 kfree_skb(conn->rx_skb);
979
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200980 mutex_lock(&conn->chan_lock);
981
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300982 /* Kill channels */
983 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
984 sk = chan->sk;
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300985 lock_sock(sk);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300986 l2cap_chan_del(chan, err);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300987 release_sock(sk);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300988 chan->ops->close(chan->data);
989 }
990
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200991 mutex_unlock(&conn->chan_lock);
992
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200993 hci_chan_del(conn->hchan);
994
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300995 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
Ulisses Furquim127074b2012-01-30 18:26:29 -0200996 cancel_delayed_work_sync(&conn->info_timer);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300997
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200998 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
Ulisses Furquim127074b2012-01-30 18:26:29 -0200999 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001000 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001001 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001002
1003 hcon->l2cap_data = NULL;
1004 kfree(conn);
1005}
1006
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001007static void security_timeout(struct work_struct *work)
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001008{
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001009 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1010 security_timer.work);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001011
1012 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1013}
1014
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1016{
Marcel Holtmann01394182006-07-03 10:02:46 +02001017 struct l2cap_conn *conn = hcon->l2cap_data;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001018 struct hci_chan *hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019
Marcel Holtmann01394182006-07-03 10:02:46 +02001020 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 return conn;
1022
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001023 hchan = hci_chan_create(hcon);
1024 if (!hchan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001027 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1028 if (!conn) {
1029 hci_chan_del(hchan);
1030 return NULL;
1031 }
1032
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 hcon->l2cap_data = conn;
1034 conn->hcon = hcon;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001035 conn->hchan = hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001037 BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
Marcel Holtmann01394182006-07-03 10:02:46 +02001038
Ville Tervoacd7d372011-02-10 22:38:49 -03001039 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1040 conn->mtu = hcon->hdev->le_mtu;
1041 else
1042 conn->mtu = hcon->hdev->acl_mtu;
1043
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 conn->src = &hcon->hdev->bdaddr;
1045 conn->dst = &hcon->dst;
1046
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001047 conn->feat_mask = 0;
1048
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 spin_lock_init(&conn->lock);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001050 mutex_init(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001051
1052 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001054 if (hcon->type == LE_LINK)
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001055 INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001056 else
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02001057 INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
Dave Young45054dc2009-10-18 20:28:30 +00001058
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001059 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01001060
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 return conn;
1062}
1063
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
1066/* Find socket with psm and source bdaddr.
1067 * Returns closest match.
1068 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001069static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001071 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001073 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001074
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001075 list_for_each_entry(c, &chan_list, global_l) {
1076 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001077
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001078 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 continue;
1080
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001081 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001083 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001084 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001085 return c;
1086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
1088 /* Closest match */
1089 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001090 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 }
1092 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001094 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001095
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001096 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097}
1098
Johan Hedbergcbe8fed2012-01-08 22:51:16 +02001099int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001101 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 bdaddr_t *src = &bt_sk(sk)->src;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 struct l2cap_conn *conn;
1104 struct hci_conn *hcon;
1105 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001106 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001107 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001109 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001110 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001112 hdev = hci_get_route(dst, src);
1113 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 return -EHOSTUNREACH;
1115
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001116 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001118 lock_sock(sk);
1119
1120 /* PSM must be odd and lsb of upper byte must be 0 */
1121 if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
1122 chan->chan_type != L2CAP_CHAN_RAW) {
1123 err = -EINVAL;
1124 goto done;
1125 }
1126
1127 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
1128 err = -EINVAL;
1129 goto done;
1130 }
1131
1132 switch (chan->mode) {
1133 case L2CAP_MODE_BASIC:
1134 break;
1135 case L2CAP_MODE_ERTM:
1136 case L2CAP_MODE_STREAMING:
1137 if (!disable_ertm)
1138 break;
1139 /* fall through */
1140 default:
1141 err = -ENOTSUPP;
1142 goto done;
1143 }
1144
1145 switch (sk->sk_state) {
1146 case BT_CONNECT:
1147 case BT_CONNECT2:
1148 case BT_CONFIG:
1149 /* Already connecting */
1150 err = 0;
1151 goto done;
1152
1153 case BT_CONNECTED:
1154 /* Already connected */
1155 err = -EISCONN;
1156 goto done;
1157
1158 case BT_OPEN:
1159 case BT_BOUND:
1160 /* Can connect */
1161 break;
1162
1163 default:
1164 err = -EBADFD;
1165 goto done;
1166 }
1167
1168 /* Set destination address and psm */
Gustavo F. Padovan9219b2a2012-01-02 20:08:04 -02001169 bacpy(&bt_sk(sk)->dst, dst);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001170 chan->psm = psm;
1171 chan->dcid = cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001173 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001174
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001175 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001176 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001177 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001178 else
1179 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001180 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001181
Ville Tervo30e76272011-02-22 16:10:53 -03001182 if (IS_ERR(hcon)) {
1183 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001185 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186
1187 conn = l2cap_conn_add(hcon, 0);
1188 if (!conn) {
1189 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001190 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 goto done;
1192 }
1193
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 /* Update source addr of the socket */
1195 bacpy(src, conn->src);
1196
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001197 l2cap_chan_add(conn, chan);
1198
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001199 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001200 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201
1202 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001203 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001204 __clear_chan_timer(chan);
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001205 if (l2cap_chan_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001206 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001207 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001208 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 }
1210
Ville Tervo30e76272011-02-22 16:10:53 -03001211 err = 0;
1212
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001214 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 hci_dev_put(hdev);
1216 return err;
1217}
1218
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001219int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001220{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001221 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001222 DECLARE_WAITQUEUE(wait, current);
1223 int err = 0;
1224 int timeo = HZ/5;
1225
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001226 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001227 set_current_state(TASK_INTERRUPTIBLE);
1228 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001229 if (!timeo)
1230 timeo = HZ/5;
1231
1232 if (signal_pending(current)) {
1233 err = sock_intr_errno(timeo);
1234 break;
1235 }
1236
1237 release_sock(sk);
1238 timeo = schedule_timeout(timeo);
1239 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001240 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001241
1242 err = sock_error(sk);
1243 if (err)
1244 break;
1245 }
1246 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001247 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001248 return err;
1249}
1250
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001251static void l2cap_monitor_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001252{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001253 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1254 monitor_timer.work);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001255 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001256
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001257 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001258
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001259 lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001260 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001261 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001262 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001263 return;
1264 }
1265
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001266 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001267 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001268
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001269 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001270 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001271}
1272
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001273static void l2cap_retrans_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001274{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001275 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1276 retrans_timer.work);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001277 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001278
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001279 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001280
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001281 lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001282 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001283 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001284
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001285 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001286
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001287 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001288 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001289}
1290
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001291static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001292{
1293 struct sk_buff *skb;
1294
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001295 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001296 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001297 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001298 break;
1299
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001300 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001301 kfree_skb(skb);
1302
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001303 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001304 }
1305
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001306 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001307 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001308}
1309
Szymon Janc67c9e842011-07-28 16:24:33 +02001310static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001311{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001312 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001313 u32 control;
1314 u16 fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001315
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001316 while ((skb = skb_dequeue(&chan->tx_q))) {
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001317 control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001318 control |= __set_txseq(chan, chan->next_tx_seq);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001319 __put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001320
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001321 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001322 fcs = crc16(0, (u8 *)skb->data,
1323 skb->len - L2CAP_FCS_SIZE);
1324 put_unaligned_le16(fcs,
1325 skb->data + skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001326 }
1327
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001328 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001329
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001330 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001331 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001332}
1333
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001334static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001335{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001336 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001337 u16 fcs;
1338 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001339
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001340 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001341 if (!skb)
1342 return;
1343
Szymon Jancd1726b62011-11-16 09:32:20 +01001344 while (bt_cb(skb)->tx_seq != tx_seq) {
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001345 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001346 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001347
Szymon Jancd1726b62011-11-16 09:32:20 +01001348 skb = skb_queue_next(&chan->tx_q, skb);
1349 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001350
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001351 if (chan->remote_max_tx &&
1352 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001353 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001354 return;
1355 }
1356
1357 tx_skb = skb_clone(skb, GFP_ATOMIC);
1358 bt_cb(skb)->retries++;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001359
1360 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001361 control &= __get_sar_mask(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001362
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001363 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001364 control |= __set_ctrl_final(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001365
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001366 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001367 control |= __set_txseq(chan, tx_seq);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001368
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001369 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001370
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001371 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001372 fcs = crc16(0, (u8 *)tx_skb->data,
1373 tx_skb->len - L2CAP_FCS_SIZE);
1374 put_unaligned_le16(fcs,
1375 tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001376 }
1377
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001378 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001379}
1380
Szymon Janc67c9e842011-07-28 16:24:33 +02001381static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001382{
1383 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001384 u16 fcs;
1385 u32 control;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001386 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001387
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001388 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001389 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001390
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001391 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001392
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001393 if (chan->remote_max_tx &&
1394 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001395 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001396 break;
1397 }
1398
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001399 tx_skb = skb_clone(skb, GFP_ATOMIC);
1400
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001401 bt_cb(skb)->retries++;
1402
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001403 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001404 control &= __get_sar_mask(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001405
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001406 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001407 control |= __set_ctrl_final(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001408
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001409 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001410 control |= __set_txseq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001411
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001412 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001413
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001414 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001415 fcs = crc16(0, (u8 *)skb->data,
1416 tx_skb->len - L2CAP_FCS_SIZE);
1417 put_unaligned_le16(fcs, skb->data +
1418 tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001419 }
1420
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001421 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001422
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001423 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001424
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001425 bt_cb(skb)->tx_seq = chan->next_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001426
1427 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001428
Szymon Janc8ed7a0a2012-02-07 15:43:01 +01001429 if (bt_cb(skb)->retries == 1) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001430 chan->unacked_frames++;
Szymon Janc930fa4a2012-02-07 15:43:02 +01001431
1432 if (!nsent++)
1433 __clear_ack_timer(chan);
Szymon Janc8ed7a0a2012-02-07 15:43:01 +01001434 }
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301435
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001436 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001437
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001438 if (skb_queue_is_last(&chan->tx_q, skb))
1439 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001440 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001441 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001442 }
1443
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001444 return nsent;
1445}
1446
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001447static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001448{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001449 int ret;
1450
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001451 if (!skb_queue_empty(&chan->tx_q))
1452 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001453
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001454 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001455 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001456 return ret;
1457}
1458
Szymon Jancb17e73b2012-01-11 10:59:47 +01001459static void __l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001460{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001461 u32 control = 0;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001462
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001463 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001464
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001465 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001466 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001467 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001468 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001469 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001470 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001471
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001472 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001473 return;
1474
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001475 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001476 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001477}
1478
Szymon Jancb17e73b2012-01-11 10:59:47 +01001479static void l2cap_send_ack(struct l2cap_chan *chan)
1480{
1481 __clear_ack_timer(chan);
1482 __l2cap_send_ack(chan);
1483}
1484
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001485static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001486{
1487 struct srej_list *tail;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001488 u32 control;
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001489
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001490 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001491 control |= __set_ctrl_final(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001492
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001493 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001494 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001495
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001496 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001497}
1498
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001499static 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 -07001500{
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001501 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001502 struct sk_buff **frag;
1503 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001505 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001506 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507
1508 sent += count;
1509 len -= count;
1510
1511 /* Continuation fragments (no L2CAP header) */
1512 frag = &skb_shinfo(skb)->frag_list;
1513 while (len) {
1514 count = min_t(unsigned int, conn->mtu, len);
1515
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001516 *frag = chan->ops->alloc_skb(chan, count,
1517 msg->msg_flags & MSG_DONTWAIT, &err);
1518
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001520 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001521 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1522 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001524 (*frag)->priority = skb->priority;
1525
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 sent += count;
1527 len -= count;
1528
1529 frag = &(*frag)->next;
1530 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531
1532 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001533}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001535static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
1536 struct msghdr *msg, size_t len,
1537 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001538{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001539 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001540 struct sk_buff *skb;
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001541 int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001542 struct l2cap_hdr *lh;
1543
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001544 BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001545
1546 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001547
1548 skb = chan->ops->alloc_skb(chan, count + hlen,
1549 msg->msg_flags & MSG_DONTWAIT, &err);
1550
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001551 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001552 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001553
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001554 skb->priority = priority;
1555
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001556 /* Create L2CAP header */
1557 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001558 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001559 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001560 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001561
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001562 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001563 if (unlikely(err < 0)) {
1564 kfree_skb(skb);
1565 return ERR_PTR(err);
1566 }
1567 return skb;
1568}
1569
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001570static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
1571 struct msghdr *msg, size_t len,
1572 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001573{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001574 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001575 struct sk_buff *skb;
1576 int err, count, hlen = L2CAP_HDR_SIZE;
1577 struct l2cap_hdr *lh;
1578
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001579 BT_DBG("chan %p len %d", chan, (int)len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001580
1581 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001582
1583 skb = chan->ops->alloc_skb(chan, count + hlen,
1584 msg->msg_flags & MSG_DONTWAIT, &err);
1585
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001586 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001587 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001588
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001589 skb->priority = priority;
1590
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001591 /* Create L2CAP header */
1592 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001593 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001594 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1595
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001596 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001597 if (unlikely(err < 0)) {
1598 kfree_skb(skb);
1599 return ERR_PTR(err);
1600 }
1601 return skb;
1602}
1603
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001604static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1605 struct msghdr *msg, size_t len,
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001606 u32 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001607{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001608 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001609 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001610 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001611 struct l2cap_hdr *lh;
1612
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001613 BT_DBG("chan %p len %d", chan, (int)len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001614
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001615 if (!conn)
1616 return ERR_PTR(-ENOTCONN);
1617
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001618 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1619 hlen = L2CAP_EXT_HDR_SIZE;
1620 else
1621 hlen = L2CAP_ENH_HDR_SIZE;
1622
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001623 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001624 hlen += L2CAP_SDULEN_SIZE;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001625
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001626 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001627 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001628
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001629 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001630
1631 skb = chan->ops->alloc_skb(chan, count + hlen,
1632 msg->msg_flags & MSG_DONTWAIT, &err);
1633
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001634 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001635 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001636
1637 /* Create L2CAP header */
1638 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001639 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001640 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001641
1642 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
1643
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001644 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001645 put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001646
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001647 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001648 if (unlikely(err < 0)) {
1649 kfree_skb(skb);
1650 return ERR_PTR(err);
1651 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001652
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001653 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001654 put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001655
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001656 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001657 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658}
1659
Szymon Janc67c9e842011-07-28 16:24:33 +02001660static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001661{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001662 struct sk_buff *skb;
1663 struct sk_buff_head sar_queue;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001664 u32 control;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001665 size_t size = 0;
1666
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001667 skb_queue_head_init(&sar_queue);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001668 control = __set_ctrl_sar(chan, L2CAP_SAR_START);
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001669 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001670 if (IS_ERR(skb))
1671 return PTR_ERR(skb);
1672
1673 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001674 len -= chan->remote_mps;
1675 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001676
1677 while (len > 0) {
1678 size_t buflen;
1679
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001680 if (len > chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001681 control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001682 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001683 } else {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001684 control = __set_ctrl_sar(chan, L2CAP_SAR_END);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001685 buflen = len;
1686 }
1687
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001688 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001689 if (IS_ERR(skb)) {
1690 skb_queue_purge(&sar_queue);
1691 return PTR_ERR(skb);
1692 }
1693
1694 __skb_queue_tail(&sar_queue, skb);
1695 len -= buflen;
1696 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001697 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001698 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1699 if (chan->tx_send_head == NULL)
1700 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001701
1702 return size;
1703}
1704
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001705int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
1706 u32 priority)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001707{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001708 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001709 u32 control;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001710 int err;
1711
1712 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001713 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001714 skb = l2cap_create_connless_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001715 if (IS_ERR(skb))
1716 return PTR_ERR(skb);
1717
1718 l2cap_do_send(chan, skb);
1719 return len;
1720 }
1721
1722 switch (chan->mode) {
1723 case L2CAP_MODE_BASIC:
1724 /* Check outgoing MTU */
1725 if (len > chan->omtu)
1726 return -EMSGSIZE;
1727
1728 /* Create a basic PDU */
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001729 skb = l2cap_create_basic_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001730 if (IS_ERR(skb))
1731 return PTR_ERR(skb);
1732
1733 l2cap_do_send(chan, skb);
1734 err = len;
1735 break;
1736
1737 case L2CAP_MODE_ERTM:
1738 case L2CAP_MODE_STREAMING:
1739 /* Entire SDU fits into one PDU */
1740 if (len <= chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001741 control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001742 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1743 0);
1744 if (IS_ERR(skb))
1745 return PTR_ERR(skb);
1746
1747 __skb_queue_tail(&chan->tx_q, skb);
1748
1749 if (chan->tx_send_head == NULL)
1750 chan->tx_send_head = skb;
1751
1752 } else {
1753 /* Segment SDU into multiples PDUs */
1754 err = l2cap_sar_segment_sdu(chan, msg, len);
1755 if (err < 0)
1756 return err;
1757 }
1758
1759 if (chan->mode == L2CAP_MODE_STREAMING) {
1760 l2cap_streaming_send(chan);
1761 err = len;
1762 break;
1763 }
1764
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001765 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1766 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001767 err = len;
1768 break;
1769 }
1770
1771 err = l2cap_ertm_send(chan);
1772 if (err >= 0)
1773 err = len;
1774
1775 break;
1776
1777 default:
1778 BT_DBG("bad state %1.1x", chan->mode);
1779 err = -EBADFD;
1780 }
1781
1782 return err;
1783}
1784
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785/* Copy frame to all raw sockets on that connection */
1786static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1787{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001789 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790
1791 BT_DBG("conn %p", conn);
1792
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001793 mutex_lock(&conn->chan_lock);
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001794
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001795 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001796 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001797 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798 continue;
1799
1800 /* Don't send frame to the socket it came from */
1801 if (skb->sk == sk)
1802 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001803 nskb = skb_clone(skb, GFP_ATOMIC);
1804 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 continue;
1806
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001807 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 kfree_skb(nskb);
1809 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001810
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001811 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812}
1813
1814/* ---- L2CAP signalling commands ---- */
1815static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1816 u8 code, u8 ident, u16 dlen, void *data)
1817{
1818 struct sk_buff *skb, **frag;
1819 struct l2cap_cmd_hdr *cmd;
1820 struct l2cap_hdr *lh;
1821 int len, count;
1822
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001823 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1824 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825
1826 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1827 count = min_t(unsigned int, conn->mtu, len);
1828
1829 skb = bt_skb_alloc(count, GFP_ATOMIC);
1830 if (!skb)
1831 return NULL;
1832
1833 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001834 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001835
1836 if (conn->hcon->type == LE_LINK)
1837 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1838 else
1839 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840
1841 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1842 cmd->code = code;
1843 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001844 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845
1846 if (dlen) {
1847 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1848 memcpy(skb_put(skb, count), data, count);
1849 data += count;
1850 }
1851
1852 len -= skb->len;
1853
1854 /* Continuation fragments (no L2CAP header) */
1855 frag = &skb_shinfo(skb)->frag_list;
1856 while (len) {
1857 count = min_t(unsigned int, conn->mtu, len);
1858
1859 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1860 if (!*frag)
1861 goto fail;
1862
1863 memcpy(skb_put(*frag, count), data, count);
1864
1865 len -= count;
1866 data += count;
1867
1868 frag = &(*frag)->next;
1869 }
1870
1871 return skb;
1872
1873fail:
1874 kfree_skb(skb);
1875 return NULL;
1876}
1877
1878static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1879{
1880 struct l2cap_conf_opt *opt = *ptr;
1881 int len;
1882
1883 len = L2CAP_CONF_OPT_SIZE + opt->len;
1884 *ptr += len;
1885
1886 *type = opt->type;
1887 *olen = opt->len;
1888
1889 switch (opt->len) {
1890 case 1:
1891 *val = *((u8 *) opt->val);
1892 break;
1893
1894 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001895 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 break;
1897
1898 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001899 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 break;
1901
1902 default:
1903 *val = (unsigned long) opt->val;
1904 break;
1905 }
1906
1907 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1908 return len;
1909}
1910
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1912{
1913 struct l2cap_conf_opt *opt = *ptr;
1914
1915 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1916
1917 opt->type = type;
1918 opt->len = len;
1919
1920 switch (len) {
1921 case 1:
1922 *((u8 *) opt->val) = val;
1923 break;
1924
1925 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001926 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927 break;
1928
1929 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001930 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 break;
1932
1933 default:
1934 memcpy(opt->val, (void *) val, len);
1935 break;
1936 }
1937
1938 *ptr += L2CAP_CONF_OPT_SIZE + len;
1939}
1940
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001941static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
1942{
1943 struct l2cap_conf_efs efs;
1944
Szymon Janc1ec918c2011-11-16 09:32:21 +01001945 switch (chan->mode) {
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001946 case L2CAP_MODE_ERTM:
1947 efs.id = chan->local_id;
1948 efs.stype = chan->local_stype;
1949 efs.msdu = cpu_to_le16(chan->local_msdu);
1950 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1951 efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
1952 efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
1953 break;
1954
1955 case L2CAP_MODE_STREAMING:
1956 efs.id = 1;
1957 efs.stype = L2CAP_SERV_BESTEFFORT;
1958 efs.msdu = cpu_to_le16(chan->local_msdu);
1959 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1960 efs.acc_lat = 0;
1961 efs.flush_to = 0;
1962 break;
1963
1964 default:
1965 return;
1966 }
1967
1968 l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
1969 (unsigned long) &efs);
1970}
1971
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001972static void l2cap_ack_timeout(struct work_struct *work)
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001973{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001974 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1975 ack_timer.work);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001976
Gustavo F. Padovan2fb9b3d2011-12-22 16:56:05 -02001977 BT_DBG("chan %p", chan);
1978
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001979 lock_sock(chan->sk);
Szymon Jancb17e73b2012-01-11 10:59:47 +01001980 __l2cap_send_ack(chan);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001981 release_sock(chan->sk);
Szymon Janc09bfb2e2012-01-11 10:59:49 +01001982
1983 l2cap_chan_put(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001984}
1985
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001986static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001987{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001988 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001989 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001990 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001991 chan->num_acked = 0;
1992 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001993
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001994 INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
1995 INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
1996 INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001997
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001998 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001999
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03002000 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002001}
2002
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002003static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2004{
2005 switch (mode) {
2006 case L2CAP_MODE_STREAMING:
2007 case L2CAP_MODE_ERTM:
2008 if (l2cap_mode_supported(mode, remote_feat_mask))
2009 return mode;
2010 /* fall through */
2011 default:
2012 return L2CAP_MODE_BASIC;
2013 }
2014}
2015
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002016static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
2017{
2018 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
2019}
2020
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002021static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2022{
2023 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2024}
2025
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002026static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
2027{
2028 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002029 __l2cap_ews_supported(chan)) {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002030 /* use extended control field */
2031 set_bit(FLAG_EXT_CTRL, &chan->flags);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002032 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2033 } else {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002034 chan->tx_win = min_t(u16, chan->tx_win,
2035 L2CAP_DEFAULT_TX_WINDOW);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002036 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2037 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002038}
2039
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002040static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002043 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044 void *ptr = req->data;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002045 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002047 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002049 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002050 goto done;
2051
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002052 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002053 case L2CAP_MODE_STREAMING:
2054 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002055 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002056 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002057
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002058 if (__l2cap_efs_supported(chan))
2059 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2060
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002061 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002062 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002063 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002064 break;
2065 }
2066
2067done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002068 if (chan->imtu != L2CAP_DEFAULT_MTU)
2069 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002070
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002071 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002072 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002073 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2074 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002075 break;
2076
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002077 rfc.mode = L2CAP_MODE_BASIC;
2078 rfc.txwin_size = 0;
2079 rfc.max_transmit = 0;
2080 rfc.retrans_timeout = 0;
2081 rfc.monitor_timeout = 0;
2082 rfc.max_pdu_size = 0;
2083
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002084 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2085 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002086 break;
2087
2088 case L2CAP_MODE_ERTM:
2089 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002090 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002091 rfc.retrans_timeout = 0;
2092 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002093
2094 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2095 L2CAP_EXT_HDR_SIZE -
2096 L2CAP_SDULEN_SIZE -
2097 L2CAP_FCS_SIZE);
2098 rfc.max_pdu_size = cpu_to_le16(size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002099
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002100 l2cap_txwin_setup(chan);
2101
2102 rfc.txwin_size = min_t(u16, chan->tx_win,
2103 L2CAP_DEFAULT_TX_WINDOW);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002104
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002105 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2106 (unsigned long) &rfc);
2107
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002108 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2109 l2cap_add_opt_efs(&ptr, chan);
2110
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002111 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002112 break;
2113
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002114 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002115 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002116 chan->fcs = L2CAP_FCS_NONE;
2117 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002118 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002119
2120 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2121 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2122 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002123 break;
2124
2125 case L2CAP_MODE_STREAMING:
2126 rfc.mode = L2CAP_MODE_STREAMING;
2127 rfc.txwin_size = 0;
2128 rfc.max_transmit = 0;
2129 rfc.retrans_timeout = 0;
2130 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002131
2132 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2133 L2CAP_EXT_HDR_SIZE -
2134 L2CAP_SDULEN_SIZE -
2135 L2CAP_FCS_SIZE);
2136 rfc.max_pdu_size = cpu_to_le16(size);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002137
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002138 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2139 (unsigned long) &rfc);
2140
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002141 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2142 l2cap_add_opt_efs(&ptr, chan);
2143
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002144 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002145 break;
2146
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002147 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002148 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002149 chan->fcs = L2CAP_FCS_NONE;
2150 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002151 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002152 break;
2153 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002155 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002156 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157
2158 return ptr - data;
2159}
2160
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002161static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002163 struct l2cap_conf_rsp *rsp = data;
2164 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002165 void *req = chan->conf_req;
2166 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002167 int type, hint, olen;
2168 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002169 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002170 struct l2cap_conf_efs efs;
2171 u8 remote_efs = 0;
Marcel Holtmann861d6882007-10-20 13:37:06 +02002172 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002173 u16 result = L2CAP_CONF_SUCCESS;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002174 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002176 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002177
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002178 while (len >= L2CAP_CONF_OPT_SIZE) {
2179 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002181 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002182 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002183
2184 switch (type) {
2185 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002186 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002187 break;
2188
2189 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002190 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002191 break;
2192
2193 case L2CAP_CONF_QOS:
2194 break;
2195
Marcel Holtmann6464f352007-10-20 13:39:51 +02002196 case L2CAP_CONF_RFC:
2197 if (olen == sizeof(rfc))
2198 memcpy(&rfc, (void *) val, olen);
2199 break;
2200
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002201 case L2CAP_CONF_FCS:
2202 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002203 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002204 break;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002205
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002206 case L2CAP_CONF_EFS:
2207 remote_efs = 1;
2208 if (olen == sizeof(efs))
2209 memcpy(&efs, (void *) val, olen);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002210 break;
2211
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002212 case L2CAP_CONF_EWS:
2213 if (!enable_hs)
2214 return -ECONNREFUSED;
2215
2216 set_bit(FLAG_EXT_CTRL, &chan->flags);
2217 set_bit(CONF_EWS_RECV, &chan->conf_state);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002218 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002219 chan->remote_tx_win = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002220 break;
2221
2222 default:
2223 if (hint)
2224 break;
2225
2226 result = L2CAP_CONF_UNKNOWN;
2227 *((u8 *) ptr++) = type;
2228 break;
2229 }
2230 }
2231
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002232 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002233 goto done;
2234
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002235 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002236 case L2CAP_MODE_STREAMING:
2237 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002238 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002239 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002240 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002241 break;
2242 }
2243
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002244 if (remote_efs) {
2245 if (__l2cap_efs_supported(chan))
2246 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2247 else
2248 return -ECONNREFUSED;
2249 }
2250
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002251 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002252 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002253
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002254 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002255 }
2256
2257done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002258 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002259 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002260 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002261
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002262 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002263 return -ECONNREFUSED;
2264
2265 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2266 sizeof(rfc), (unsigned long) &rfc);
2267 }
2268
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002269 if (result == L2CAP_CONF_SUCCESS) {
2270 /* Configure output options and let the other side know
2271 * which ones we don't like. */
2272
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002273 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2274 result = L2CAP_CONF_UNACCEPT;
2275 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002276 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002277 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002278 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002279 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002280
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002281 if (remote_efs) {
2282 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2283 efs.stype != L2CAP_SERV_NOTRAFIC &&
2284 efs.stype != chan->local_stype) {
2285
2286 result = L2CAP_CONF_UNACCEPT;
2287
2288 if (chan->num_conf_req >= 1)
2289 return -ECONNREFUSED;
2290
2291 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002292 sizeof(efs),
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002293 (unsigned long) &efs);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002294 } else {
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002295 /* Send PENDING Conf Rsp */
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002296 result = L2CAP_CONF_PENDING;
2297 set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002298 }
2299 }
2300
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002301 switch (rfc.mode) {
2302 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002303 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002304 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002305 break;
2306
2307 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002308 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2309 chan->remote_tx_win = rfc.txwin_size;
2310 else
2311 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2312
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002313 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002314
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002315 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2316 chan->conn->mtu -
2317 L2CAP_EXT_HDR_SIZE -
2318 L2CAP_SDULEN_SIZE -
2319 L2CAP_FCS_SIZE);
2320 rfc.max_pdu_size = cpu_to_le16(size);
2321 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002322
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002323 rfc.retrans_timeout =
2324 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2325 rfc.monitor_timeout =
2326 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002327
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002328 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002329
2330 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2331 sizeof(rfc), (unsigned long) &rfc);
2332
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002333 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2334 chan->remote_id = efs.id;
2335 chan->remote_stype = efs.stype;
2336 chan->remote_msdu = le16_to_cpu(efs.msdu);
2337 chan->remote_flush_to =
2338 le32_to_cpu(efs.flush_to);
2339 chan->remote_acc_lat =
2340 le32_to_cpu(efs.acc_lat);
2341 chan->remote_sdu_itime =
2342 le32_to_cpu(efs.sdu_itime);
2343 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2344 sizeof(efs), (unsigned long) &efs);
2345 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002346 break;
2347
2348 case L2CAP_MODE_STREAMING:
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002349 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2350 chan->conn->mtu -
2351 L2CAP_EXT_HDR_SIZE -
2352 L2CAP_SDULEN_SIZE -
2353 L2CAP_FCS_SIZE);
2354 rfc.max_pdu_size = cpu_to_le16(size);
2355 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002356
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002357 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002358
2359 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2360 sizeof(rfc), (unsigned long) &rfc);
2361
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002362 break;
2363
2364 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002365 result = L2CAP_CONF_UNACCEPT;
2366
2367 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002368 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002369 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002370
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002371 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002372 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002373 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002374 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002375 rsp->result = cpu_to_le16(result);
2376 rsp->flags = cpu_to_le16(0x0000);
2377
2378 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379}
2380
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002381static 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 -03002382{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002383 struct l2cap_conf_req *req = data;
2384 void *ptr = req->data;
2385 int type, olen;
2386 unsigned long val;
Mat Martineau36e999a2011-12-08 17:23:21 -08002387 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002388 struct l2cap_conf_efs efs;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002389
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002390 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002391
2392 while (len >= L2CAP_CONF_OPT_SIZE) {
2393 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2394
2395 switch (type) {
2396 case L2CAP_CONF_MTU:
2397 if (val < L2CAP_DEFAULT_MIN_MTU) {
2398 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002399 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002400 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002401 chan->imtu = val;
2402 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002403 break;
2404
2405 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002406 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002407 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002408 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002409 break;
2410
2411 case L2CAP_CONF_RFC:
2412 if (olen == sizeof(rfc))
2413 memcpy(&rfc, (void *)val, olen);
2414
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002415 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002416 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002417 return -ECONNREFUSED;
2418
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002419 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002420
2421 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2422 sizeof(rfc), (unsigned long) &rfc);
2423 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002424
2425 case L2CAP_CONF_EWS:
2426 chan->tx_win = min_t(u16, val,
2427 L2CAP_DEFAULT_EXT_WINDOW);
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002428 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2429 chan->tx_win);
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002430 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002431
2432 case L2CAP_CONF_EFS:
2433 if (olen == sizeof(efs))
2434 memcpy(&efs, (void *)val, olen);
2435
2436 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2437 efs.stype != L2CAP_SERV_NOTRAFIC &&
2438 efs.stype != chan->local_stype)
2439 return -ECONNREFUSED;
2440
2441 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2442 sizeof(efs), (unsigned long) &efs);
2443 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002444 }
2445 }
2446
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002447 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002448 return -ECONNREFUSED;
2449
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002450 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002451
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002452 if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002453 switch (rfc.mode) {
2454 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002455 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2456 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2457 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002458
2459 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2460 chan->local_msdu = le16_to_cpu(efs.msdu);
2461 chan->local_sdu_itime =
2462 le32_to_cpu(efs.sdu_itime);
2463 chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
2464 chan->local_flush_to =
2465 le32_to_cpu(efs.flush_to);
2466 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002467 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002468
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002469 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002470 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002471 }
2472 }
2473
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002474 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002475 req->flags = cpu_to_le16(0x0000);
2476
2477 return ptr - data;
2478}
2479
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002480static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481{
2482 struct l2cap_conf_rsp *rsp = data;
2483 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002485 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002487 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002488 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002489 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490
2491 return ptr - data;
2492}
2493
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002494void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002495{
2496 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002497 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002498 u8 buf[128];
2499
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002500 rsp.scid = cpu_to_le16(chan->dcid);
2501 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002502 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2503 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2504 l2cap_send_cmd(conn, chan->ident,
2505 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2506
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002507 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002508 return;
2509
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002510 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2511 l2cap_build_conf_req(chan, buf), buf);
2512 chan->num_conf_req++;
2513}
2514
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002515static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002516{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002517 int type, olen;
2518 unsigned long val;
2519 struct l2cap_conf_rfc rfc;
2520
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002521 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002522
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002523 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002524 return;
2525
2526 while (len >= L2CAP_CONF_OPT_SIZE) {
2527 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2528
2529 switch (type) {
2530 case L2CAP_CONF_RFC:
2531 if (olen == sizeof(rfc))
2532 memcpy(&rfc, (void *)val, olen);
2533 goto done;
2534 }
2535 }
2536
Mat Martineau36e999a2011-12-08 17:23:21 -08002537 /* Use sane default values in case a misbehaving remote device
2538 * did not send an RFC option.
2539 */
2540 rfc.mode = chan->mode;
2541 rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
2542 rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
2543 rfc.max_pdu_size = cpu_to_le16(chan->imtu);
2544
2545 BT_ERR("Expected RFC option was not found, using defaults");
2546
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002547done:
2548 switch (rfc.mode) {
2549 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002550 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2551 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2552 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002553 break;
2554 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002555 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002556 }
2557}
2558
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002559static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2560{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002561 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002562
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002563 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002564 return 0;
2565
2566 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2567 cmd->ident == conn->info_ident) {
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02002568 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002569
2570 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002571 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002572
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002573 l2cap_conn_start(conn);
2574 }
2575
2576 return 0;
2577}
2578
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2580{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2582 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002583 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002584 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002585 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586
2587 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002588 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589
2590 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2591
2592 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002593 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2594 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595 result = L2CAP_CR_BAD_PSM;
2596 goto sendresp;
2597 }
2598
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002599 parent = pchan->sk;
2600
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002601 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002602 lock_sock(parent);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002603
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002604 /* Check if the ACL is secure enough (if not SDP) */
2605 if (psm != cpu_to_le16(0x0001) &&
2606 !hci_conn_check_link_mode(conn->hcon)) {
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002607 conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002608 result = L2CAP_CR_SEC_BLOCK;
2609 goto response;
2610 }
2611
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612 result = L2CAP_CR_NO_MEM;
2613
2614 /* Check for backlog size */
2615 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002616 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617 goto response;
2618 }
2619
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002620 chan = pchan->ops->new_connection(pchan->data);
2621 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 goto response;
2623
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002624 sk = chan->sk;
2625
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002627 if (__l2cap_get_chan_by_dcid(conn, scid)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002629 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630 goto response;
2631 }
2632
2633 hci_conn_hold(conn->hcon);
2634
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635 bacpy(&bt_sk(sk)->src, conn->src);
2636 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002637 chan->psm = psm;
2638 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002640 bt_accept_enqueue(parent, sk);
2641
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02002642 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002643
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002644 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002646 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002648 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649
Marcel Holtmann984947d2009-02-06 23:35:19 +01002650 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02002651 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002652 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002653 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002654 result = L2CAP_CR_PEND;
2655 status = L2CAP_CS_AUTHOR_PEND;
2656 parent->sk_data_ready(parent, 0);
2657 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002658 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002659 result = L2CAP_CR_SUCCESS;
2660 status = L2CAP_CS_NO_INFO;
2661 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002662 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002663 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002664 result = L2CAP_CR_PEND;
2665 status = L2CAP_CS_AUTHEN_PEND;
2666 }
2667 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002668 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002669 result = L2CAP_CR_PEND;
2670 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671 }
2672
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673response:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002674 release_sock(parent);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002675 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676
2677sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002678 rsp.scid = cpu_to_le16(scid);
2679 rsp.dcid = cpu_to_le16(dcid);
2680 rsp.result = cpu_to_le16(result);
2681 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002683
2684 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2685 struct l2cap_info_req info;
2686 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2687
2688 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2689 conn->info_ident = l2cap_get_ident(conn);
2690
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02002691 schedule_delayed_work(&conn->info_timer,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002692 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2693
2694 l2cap_send_cmd(conn, conn->info_ident,
2695 L2CAP_INFO_REQ, sizeof(info), &info);
2696 }
2697
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002698 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002699 result == L2CAP_CR_SUCCESS) {
2700 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002701 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002702 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002703 l2cap_build_conf_req(chan, buf), buf);
2704 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002705 }
2706
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707 return 0;
2708}
2709
2710static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2711{
2712 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2713 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002714 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 struct sock *sk;
2716 u8 req[128];
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002717 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718
2719 scid = __le16_to_cpu(rsp->scid);
2720 dcid = __le16_to_cpu(rsp->dcid);
2721 result = __le16_to_cpu(rsp->result);
2722 status = __le16_to_cpu(rsp->status);
2723
Andrei Emeltchenko1b009c92012-02-21 12:54:54 +02002724 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
2725 dcid, scid, result, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002727 mutex_lock(&conn->chan_lock);
2728
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729 if (scid) {
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002730 chan = __l2cap_get_chan_by_scid(conn, scid);
2731 if (!chan) {
2732 err = -EFAULT;
2733 goto unlock;
2734 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735 } else {
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002736 chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
2737 if (!chan) {
2738 err = -EFAULT;
2739 goto unlock;
2740 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002741 }
2742
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002743 err = 0;
2744
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002745 sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002746 lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002747
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 switch (result) {
2749 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002750 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002751 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002752 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002753 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002754
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002755 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002756 break;
2757
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002759 l2cap_build_conf_req(chan, req), req);
2760 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 break;
2762
2763 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002764 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 break;
2766
2767 default:
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002768 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 break;
2770 }
2771
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002772 release_sock(sk);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002773
2774unlock:
2775 mutex_unlock(&conn->chan_lock);
2776
2777 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778}
2779
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002780static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002781{
2782 /* FCS is enabled only in ERTM or streaming mode, if one or both
2783 * sides request it.
2784 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002785 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002786 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002787 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002788 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002789}
2790
Al Viro88219a02007-07-29 00:17:25 -07002791static 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 -07002792{
2793 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2794 u16 dcid, flags;
2795 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002796 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002798 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799
2800 dcid = __le16_to_cpu(req->dcid);
2801 flags = __le16_to_cpu(req->flags);
2802
2803 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2804
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002805 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002806 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807 return -ENOENT;
2808
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002809 sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002810 lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002811
David S. Miller033b1142011-07-21 13:38:42 -07002812 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002813 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002814
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002815 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2816 rej.scid = cpu_to_le16(chan->scid);
2817 rej.dcid = cpu_to_le16(chan->dcid);
2818
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002819 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2820 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002821 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002822 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002823
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002824 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002825 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002826 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002827 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002828 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002829 L2CAP_CONF_REJECT, flags), rsp);
2830 goto unlock;
2831 }
2832
2833 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002834 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2835 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836
2837 if (flags & 0x0001) {
2838 /* Incomplete config. Send empty response. */
2839 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002840 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002841 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842 goto unlock;
2843 }
2844
2845 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002846 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002847 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002848 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002850 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002852 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002853 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002854
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002855 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002856 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002857
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002858 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002859 goto unlock;
2860
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002861 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002862 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002863
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002864 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002865
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002866 chan->next_tx_seq = 0;
2867 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002868 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002869 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002870 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002871
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02002872 l2cap_chan_ready(chan);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002873 goto unlock;
2874 }
2875
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002876 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002877 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002878 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002879 l2cap_build_conf_req(chan, buf), buf);
2880 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881 }
2882
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002883 /* Got Conf Rsp PENDING from remote side and asume we sent
2884 Conf Rsp PENDING in the code above */
2885 if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
2886 test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2887
2888 /* check compatibility */
2889
2890 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2891 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2892
2893 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002894 l2cap_build_conf_rsp(chan, rsp,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002895 L2CAP_CONF_SUCCESS, 0x0000), rsp);
2896 }
2897
Linus Torvalds1da177e2005-04-16 15:20:36 -07002898unlock:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002899 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002900 return 0;
2901}
2902
2903static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2904{
2905 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2906 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002907 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002909 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910
2911 scid = __le16_to_cpu(rsp->scid);
2912 flags = __le16_to_cpu(rsp->flags);
2913 result = __le16_to_cpu(rsp->result);
2914
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002915 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2916 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002918 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002919 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920 return 0;
2921
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002922 sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002923 lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002924
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925 switch (result) {
2926 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002927 l2cap_conf_rfc_get(chan, rsp->data, len);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002928 clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929 break;
2930
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002931 case L2CAP_CONF_PENDING:
2932 set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
2933
2934 if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2935 char buf[64];
2936
2937 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2938 buf, &result);
2939 if (len < 0) {
2940 l2cap_send_disconn_req(conn, chan, ECONNRESET);
2941 goto done;
2942 }
2943
2944 /* check compatibility */
2945
2946 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2947 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2948
2949 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002950 l2cap_build_conf_rsp(chan, buf,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002951 L2CAP_CONF_SUCCESS, 0x0000), buf);
2952 }
2953 goto done;
2954
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002956 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002957 char req[64];
2958
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002959 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002960 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002961 goto done;
2962 }
2963
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002964 /* throw out any old stored conf requests */
2965 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002966 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2967 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002968 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002969 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002970 goto done;
2971 }
2972
2973 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2974 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002975 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002976 if (result != L2CAP_CONF_SUCCESS)
2977 goto done;
2978 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979 }
2980
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002981 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002982 sk->sk_err = ECONNRESET;
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01002983 __set_chan_timer(chan,
2984 msecs_to_jiffies(L2CAP_DISC_REJ_TIMEOUT));
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002985 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986 goto done;
2987 }
2988
2989 if (flags & 0x01)
2990 goto done;
2991
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002992 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002994 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002995 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002996
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002997 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002998 chan->next_tx_seq = 0;
2999 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03003000 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003001 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003002 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003003
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02003004 l2cap_chan_ready(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005 }
3006
3007done:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003008 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009 return 0;
3010}
3011
3012static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3013{
3014 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3015 struct l2cap_disconn_rsp rsp;
3016 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003017 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018 struct sock *sk;
3019
3020 scid = __le16_to_cpu(req->scid);
3021 dcid = __le16_to_cpu(req->dcid);
3022
3023 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3024
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003025 mutex_lock(&conn->chan_lock);
3026
3027 chan = __l2cap_get_chan_by_scid(conn, dcid);
3028 if (!chan) {
3029 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030 return 0;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003031 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003033 sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003034 lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003035
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003036 rsp.dcid = cpu_to_le16(chan->scid);
3037 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3039
3040 sk->sk_shutdown = SHUTDOWN_MASK;
3041
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003042 l2cap_chan_del(chan, ECONNRESET);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003043 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003045 chan->ops->close(chan->data);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003046
3047 mutex_unlock(&conn->chan_lock);
3048
Linus Torvalds1da177e2005-04-16 15:20:36 -07003049 return 0;
3050}
3051
3052static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3053{
3054 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3055 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003056 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057 struct sock *sk;
3058
3059 scid = __le16_to_cpu(rsp->scid);
3060 dcid = __le16_to_cpu(rsp->dcid);
3061
3062 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3063
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003064 mutex_lock(&conn->chan_lock);
3065
3066 chan = __l2cap_get_chan_by_scid(conn, scid);
3067 if (!chan) {
3068 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069 return 0;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003070 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003072 sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003073 lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003074
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003075 l2cap_chan_del(chan, 0);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003076 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003078 chan->ops->close(chan->data);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003079
3080 mutex_unlock(&conn->chan_lock);
3081
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082 return 0;
3083}
3084
3085static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3086{
3087 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088 u16 type;
3089
3090 type = __le16_to_cpu(req->type);
3091
3092 BT_DBG("type 0x%4.4x", type);
3093
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003094 if (type == L2CAP_IT_FEAT_MASK) {
3095 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003096 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003097 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3098 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3099 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003100 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003101 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3102 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003103 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003104 feat_mask |= L2CAP_FEAT_EXT_FLOW
3105 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003106
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003107 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003108 l2cap_send_cmd(conn, cmd->ident,
3109 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003110 } else if (type == L2CAP_IT_FIXED_CHAN) {
3111 u8 buf[12];
3112 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
Mat Martineau50a147c2011-11-02 16:18:34 -07003113
3114 if (enable_hs)
3115 l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
3116 else
3117 l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
3118
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003119 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3120 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003121 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003122 l2cap_send_cmd(conn, cmd->ident,
3123 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003124 } else {
3125 struct l2cap_info_rsp rsp;
3126 rsp.type = cpu_to_le16(type);
3127 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3128 l2cap_send_cmd(conn, cmd->ident,
3129 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3130 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131
3132 return 0;
3133}
3134
3135static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3136{
3137 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3138 u16 type, result;
3139
3140 type = __le16_to_cpu(rsp->type);
3141 result = __le16_to_cpu(rsp->result);
3142
3143 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3144
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003145 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3146 if (cmd->ident != conn->info_ident ||
3147 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3148 return 0;
3149
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02003150 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003151
Ville Tervoadb08ed2010-08-04 09:43:33 +03003152 if (result != L2CAP_IR_SUCCESS) {
3153 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3154 conn->info_ident = 0;
3155
3156 l2cap_conn_start(conn);
3157
3158 return 0;
3159 }
3160
Marcel Holtmann984947d2009-02-06 23:35:19 +01003161 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003162 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003163
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003164 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003165 struct l2cap_info_req req;
3166 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3167
3168 conn->info_ident = l2cap_get_ident(conn);
3169
3170 l2cap_send_cmd(conn, conn->info_ident,
3171 L2CAP_INFO_REQ, sizeof(req), &req);
3172 } else {
3173 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3174 conn->info_ident = 0;
3175
3176 l2cap_conn_start(conn);
3177 }
3178 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003179 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003180 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003181
3182 l2cap_conn_start(conn);
3183 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003184
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185 return 0;
3186}
3187
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003188static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3189 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3190 void *data)
3191{
3192 struct l2cap_create_chan_req *req = data;
3193 struct l2cap_create_chan_rsp rsp;
3194 u16 psm, scid;
3195
3196 if (cmd_len != sizeof(*req))
3197 return -EPROTO;
3198
3199 if (!enable_hs)
3200 return -EINVAL;
3201
3202 psm = le16_to_cpu(req->psm);
3203 scid = le16_to_cpu(req->scid);
3204
3205 BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3206
3207 /* Placeholder: Always reject */
3208 rsp.dcid = 0;
3209 rsp.scid = cpu_to_le16(scid);
3210 rsp.result = L2CAP_CR_NO_MEM;
3211 rsp.status = L2CAP_CS_NO_INFO;
3212
3213 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3214 sizeof(rsp), &rsp);
3215
3216 return 0;
3217}
3218
3219static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3220 struct l2cap_cmd_hdr *cmd, void *data)
3221{
3222 BT_DBG("conn %p", conn);
3223
3224 return l2cap_connect_rsp(conn, cmd, data);
3225}
3226
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003227static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
3228 u16 icid, u16 result)
3229{
3230 struct l2cap_move_chan_rsp rsp;
3231
3232 BT_DBG("icid %d, result %d", icid, result);
3233
3234 rsp.icid = cpu_to_le16(icid);
3235 rsp.result = cpu_to_le16(result);
3236
3237 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
3238}
3239
3240static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
3241 struct l2cap_chan *chan, u16 icid, u16 result)
3242{
3243 struct l2cap_move_chan_cfm cfm;
3244 u8 ident;
3245
3246 BT_DBG("icid %d, result %d", icid, result);
3247
3248 ident = l2cap_get_ident(conn);
3249 if (chan)
3250 chan->ident = ident;
3251
3252 cfm.icid = cpu_to_le16(icid);
3253 cfm.result = cpu_to_le16(result);
3254
3255 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
3256}
3257
3258static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
3259 u16 icid)
3260{
3261 struct l2cap_move_chan_cfm_rsp rsp;
3262
3263 BT_DBG("icid %d", icid);
3264
3265 rsp.icid = cpu_to_le16(icid);
3266 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
3267}
3268
3269static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
3270 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3271{
3272 struct l2cap_move_chan_req *req = data;
3273 u16 icid = 0;
3274 u16 result = L2CAP_MR_NOT_ALLOWED;
3275
3276 if (cmd_len != sizeof(*req))
3277 return -EPROTO;
3278
3279 icid = le16_to_cpu(req->icid);
3280
3281 BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
3282
3283 if (!enable_hs)
3284 return -EINVAL;
3285
3286 /* Placeholder: Always refuse */
3287 l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
3288
3289 return 0;
3290}
3291
3292static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
3293 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3294{
3295 struct l2cap_move_chan_rsp *rsp = data;
3296 u16 icid, result;
3297
3298 if (cmd_len != sizeof(*rsp))
3299 return -EPROTO;
3300
3301 icid = le16_to_cpu(rsp->icid);
3302 result = le16_to_cpu(rsp->result);
3303
3304 BT_DBG("icid %d, result %d", icid, result);
3305
3306 /* Placeholder: Always unconfirmed */
3307 l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
3308
3309 return 0;
3310}
3311
3312static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
3313 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3314{
3315 struct l2cap_move_chan_cfm *cfm = data;
3316 u16 icid, result;
3317
3318 if (cmd_len != sizeof(*cfm))
3319 return -EPROTO;
3320
3321 icid = le16_to_cpu(cfm->icid);
3322 result = le16_to_cpu(cfm->result);
3323
3324 BT_DBG("icid %d, result %d", icid, result);
3325
3326 l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
3327
3328 return 0;
3329}
3330
3331static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
3332 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3333{
3334 struct l2cap_move_chan_cfm_rsp *rsp = data;
3335 u16 icid;
3336
3337 if (cmd_len != sizeof(*rsp))
3338 return -EPROTO;
3339
3340 icid = le16_to_cpu(rsp->icid);
3341
3342 BT_DBG("icid %d", icid);
3343
3344 return 0;
3345}
3346
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003347static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02003348 u16 to_multiplier)
3349{
3350 u16 max_latency;
3351
3352 if (min > max || min < 6 || max > 3200)
3353 return -EINVAL;
3354
3355 if (to_multiplier < 10 || to_multiplier > 3200)
3356 return -EINVAL;
3357
3358 if (max >= to_multiplier * 8)
3359 return -EINVAL;
3360
3361 max_latency = (to_multiplier * 8 / max) - 1;
3362 if (latency > 499 || latency > max_latency)
3363 return -EINVAL;
3364
3365 return 0;
3366}
3367
3368static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3369 struct l2cap_cmd_hdr *cmd, u8 *data)
3370{
3371 struct hci_conn *hcon = conn->hcon;
3372 struct l2cap_conn_param_update_req *req;
3373 struct l2cap_conn_param_update_rsp rsp;
3374 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003375 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02003376
3377 if (!(hcon->link_mode & HCI_LM_MASTER))
3378 return -EINVAL;
3379
3380 cmd_len = __le16_to_cpu(cmd->len);
3381 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3382 return -EPROTO;
3383
3384 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003385 min = __le16_to_cpu(req->min);
3386 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02003387 latency = __le16_to_cpu(req->latency);
3388 to_multiplier = __le16_to_cpu(req->to_multiplier);
3389
3390 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3391 min, max, latency, to_multiplier);
3392
3393 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003394
3395 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
3396 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02003397 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3398 else
3399 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3400
3401 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3402 sizeof(rsp), &rsp);
3403
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003404 if (!err)
3405 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
3406
Claudio Takahaside731152011-02-11 19:28:55 -02003407 return 0;
3408}
3409
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003410static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
3411 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
3412{
3413 int err = 0;
3414
3415 switch (cmd->code) {
3416 case L2CAP_COMMAND_REJ:
3417 l2cap_command_rej(conn, cmd, data);
3418 break;
3419
3420 case L2CAP_CONN_REQ:
3421 err = l2cap_connect_req(conn, cmd, data);
3422 break;
3423
3424 case L2CAP_CONN_RSP:
3425 err = l2cap_connect_rsp(conn, cmd, data);
3426 break;
3427
3428 case L2CAP_CONF_REQ:
3429 err = l2cap_config_req(conn, cmd, cmd_len, data);
3430 break;
3431
3432 case L2CAP_CONF_RSP:
3433 err = l2cap_config_rsp(conn, cmd, data);
3434 break;
3435
3436 case L2CAP_DISCONN_REQ:
3437 err = l2cap_disconnect_req(conn, cmd, data);
3438 break;
3439
3440 case L2CAP_DISCONN_RSP:
3441 err = l2cap_disconnect_rsp(conn, cmd, data);
3442 break;
3443
3444 case L2CAP_ECHO_REQ:
3445 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3446 break;
3447
3448 case L2CAP_ECHO_RSP:
3449 break;
3450
3451 case L2CAP_INFO_REQ:
3452 err = l2cap_information_req(conn, cmd, data);
3453 break;
3454
3455 case L2CAP_INFO_RSP:
3456 err = l2cap_information_rsp(conn, cmd, data);
3457 break;
3458
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003459 case L2CAP_CREATE_CHAN_REQ:
3460 err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3461 break;
3462
3463 case L2CAP_CREATE_CHAN_RSP:
3464 err = l2cap_create_channel_rsp(conn, cmd, data);
3465 break;
3466
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003467 case L2CAP_MOVE_CHAN_REQ:
3468 err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
3469 break;
3470
3471 case L2CAP_MOVE_CHAN_RSP:
3472 err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
3473 break;
3474
3475 case L2CAP_MOVE_CHAN_CFM:
3476 err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
3477 break;
3478
3479 case L2CAP_MOVE_CHAN_CFM_RSP:
3480 err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
3481 break;
3482
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003483 default:
3484 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3485 err = -EINVAL;
3486 break;
3487 }
3488
3489 return err;
3490}
3491
3492static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3493 struct l2cap_cmd_hdr *cmd, u8 *data)
3494{
3495 switch (cmd->code) {
3496 case L2CAP_COMMAND_REJ:
3497 return 0;
3498
3499 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003500 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003501
3502 case L2CAP_CONN_PARAM_UPDATE_RSP:
3503 return 0;
3504
3505 default:
3506 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3507 return -EINVAL;
3508 }
3509}
3510
3511static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3512 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513{
3514 u8 *data = skb->data;
3515 int len = skb->len;
3516 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003517 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003518
3519 l2cap_raw_recv(conn, skb);
3520
3521 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003522 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003523 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3524 data += L2CAP_CMD_HDR_SIZE;
3525 len -= L2CAP_CMD_HDR_SIZE;
3526
Al Viro88219a02007-07-29 00:17:25 -07003527 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003528
Al Viro88219a02007-07-29 00:17:25 -07003529 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 -07003530
Al Viro88219a02007-07-29 00:17:25 -07003531 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003532 BT_DBG("corrupted command");
3533 break;
3534 }
3535
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003536 if (conn->hcon->type == LE_LINK)
3537 err = l2cap_le_sig_cmd(conn, &cmd, data);
3538 else
3539 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003540
3541 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003542 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003543
3544 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003545
3546 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003547 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003548 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3549 }
3550
Al Viro88219a02007-07-29 00:17:25 -07003551 data += cmd_len;
3552 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003553 }
3554
3555 kfree_skb(skb);
3556}
3557
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003558static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003559{
3560 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003561 int hdr_size;
3562
3563 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3564 hdr_size = L2CAP_EXT_HDR_SIZE;
3565 else
3566 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003567
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003568 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003569 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003570 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3571 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3572
3573 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003574 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003575 }
3576 return 0;
3577}
3578
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003579static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003580{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003581 u32 control = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003582
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003583 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003584
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003585 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003586
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003587 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003588 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003589 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003590 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003591 }
3592
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003593 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003594 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003595
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003596 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003597
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003598 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003599 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003600 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003601 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003602 }
3603}
3604
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003605static 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 -03003606{
3607 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003608 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003609
3610 bt_cb(skb)->tx_seq = tx_seq;
3611 bt_cb(skb)->sar = sar;
3612
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003613 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003614
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003615 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003616
Szymon Janc039d9572011-11-16 09:32:19 +01003617 while (next_skb) {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003618 if (bt_cb(next_skb)->tx_seq == tx_seq)
3619 return -EINVAL;
3620
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003621 next_tx_seq_offset = __seq_offset(chan,
3622 bt_cb(next_skb)->tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003623
3624 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003625 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003626 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003627 }
3628
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003629 if (skb_queue_is_last(&chan->srej_q, next_skb))
Szymon Janc039d9572011-11-16 09:32:19 +01003630 next_skb = NULL;
3631 else
3632 next_skb = skb_queue_next(&chan->srej_q, next_skb);
3633 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003634
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003635 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003636
3637 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003638}
3639
Mat Martineau84084a32011-07-22 14:54:00 -07003640static void append_skb_frag(struct sk_buff *skb,
3641 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003642{
Mat Martineau84084a32011-07-22 14:54:00 -07003643 /* skb->len reflects data in skb as well as all fragments
3644 * skb->data_len reflects only data in fragments
3645 */
3646 if (!skb_has_frag_list(skb))
3647 skb_shinfo(skb)->frag_list = new_frag;
3648
3649 new_frag->next = NULL;
3650
3651 (*last_frag)->next = new_frag;
3652 *last_frag = new_frag;
3653
3654 skb->len += new_frag->len;
3655 skb->data_len += new_frag->len;
3656 skb->truesize += new_frag->truesize;
3657}
3658
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003659static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
Mat Martineau84084a32011-07-22 14:54:00 -07003660{
3661 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003662
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003663 switch (__get_ctrl_sar(chan, control)) {
3664 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003665 if (chan->sdu)
3666 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003667
Mat Martineau84084a32011-07-22 14:54:00 -07003668 err = chan->ops->recv(chan->data, skb);
3669 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003670
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003671 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003672 if (chan->sdu)
3673 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003674
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003675 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003676 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003677
Mat Martineau84084a32011-07-22 14:54:00 -07003678 if (chan->sdu_len > chan->imtu) {
3679 err = -EMSGSIZE;
3680 break;
3681 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003682
Mat Martineau84084a32011-07-22 14:54:00 -07003683 if (skb->len >= chan->sdu_len)
3684 break;
3685
3686 chan->sdu = skb;
3687 chan->sdu_last_frag = skb;
3688
3689 skb = NULL;
3690 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003691 break;
3692
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003693 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003694 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003695 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003696
Mat Martineau84084a32011-07-22 14:54:00 -07003697 append_skb_frag(chan->sdu, skb,
3698 &chan->sdu_last_frag);
3699 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003700
Mat Martineau84084a32011-07-22 14:54:00 -07003701 if (chan->sdu->len >= chan->sdu_len)
3702 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003703
Mat Martineau84084a32011-07-22 14:54:00 -07003704 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003705 break;
3706
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003707 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003708 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003709 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003710
Mat Martineau84084a32011-07-22 14:54:00 -07003711 append_skb_frag(chan->sdu, skb,
3712 &chan->sdu_last_frag);
3713 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003714
Mat Martineau84084a32011-07-22 14:54:00 -07003715 if (chan->sdu->len != chan->sdu_len)
3716 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003717
Mat Martineau84084a32011-07-22 14:54:00 -07003718 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003719
Mat Martineau84084a32011-07-22 14:54:00 -07003720 if (!err) {
3721 /* Reassembly complete */
3722 chan->sdu = NULL;
3723 chan->sdu_last_frag = NULL;
3724 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003725 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003726 break;
3727 }
3728
Mat Martineau84084a32011-07-22 14:54:00 -07003729 if (err) {
3730 kfree_skb(skb);
3731 kfree_skb(chan->sdu);
3732 chan->sdu = NULL;
3733 chan->sdu_last_frag = NULL;
3734 chan->sdu_len = 0;
3735 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003736
Mat Martineau84084a32011-07-22 14:54:00 -07003737 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003738}
3739
Mat Martineau26f880d2011-07-07 09:39:01 -07003740static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003741{
Mat Martineau26f880d2011-07-07 09:39:01 -07003742 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003743
Mat Martineau26f880d2011-07-07 09:39:01 -07003744 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3745
Szymon Janc77f918b2012-01-11 10:59:48 +01003746 __set_ack_timer(chan);
Mat Martineau26f880d2011-07-07 09:39:01 -07003747}
3748
3749static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3750{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003751 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003752
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003753 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003754 goto done;
3755
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003756 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003757 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003758 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003759 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003760 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003761
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003762 __clear_retrans_timer(chan);
3763 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003764
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003765 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003766
3767done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003768 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3769 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003770
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003771 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003772}
3773
Mat Martineaue3281402011-07-07 09:39:02 -07003774void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003775{
Mat Martineaue3281402011-07-07 09:39:02 -07003776 if (chan->mode == L2CAP_MODE_ERTM) {
3777 if (busy)
3778 l2cap_ertm_enter_local_busy(chan);
3779 else
3780 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003781 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003782}
3783
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003784static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003785{
3786 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003787 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003788
Mat Martineaue3281402011-07-07 09:39:02 -07003789 while ((skb = skb_peek(&chan->srej_q)) &&
3790 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3791 int err;
3792
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003793 if (bt_cb(skb)->tx_seq != tx_seq)
3794 break;
3795
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003796 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003797 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003798 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003799
3800 if (err < 0) {
3801 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3802 break;
3803 }
3804
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003805 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
3806 tx_seq = __next_seq(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003807 }
3808}
3809
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003810static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003811{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003812 struct srej_list *l, *tmp;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003813 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003814
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003815 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003816 if (l->tx_seq == tx_seq) {
3817 list_del(&l->list);
3818 kfree(l);
3819 return;
3820 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003821 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003822 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003823 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003824 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003825 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003826 }
3827}
3828
Szymon Jancaef89f22011-11-16 09:32:18 +01003829static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003830{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003831 struct srej_list *new;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003832 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003833
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003834 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003835 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003836 control |= __set_reqseq(chan, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003837 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003838
3839 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Szymon Jancaef89f22011-11-16 09:32:18 +01003840 if (!new)
3841 return -ENOMEM;
3842
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003843 new->tx_seq = chan->expected_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003844
3845 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
3846
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003847 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003848 }
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003849
3850 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Szymon Jancaef89f22011-11-16 09:32:18 +01003851
3852 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003853}
3854
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003855static 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 -03003856{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003857 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003858 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003859 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003860 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003861 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003862 int err = 0;
3863
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003864 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 -03003865 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003866
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003867 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003868 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003869 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003870 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003871 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003872 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003873 }
3874
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003875 chan->expected_ack_seq = req_seq;
3876 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003877
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003878 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003879
3880 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003881 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003882 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003883 goto drop;
3884 }
3885
Szymon Janc77f918b2012-01-11 10:59:48 +01003886 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3887 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
3888 l2cap_send_ack(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003889 goto drop;
Szymon Janc77f918b2012-01-11 10:59:48 +01003890 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003891
Mat Martineau02f1b642011-06-29 14:35:19 -07003892 if (tx_seq == chan->expected_tx_seq)
3893 goto expected;
3894
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003895 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003896 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003897
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003898 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003899 struct srej_list, list);
3900 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003901 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003902 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003903
3904 list_del(&first->list);
3905 kfree(first);
3906
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003907 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003908 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003909 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003910 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003911 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003912 }
3913 } else {
3914 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003915
3916 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003917 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003918 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003919
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003920 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003921 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003922 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003923 return 0;
3924 }
3925 }
Szymon Jancaef89f22011-11-16 09:32:18 +01003926
3927 err = l2cap_send_srejframe(chan, tx_seq);
3928 if (err < 0) {
3929 l2cap_send_disconn_req(chan->conn, chan, -err);
3930 return err;
3931 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003932 }
3933 } else {
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003934 expected_tx_seq_offset = __seq_offset(chan,
3935 chan->expected_tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003936
3937 /* duplicated tx_seq */
3938 if (tx_seq_offset < expected_tx_seq_offset)
3939 goto drop;
3940
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003941 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003942
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003943 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003944
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003945 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003946 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003947
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003948 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003949 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003950
Szymon Janc0ef3ef02012-01-11 10:59:46 +01003951 /* Set P-bit only if there are some I-frames to ack. */
3952 if (__clear_ack_timer(chan))
3953 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003954
Szymon Jancaef89f22011-11-16 09:32:18 +01003955 err = l2cap_send_srejframe(chan, tx_seq);
3956 if (err < 0) {
3957 l2cap_send_disconn_req(chan->conn, chan, -err);
3958 return err;
3959 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003960 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003961 return 0;
3962
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003963expected:
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003964 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003965
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003966 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003967 bt_cb(skb)->tx_seq = tx_seq;
3968 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003969 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003970 return 0;
3971 }
3972
Mat Martineau84084a32011-07-22 14:54:00 -07003973 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003974 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
3975
Mat Martineaue3281402011-07-07 09:39:02 -07003976 if (err < 0) {
3977 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3978 return err;
3979 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003980
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003981 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003982 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003983 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003984 }
3985
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003986
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003987 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3988 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003989 l2cap_send_ack(chan);
Gustavo F. Padovan4d611e42011-06-23 19:30:48 -03003990 else
3991 __set_ack_timer(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003992
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003993 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003994
3995drop:
3996 kfree_skb(skb);
3997 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003998}
3999
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004000static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004001{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004002 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004003 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004004
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004005 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004006 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004007
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004008 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004009 set_bit(CONN_SEND_FBIT, &chan->conn_state);
4010 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
4011 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004012 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004013 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004014
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004015 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004016 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004017 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004018 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004019 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004020
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004021 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004022 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004023
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004024 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004025 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004026
4027 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004028 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004029 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004030 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004031
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004032 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4033 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004034 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02004035 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004036 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004037 }
4038}
4039
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004040static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004041{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004042 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004043
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004044 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004045
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004046 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004047
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004048 chan->expected_ack_seq = tx_seq;
4049 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004050
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004051 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004052 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004053 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004054 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004055 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004056
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004057 if (test_bit(CONN_WAIT_F, &chan->conn_state))
4058 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004059 }
4060}
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004061static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004062{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004063 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004064
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004065 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004066
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004067 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004068
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004069 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004070 chan->expected_ack_seq = tx_seq;
4071 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004072
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004073 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004074 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004075
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004076 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004077
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004078 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004079 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004080 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004081 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004082 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004083 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004084 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004085 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
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. Padovane0727452010-05-01 16:15:38 -03004088 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004089 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004090 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004091 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004092 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004093 }
4094 }
4095}
4096
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004097static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004098{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004099 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004100
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004101 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004102
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004103 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004104 chan->expected_ack_seq = tx_seq;
4105 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004106
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004107 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004108 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004109
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004110 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004111 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004112 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004113 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004114 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004115 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004116
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004117 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004118 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004119 } else {
4120 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4121 l2cap_send_sframe(chan, rx_control);
4122 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004123}
4124
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004125static 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 -03004126{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004127 BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004128
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004129 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004130 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004131 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004132 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004133 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004134 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004135 }
4136
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004137 switch (__get_ctrl_super(chan, rx_control)) {
4138 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004139 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004140 break;
4141
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004142 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004143 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004144 break;
4145
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004146 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004147 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004148 break;
4149
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004150 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004151 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004152 break;
4153 }
4154
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004155 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004156 return 0;
4157}
4158
Szymon Janccad8f1d02012-01-23 10:06:05 +01004159static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004160{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004161 u32 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004162 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004163 int len, next_tx_seq_offset, req_seq_offset;
4164
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004165 control = __get_control(chan, skb->data);
4166 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004167 len = skb->len;
4168
4169 /*
4170 * We can just drop the corrupted I-frame here.
4171 * Receiver will miss it and start proper recovery
4172 * procedures and ask retransmission.
4173 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004174 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004175 goto drop;
4176
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004177 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004178 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004179
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004180 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004181 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004182
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004183 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004184 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004185 goto drop;
4186 }
4187
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004188 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004189
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004190 req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4191
4192 next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4193 chan->expected_ack_seq);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004194
4195 /* check for invalid req-seq */
4196 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004197 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004198 goto drop;
4199 }
4200
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004201 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004202 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004203 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004204 goto drop;
4205 }
4206
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004207 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004208 } else {
4209 if (len != 0) {
4210 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004211 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004212 goto drop;
4213 }
4214
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004215 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004216 }
4217
4218 return 0;
4219
4220drop:
4221 kfree_skb(skb);
4222 return 0;
4223}
4224
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4226{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004227 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07004228 struct sock *sk = NULL;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004229 u32 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004230 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004231 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004233 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004234 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004235 BT_DBG("unknown cid 0x%4.4x", cid);
4236 goto drop;
4237 }
4238
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004239 sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004240 lock_sock(sk);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004241
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004242 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004243
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004244 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245 goto drop;
4246
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004247 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004248 case L2CAP_MODE_BASIC:
4249 /* If socket recv buffers overflows we drop data here
4250 * which is *bad* because L2CAP has to be reliable.
4251 * But we don't have any other choice. L2CAP doesn't
4252 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004253
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004254 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004255 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004256
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004257 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004258 goto done;
4259 break;
4260
4261 case L2CAP_MODE_ERTM:
Andrei Emeltchenko5ef8cb92012-01-13 17:21:42 +02004262 l2cap_ertm_data_rcv(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004263
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004264 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004265
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004266 case L2CAP_MODE_STREAMING:
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004267 control = __get_control(chan, skb->data);
4268 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004269 len = skb->len;
4270
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004271 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004272 goto drop;
4273
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004274 if (__is_sar_start(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004275 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004276
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004277 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004278 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004279
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004280 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004281 goto drop;
4282
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004283 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004284
Mat Martineau84084a32011-07-22 14:54:00 -07004285 if (chan->expected_tx_seq != tx_seq) {
4286 /* Frame(s) missing - must discard partial SDU */
4287 kfree_skb(chan->sdu);
4288 chan->sdu = NULL;
4289 chan->sdu_last_frag = NULL;
4290 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004291
Mat Martineau84084a32011-07-22 14:54:00 -07004292 /* TODO: Notify userland of missing data */
4293 }
4294
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004295 chan->expected_tx_seq = __next_seq(chan, tx_seq);
Mat Martineau84084a32011-07-22 14:54:00 -07004296
4297 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
4298 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004299
4300 goto done;
4301
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004302 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004303 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004304 break;
4305 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306
4307drop:
4308 kfree_skb(skb);
4309
4310done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004311 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004312 release_sock(sk);
Marcel Holtmann01394182006-07-03 10:02:46 +02004313
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314 return 0;
4315}
4316
Al Viro8e036fc2007-07-29 00:16:36 -07004317static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004319 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004320 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004321
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004322 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
4323 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324 goto drop;
4325
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004326 sk = chan->sk;
4327
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004328 lock_sock(sk);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00004329
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330 BT_DBG("sk %p, len %d", sk, skb->len);
4331
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004332 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333 goto drop;
4334
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004335 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336 goto drop;
4337
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004338 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004339 goto done;
4340
4341drop:
4342 kfree_skb(skb);
4343
4344done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004345 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004346 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347 return 0;
4348}
4349
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004350static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
4351{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004352 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004353 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004354
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004355 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
4356 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004357 goto drop;
4358
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004359 sk = chan->sk;
4360
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004361 lock_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004362
4363 BT_DBG("sk %p, len %d", sk, skb->len);
4364
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004365 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004366 goto drop;
4367
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004368 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004369 goto drop;
4370
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004371 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004372 goto done;
4373
4374drop:
4375 kfree_skb(skb);
4376
4377done:
4378 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004379 release_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004380 return 0;
4381}
4382
Linus Torvalds1da177e2005-04-16 15:20:36 -07004383static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4384{
4385 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004386 u16 cid, len;
4387 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004388
4389 skb_pull(skb, L2CAP_HDR_SIZE);
4390 cid = __le16_to_cpu(lh->cid);
4391 len = __le16_to_cpu(lh->len);
4392
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004393 if (len != skb->len) {
4394 kfree_skb(skb);
4395 return;
4396 }
4397
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4399
4400 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004401 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004402 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403 l2cap_sig_channel(conn, skb);
4404 break;
4405
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004406 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004407 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004408 skb_pull(skb, 2);
4409 l2cap_conless_channel(conn, psm, skb);
4410 break;
4411
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004412 case L2CAP_CID_LE_DATA:
4413 l2cap_att_channel(conn, cid, skb);
4414 break;
4415
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004416 case L2CAP_CID_SMP:
4417 if (smp_sig_channel(conn, skb))
4418 l2cap_conn_del(conn->hcon, EACCES);
4419 break;
4420
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421 default:
4422 l2cap_data_channel(conn, cid, skb);
4423 break;
4424 }
4425}
4426
4427/* ---- L2CAP interface with lower layer (HCI) ---- */
4428
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004429int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430{
4431 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004432 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004433
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4435
4436 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004437 read_lock(&chan_list_lock);
4438 list_for_each_entry(c, &chan_list, global_l) {
4439 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004440
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004441 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442 continue;
4443
4444 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004445 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004446 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004447 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004448 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004449 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4450 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004451 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004452 lm2 |= HCI_LM_MASTER;
4453 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004455 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456
4457 return exact ? lm1 : lm2;
4458}
4459
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004460int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004461{
Marcel Holtmann01394182006-07-03 10:02:46 +02004462 struct l2cap_conn *conn;
4463
Linus Torvalds1da177e2005-04-16 15:20:36 -07004464 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4465
Linus Torvalds1da177e2005-04-16 15:20:36 -07004466 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467 conn = l2cap_conn_add(hcon, status);
4468 if (conn)
4469 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004470 } else
Joe Perchese1750722011-06-29 18:18:29 -07004471 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004472
4473 return 0;
4474}
4475
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004476int l2cap_disconn_ind(struct hci_conn *hcon)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004477{
4478 struct l2cap_conn *conn = hcon->l2cap_data;
4479
4480 BT_DBG("hcon %p", hcon);
4481
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004482 if (!conn)
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02004483 return HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01004484 return conn->disc_reason;
4485}
4486
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004487int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004488{
4489 BT_DBG("hcon %p reason %d", hcon, reason);
4490
Joe Perchese1750722011-06-29 18:18:29 -07004491 l2cap_conn_del(hcon, bt_to_errno(reason));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492 return 0;
4493}
4494
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004495static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004496{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004497 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004498 return;
4499
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004500 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004501 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004502 __clear_chan_timer(chan);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004503 __set_chan_timer(chan,
4504 msecs_to_jiffies(L2CAP_ENC_TIMEOUT));
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004505 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004506 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004507 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004508 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004509 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004510 }
4511}
4512
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004513int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004515 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004516 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004517
Marcel Holtmann01394182006-07-03 10:02:46 +02004518 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004519 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004520
Linus Torvalds1da177e2005-04-16 15:20:36 -07004521 BT_DBG("conn %p", conn);
4522
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004523 if (hcon->type == LE_LINK) {
4524 smp_distribute_keys(conn, 0);
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02004525 cancel_delayed_work(&conn->security_timer);
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004526 }
4527
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004528 mutex_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004529
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004530 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004531 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004532
Linus Torvalds1da177e2005-04-16 15:20:36 -07004533 bh_lock_sock(sk);
4534
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004535 BT_DBG("chan->scid %d", chan->scid);
4536
4537 if (chan->scid == L2CAP_CID_LE_DATA) {
4538 if (!status && encrypt) {
4539 chan->sec_level = hcon->sec_level;
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02004540 l2cap_chan_ready(chan);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004541 }
4542
4543 bh_unlock_sock(sk);
4544 continue;
4545 }
4546
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004547 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004548 bh_unlock_sock(sk);
4549 continue;
4550 }
4551
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004552 if (!status && (chan->state == BT_CONNECTED ||
4553 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004554 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004555 bh_unlock_sock(sk);
4556 continue;
4557 }
4558
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004559 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004560 if (!status) {
4561 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004562 req.scid = cpu_to_le16(chan->scid);
4563 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004564
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004565 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004566 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004567
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004568 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004569 L2CAP_CONN_REQ, sizeof(req), &req);
4570 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004571 __clear_chan_timer(chan);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004572 __set_chan_timer(chan,
4573 msecs_to_jiffies(L2CAP_DISC_TIMEOUT));
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004574 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004575 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004576 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004577 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004578
4579 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004580 if (bt_sk(sk)->defer_setup) {
4581 struct sock *parent = bt_sk(sk)->parent;
4582 res = L2CAP_CR_PEND;
4583 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004584 if (parent)
4585 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004586 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004587 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004588 res = L2CAP_CR_SUCCESS;
4589 stat = L2CAP_CS_NO_INFO;
4590 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004591 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004592 l2cap_state_change(chan, BT_DISCONN);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004593 __set_chan_timer(chan,
4594 msecs_to_jiffies(L2CAP_DISC_TIMEOUT));
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004595 res = L2CAP_CR_SEC_BLOCK;
4596 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004597 }
4598
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004599 rsp.scid = cpu_to_le16(chan->dcid);
4600 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004601 rsp.result = cpu_to_le16(res);
4602 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004603 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4604 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004605 }
4606
Linus Torvalds1da177e2005-04-16 15:20:36 -07004607 bh_unlock_sock(sk);
4608 }
4609
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004610 mutex_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004611
Linus Torvalds1da177e2005-04-16 15:20:36 -07004612 return 0;
4613}
4614
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004615int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004616{
4617 struct l2cap_conn *conn = hcon->l2cap_data;
4618
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004619 if (!conn)
4620 conn = l2cap_conn_add(hcon, 0);
4621
4622 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004623 goto drop;
4624
4625 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4626
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004627 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004628 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004629 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004630 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004631 int len;
4632
4633 if (conn->rx_len) {
4634 BT_ERR("Unexpected start frame (len %d)", skb->len);
4635 kfree_skb(conn->rx_skb);
4636 conn->rx_skb = NULL;
4637 conn->rx_len = 0;
4638 l2cap_conn_unreliable(conn, ECOMM);
4639 }
4640
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004641 /* Start fragment always begin with Basic L2CAP header */
4642 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004643 BT_ERR("Frame is too short (len %d)", skb->len);
4644 l2cap_conn_unreliable(conn, ECOMM);
4645 goto drop;
4646 }
4647
4648 hdr = (struct l2cap_hdr *) skb->data;
4649 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004650 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004651
4652 if (len == skb->len) {
4653 /* Complete frame received */
4654 l2cap_recv_frame(conn, skb);
4655 return 0;
4656 }
4657
4658 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4659
4660 if (skb->len > len) {
4661 BT_ERR("Frame is too long (len %d, expected len %d)",
4662 skb->len, len);
4663 l2cap_conn_unreliable(conn, ECOMM);
4664 goto drop;
4665 }
4666
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004667 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004668
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004669 if (chan && chan->sk) {
4670 struct sock *sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004671 lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004672
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004673 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004674 BT_ERR("Frame exceeding recv MTU (len %d, "
4675 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004676 chan->imtu);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004677 release_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004678 l2cap_conn_unreliable(conn, ECOMM);
4679 goto drop;
4680 }
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004681 release_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004682 }
4683
Linus Torvalds1da177e2005-04-16 15:20:36 -07004684 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004685 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4686 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004687 goto drop;
4688
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004689 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004690 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004691 conn->rx_len = len - skb->len;
4692 } else {
4693 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4694
4695 if (!conn->rx_len) {
4696 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4697 l2cap_conn_unreliable(conn, ECOMM);
4698 goto drop;
4699 }
4700
4701 if (skb->len > conn->rx_len) {
4702 BT_ERR("Fragment is too long (len %d, expected %d)",
4703 skb->len, conn->rx_len);
4704 kfree_skb(conn->rx_skb);
4705 conn->rx_skb = NULL;
4706 conn->rx_len = 0;
4707 l2cap_conn_unreliable(conn, ECOMM);
4708 goto drop;
4709 }
4710
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004711 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004712 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004713 conn->rx_len -= skb->len;
4714
4715 if (!conn->rx_len) {
4716 /* Complete frame received */
4717 l2cap_recv_frame(conn, conn->rx_skb);
4718 conn->rx_skb = NULL;
4719 }
4720 }
4721
4722drop:
4723 kfree_skb(skb);
4724 return 0;
4725}
4726
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004727static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004728{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004729 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004730
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02004731 read_lock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004732
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004733 list_for_each_entry(c, &chan_list, global_l) {
4734 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004735
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004736 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 +01004737 batostr(&bt_sk(sk)->src),
4738 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004739 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004740 c->scid, c->dcid, c->imtu, c->omtu,
4741 c->sec_level, c->mode);
Andrei Emeltchenko61e1b4b2012-01-19 11:19:50 +02004742 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004743
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02004744 read_unlock(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004745
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004746 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004747}
4748
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004749static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4750{
4751 return single_open(file, l2cap_debugfs_show, inode->i_private);
4752}
4753
4754static const struct file_operations l2cap_debugfs_fops = {
4755 .open = l2cap_debugfs_open,
4756 .read = seq_read,
4757 .llseek = seq_lseek,
4758 .release = single_release,
4759};
4760
4761static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004762
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004763int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004764{
4765 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004766
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004767 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004768 if (err < 0)
4769 return err;
4770
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004771 if (bt_debugfs) {
4772 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4773 bt_debugfs, NULL, &l2cap_debugfs_fops);
4774 if (!l2cap_debugfs)
4775 BT_ERR("Failed to create L2CAP debug file");
4776 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004777
Linus Torvalds1da177e2005-04-16 15:20:36 -07004778 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004779}
4780
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004781void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004782{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004783 debugfs_remove(l2cap_debugfs);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004784 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004785}
4786
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004787module_param(disable_ertm, bool, 0644);
4788MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");