blob: a78cdf7236dbce8668a8622e4c69c390544f20c0 [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.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006
7 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation;
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
16 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090017 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
18 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090022 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
23 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 SOFTWARE IS DISCLAIMED.
25*/
26
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020027/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30
31#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080032#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/errno.h>
34#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/sched.h>
36#include <linux/slab.h>
37#include <linux/poll.h>
38#include <linux/fcntl.h>
39#include <linux/init.h>
40#include <linux/interrupt.h>
41#include <linux/socket.h>
42#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080044#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010045#include <linux/debugfs.h>
46#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030047#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030048#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <net/sock.h>
50
51#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
Anderson Brigliab501d6a2011-06-07 18:46:31 -030057#include <net/bluetooth/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020059int disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020060
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070061static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Mat Martineau50a147c2011-11-02 16:18:34 -070062static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
Johannes Bergb5ad8b72011-06-01 08:54:45 +020064static LIST_HEAD(chan_list);
65static DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
Linus Torvalds1da177e2005-04-16 15:20:36 -070067static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
68 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030069static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
70 void *data);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -030071static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030072static void l2cap_send_disconn_req(struct l2cap_conn *conn,
73 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030075static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
76
Marcel Holtmann01394182006-07-03 10:02:46 +020077/* ---- L2CAP channels ---- */
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -030078
79static inline void chan_hold(struct l2cap_chan *c)
80{
81 atomic_inc(&c->refcnt);
82}
83
84static inline void chan_put(struct l2cap_chan *c)
85{
86 if (atomic_dec_and_test(&c->refcnt))
87 kfree(c);
88}
89
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030090static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020091{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030092 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030093
94 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030095 if (c->dcid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030096 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020097 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030098 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +020099}
100
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300101static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200102{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300103 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300104
105 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300106 if (c->scid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300107 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200108 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300109 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200110}
111
112/* Find channel with given SCID.
113 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300114static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200115{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300116 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300117
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -0200118 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300119 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300120 if (c)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300121 lock_sock(c->sk);
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -0200122 mutex_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300123 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200124}
125
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300126static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200127{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300128 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300129
130 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300131 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300132 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200133 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300134 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200135}
136
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300137static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200138{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300139 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300140
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -0200141 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300142 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300143 if (c)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300144 lock_sock(c->sk);
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -0200145 mutex_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300146 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200147}
148
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300149static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300150{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300151 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300152
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300153 list_for_each_entry(c, &chan_list, global_l) {
154 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Szymon Janc250938c2011-11-16 09:32:22 +0100155 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300156 }
Szymon Janc250938c2011-11-16 09:32:22 +0100157 return NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300158}
159
160int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
161{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300162 int err;
163
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300164 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300165
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300166 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300167 err = -EADDRINUSE;
168 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300169 }
170
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300171 if (psm) {
172 chan->psm = psm;
173 chan->sport = psm;
174 err = 0;
175 } else {
176 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300177
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300178 err = -EINVAL;
179 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300180 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300181 chan->psm = cpu_to_le16(p);
182 chan->sport = cpu_to_le16(p);
183 err = 0;
184 break;
185 }
186 }
187
188done:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300189 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300190 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300191}
192
193int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
194{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300195 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300196
197 chan->scid = scid;
198
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300199 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300200
201 return 0;
202}
203
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300204static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200205{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300206 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200207
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300208 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300209 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200210 return cid;
211 }
212
213 return 0;
214}
215
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300216static void l2cap_set_timer(struct l2cap_chan *chan, struct delayed_work *work, long timeout)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300217{
Andrei Emeltchenko457f4852011-10-31 16:17:21 +0200218 BT_DBG("chan %p state %d timeout %ld", chan, chan->state, timeout);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300219
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300220 cancel_delayed_work_sync(work);
221
222 schedule_delayed_work(work, timeout);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300223}
224
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300225static void l2cap_clear_timer(struct delayed_work *work)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300226{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300227 cancel_delayed_work_sync(work);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300228}
229
Gustavo F. Padovanbadaaa02011-11-23 20:11:46 -0200230static char *state_to_string(int state)
231{
232 switch(state) {
233 case BT_CONNECTED:
234 return "BT_CONNECTED";
235 case BT_OPEN:
236 return "BT_OPEN";
237 case BT_BOUND:
238 return "BT_BOUND";
239 case BT_LISTEN:
240 return "BT_LISTEN";
241 case BT_CONNECT:
242 return "BT_CONNECT";
243 case BT_CONNECT2:
244 return "BT_CONNECT2";
245 case BT_CONFIG:
246 return "BT_CONFIG";
247 case BT_DISCONN:
248 return "BT_DISCONN";
249 case BT_CLOSED:
250 return "BT_CLOSED";
251 }
252
253 return "invalid state";
254}
255
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300256static void l2cap_state_change(struct l2cap_chan *chan, int state)
257{
Gustavo F. Padovanbadaaa02011-11-23 20:11:46 -0200258 BT_DBG("%p %s -> %s", chan, state_to_string(chan->state),
259 state_to_string(state));
260
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300261 chan->state = state;
262 chan->ops->state_change(chan->data, state);
263}
264
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300265static void l2cap_chan_timeout(struct work_struct *work)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300266{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300267 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
268 chan_timer.work);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300269 struct sock *sk = chan->sk;
270 int reason;
271
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300272 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300273
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300274 lock_sock(sk);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300275
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300276 if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300277 reason = ECONNREFUSED;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300278 else if (chan->state == BT_CONNECT &&
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300279 chan->sec_level != BT_SECURITY_SDP)
280 reason = ECONNREFUSED;
281 else
282 reason = ETIMEDOUT;
283
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300284 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300285
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300286 release_sock(sk);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300287
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300288 chan->ops->close(chan->data);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300289 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300290}
291
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300292struct l2cap_chan *l2cap_chan_create(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200293{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300294 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200295
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300296 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
297 if (!chan)
298 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200299
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300300 chan->sk = sk;
301
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300302 write_lock_bh(&chan_list_lock);
303 list_add(&chan->global_l, &chan_list);
304 write_unlock_bh(&chan_list_lock);
305
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300306 INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300307
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300308 chan->state = BT_OPEN;
309
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300310 atomic_set(&chan->refcnt, 1);
311
Szymon Jancabc545b2011-11-03 16:05:44 +0100312 BT_DBG("sk %p chan %p", sk, chan);
313
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300314 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200315}
316
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300317void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300318{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300319 write_lock_bh(&chan_list_lock);
320 list_del(&chan->global_l);
321 write_unlock_bh(&chan_list_lock);
322
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300323 chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300324}
325
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300326static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200327{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300328 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300329 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200330
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +0200331 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +0100332
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300333 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200334
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300335 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
Ville Tervob62f3282011-02-10 22:38:50 -0300336 if (conn->hcon->type == LE_LINK) {
337 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300338 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300339 chan->scid = L2CAP_CID_LE_DATA;
340 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300341 } else {
342 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300343 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300344 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300345 }
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300346 } else if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200347 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300348 chan->scid = L2CAP_CID_CONN_LESS;
349 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300350 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200351 } else {
352 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300353 chan->scid = L2CAP_CID_SIGNALING;
354 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300355 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200356 }
357
Andrei Emeltchenko8f7975b2011-10-13 16:18:54 +0300358 chan->local_id = L2CAP_BESTEFFORT_ID;
359 chan->local_stype = L2CAP_SERV_BESTEFFORT;
360 chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
361 chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
362 chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
363 chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
364
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300365 chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300366
367 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200368}
369
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900370/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200371 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300372static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200373{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300374 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300375 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200376 struct sock *parent = bt_sk(sk)->parent;
377
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300378 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200379
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300380 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200381
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900382 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300383 /* Delete from channel list */
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -0200384 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300385 list_del(&chan->list);
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -0200386 mutex_unlock(&conn->chan_lock);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300387 chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300388
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300389 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200390 hci_conn_put(conn->hcon);
391 }
392
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300393 l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200394 sock_set_flag(sk, SOCK_ZAPPED);
395
396 if (err)
397 sk->sk_err = err;
398
399 if (parent) {
400 bt_accept_unlink(sk);
401 parent->sk_data_ready(parent, 0);
402 } else
403 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300404
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300405 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
406 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300407 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300408
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300409 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300410
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300411 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300412 struct srej_list *l, *tmp;
413
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300414 __clear_retrans_timer(chan);
415 __clear_monitor_timer(chan);
416 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300417
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300418 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300419
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300420 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300421 list_del(&l->list);
422 kfree(l);
423 }
424 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200425}
426
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300427static void l2cap_chan_cleanup_listen(struct sock *parent)
428{
429 struct sock *sk;
430
431 BT_DBG("parent %p", parent);
432
433 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300434 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300435 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300436 __clear_chan_timer(chan);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300437 lock_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300438 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300439 release_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300440 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300441 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300442}
443
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300444void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300445{
446 struct l2cap_conn *conn = chan->conn;
447 struct sock *sk = chan->sk;
448
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300449 BT_DBG("chan %p state %d socket %p", chan, chan->state, sk->sk_socket);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300450
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300451 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300452 case BT_LISTEN:
453 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300454
455 l2cap_state_change(chan, BT_CLOSED);
456 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300457 break;
458
459 case BT_CONNECTED:
460 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300461 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300462 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300463 __clear_chan_timer(chan);
464 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300465 l2cap_send_disconn_req(conn, chan, reason);
466 } else
467 l2cap_chan_del(chan, reason);
468 break;
469
470 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300471 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300472 conn->hcon->type == ACL_LINK) {
473 struct l2cap_conn_rsp rsp;
474 __u16 result;
475
476 if (bt_sk(sk)->defer_setup)
477 result = L2CAP_CR_SEC_BLOCK;
478 else
479 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300480 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300481
482 rsp.scid = cpu_to_le16(chan->dcid);
483 rsp.dcid = cpu_to_le16(chan->scid);
484 rsp.result = cpu_to_le16(result);
485 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
486 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
487 sizeof(rsp), &rsp);
488 }
489
490 l2cap_chan_del(chan, reason);
491 break;
492
493 case BT_CONNECT:
494 case BT_DISCONN:
495 l2cap_chan_del(chan, reason);
496 break;
497
498 default:
499 sock_set_flag(sk, SOCK_ZAPPED);
500 break;
501 }
502}
503
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300504static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530505{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300506 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300507 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530508 case BT_SECURITY_HIGH:
509 return HCI_AT_DEDICATED_BONDING_MITM;
510 case BT_SECURITY_MEDIUM:
511 return HCI_AT_DEDICATED_BONDING;
512 default:
513 return HCI_AT_NO_BONDING;
514 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300515 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300516 if (chan->sec_level == BT_SECURITY_LOW)
517 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530518
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300519 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530520 return HCI_AT_NO_BONDING_MITM;
521 else
522 return HCI_AT_NO_BONDING;
523 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300524 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530525 case BT_SECURITY_HIGH:
526 return HCI_AT_GENERAL_BONDING_MITM;
527 case BT_SECURITY_MEDIUM:
528 return HCI_AT_GENERAL_BONDING;
529 default:
530 return HCI_AT_NO_BONDING;
531 }
532 }
533}
534
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200535/* Service level security */
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200536int l2cap_chan_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200537{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300538 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100539 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200540
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300541 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100542
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300543 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200544}
545
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200546static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200547{
548 u8 id;
549
550 /* Get next available identificator.
551 * 1 - 128 are used by kernel.
552 * 129 - 199 are reserved.
553 * 200 - 254 are used by utilities like l2ping, etc.
554 */
555
556 spin_lock_bh(&conn->lock);
557
558 if (++conn->tx_ident > 128)
559 conn->tx_ident = 1;
560
561 id = conn->tx_ident;
562
563 spin_unlock_bh(&conn->lock);
564
565 return id;
566}
567
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300568static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200569{
570 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200571 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200572
573 BT_DBG("code 0x%2.2x", code);
574
575 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300576 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200577
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200578 if (lmp_no_flush_capable(conn->hcon->hdev))
579 flags = ACL_START_NO_FLUSH;
580 else
581 flags = ACL_START;
582
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700583 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +0200584 skb->priority = HCI_PRIO_MAX;
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700585
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200586 hci_send_acl(conn->hchan, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200587}
588
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200589static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
590{
591 struct hci_conn *hcon = chan->conn->hcon;
592 u16 flags;
593
594 BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
595 skb->priority);
596
597 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
598 lmp_no_flush_capable(hcon->hdev))
599 flags = ACL_START_NO_FLUSH;
600 else
601 flags = ACL_START;
602
603 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
604 hci_send_acl(chan->conn->hchan, skb, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605}
606
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300607static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300608{
609 struct sk_buff *skb;
610 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300611 struct l2cap_conn *conn = chan->conn;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300612 int count, hlen;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300613
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300614 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300615 return;
616
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300617 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
618 hlen = L2CAP_EXT_HDR_SIZE;
619 else
620 hlen = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300621
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300622 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300623 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300624
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300625 BT_DBG("chan %p, control 0x%8.8x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300626
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300627 count = min_t(unsigned int, conn->mtu, hlen);
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +0300628
629 control |= __set_sframe(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300630
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300631 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +0300632 control |= __set_ctrl_final(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300633
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300634 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +0300635 control |= __set_ctrl_poll(chan);
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300636
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300637 skb = bt_skb_alloc(count, GFP_ATOMIC);
638 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300639 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300640
641 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300642 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300643 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300644
645 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300646
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300647 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300648 u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
649 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300650 }
651
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200652 skb->priority = HCI_PRIO_MAX;
653 l2cap_do_send(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300654}
655
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300656static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300657{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300658 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300659 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300660 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300661 } else
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300662 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300663
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300664 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300665
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300666 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300667}
668
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300669static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300670{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300671 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300672}
673
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300674static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200675{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300676 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200677
678 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100679 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
680 return;
681
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200682 if (l2cap_chan_check_security(chan) &&
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300683 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200684 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300685 req.scid = cpu_to_le16(chan->scid);
686 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200687
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300688 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300689 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200690
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300691 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
692 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200693 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200694 } else {
695 struct l2cap_info_req req;
696 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
697
698 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
699 conn->info_ident = l2cap_get_ident(conn);
700
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -0200701 schedule_delayed_work(&conn->info_work,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200702 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
703
704 l2cap_send_cmd(conn, conn->info_ident,
705 L2CAP_INFO_REQ, sizeof(req), &req);
706 }
707}
708
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300709static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
710{
711 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300712 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300713 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
714
715 switch (mode) {
716 case L2CAP_MODE_ERTM:
717 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
718 case L2CAP_MODE_STREAMING:
719 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
720 default:
721 return 0x00;
722 }
723}
724
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300725static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300726{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300727 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300728 struct l2cap_disconn_req req;
729
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300730 if (!conn)
731 return;
732
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300733 sk = chan->sk;
734
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300735 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300736 __clear_retrans_timer(chan);
737 __clear_monitor_timer(chan);
738 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300739 }
740
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300741 req.dcid = cpu_to_le16(chan->dcid);
742 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300743 l2cap_send_cmd(conn, l2cap_get_ident(conn),
744 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300745
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300746 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300747 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300748}
749
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200751static void l2cap_conn_start(struct l2cap_conn *conn)
752{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300753 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200754
755 BT_DBG("conn %p", conn);
756
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -0200757 mutex_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200758
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300759 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300760 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300761
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200762 bh_lock_sock(sk);
763
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300764 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200765 bh_unlock_sock(sk);
766 continue;
767 }
768
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300769 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300770 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300771
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200772 if (!l2cap_chan_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300773 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300774 bh_unlock_sock(sk);
775 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200776 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300777
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300778 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
779 && test_bit(CONF_STATE2_DEVICE,
780 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300781 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300782 * so release the lock */
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -0200783 mutex_unlock(&conn->chan_lock);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300784 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -0200785 utex_lock(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300786 bh_unlock_sock(sk);
787 continue;
788 }
789
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300790 req.scid = cpu_to_le16(chan->scid);
791 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300792
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300793 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300794 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300795
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300796 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
797 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300798
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300799 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200800 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300801 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300802 rsp.scid = cpu_to_le16(chan->dcid);
803 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200804
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200805 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100806 if (bt_sk(sk)->defer_setup) {
807 struct sock *parent = bt_sk(sk)->parent;
808 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
809 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +0000810 if (parent)
811 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100812
813 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300814 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100815 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
816 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
817 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200818 } else {
819 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
820 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
821 }
822
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300823 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
824 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300825
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300826 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300827 rsp.result != L2CAP_CR_SUCCESS) {
828 bh_unlock_sock(sk);
829 continue;
830 }
831
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300832 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300833 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300834 l2cap_build_conf_req(chan, buf), buf);
835 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200836 }
837
838 bh_unlock_sock(sk);
839 }
840
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -0200841 mutex_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200842}
843
Ville Tervob62f3282011-02-10 22:38:50 -0300844/* Find socket with cid and source bdaddr.
845 * Returns closest match, locked.
846 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300847static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300848{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300849 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300850
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300851 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300852
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300853 list_for_each_entry(c, &chan_list, global_l) {
854 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300855
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300856 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300857 continue;
858
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300859 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300860 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300861 if (!bacmp(&bt_sk(sk)->src, src)) {
862 read_unlock(&chan_list_lock);
863 return c;
864 }
Ville Tervob62f3282011-02-10 22:38:50 -0300865
866 /* Closest match */
867 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300868 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300869 }
870 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300871
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300872 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300873
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300874 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300875}
876
877static void l2cap_le_conn_ready(struct l2cap_conn *conn)
878{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300879 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300880 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300881
882 BT_DBG("");
883
884 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300885 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300886 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300887 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300888 return;
889
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300890 parent = pchan->sk;
891
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300892 lock_sock(parent);
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300893
Ville Tervob62f3282011-02-10 22:38:50 -0300894 /* Check for backlog size */
895 if (sk_acceptq_is_full(parent)) {
896 BT_DBG("backlog full %d", parent->sk_ack_backlog);
897 goto clean;
898 }
899
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300900 chan = pchan->ops->new_connection(pchan->data);
901 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300902 goto clean;
903
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300904 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300905
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -0200906 mutex_lock(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300907
908 hci_conn_hold(conn->hcon);
909
Ville Tervob62f3282011-02-10 22:38:50 -0300910 bacpy(&bt_sk(sk)->src, conn->src);
911 bacpy(&bt_sk(sk)->dst, conn->dst);
912
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300913 bt_accept_enqueue(parent, sk);
914
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300915 __l2cap_chan_add(conn, chan);
916
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300917 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300918
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300919 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300920 parent->sk_data_ready(parent, 0);
921
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -0200922 mutex_unlock(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300923
924clean:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300925 release_sock(parent);
Ville Tervob62f3282011-02-10 22:38:50 -0300926}
927
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300928static void l2cap_chan_ready(struct sock *sk)
929{
930 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
931 struct sock *parent = bt_sk(sk)->parent;
932
933 BT_DBG("sk %p, parent %p", sk, parent);
934
935 chan->conf_state = 0;
936 __clear_chan_timer(chan);
937
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300938 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300939 sk->sk_state_change(sk);
940
941 if (parent)
942 parent->sk_data_ready(parent, 0);
943}
944
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200945static void l2cap_conn_ready(struct l2cap_conn *conn)
946{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300947 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200948
949 BT_DBG("conn %p", conn);
950
Ville Tervob62f3282011-02-10 22:38:50 -0300951 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
952 l2cap_le_conn_ready(conn);
953
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -0300954 if (conn->hcon->out && conn->hcon->type == LE_LINK)
955 smp_conn_security(conn, conn->hcon->pending_sec_level);
956
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -0200957 mutex_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200958
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300959 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300960 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300961
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200962 bh_lock_sock(sk);
963
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300964 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300965 if (smp_conn_security(conn, chan->sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300966 l2cap_chan_ready(sk);
Ville Tervoacd7d372011-02-10 22:38:49 -0300967
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300968 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300969 __clear_chan_timer(chan);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300970 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200971 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300972
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300973 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300974 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200975
976 bh_unlock_sock(sk);
977 }
978
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -0200979 mutex_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200980}
981
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200982/* Notify sockets that we cannot guaranty reliability anymore */
983static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
984{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300985 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200986
987 BT_DBG("conn %p", conn);
988
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -0200989 mutex_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200990
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300991 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300992 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300993
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +0300994 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200995 sk->sk_err = err;
996 }
997
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -0200998 mutex_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200999}
1000
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -02001001static void l2cap_info_timeout(struct work_struct *work)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001002{
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -02001003 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1004 info_work.work);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001005
Marcel Holtmann984947d2009-02-06 23:35:19 +01001006 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01001007 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01001008
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001009 l2cap_conn_start(conn);
1010}
1011
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001012static void l2cap_conn_del(struct hci_conn *hcon, int err)
1013{
1014 struct l2cap_conn *conn = hcon->l2cap_data;
1015 struct l2cap_chan *chan, *l;
1016 struct sock *sk;
1017
1018 if (!conn)
1019 return;
1020
1021 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
1022
1023 kfree_skb(conn->rx_skb);
1024
1025 /* Kill channels */
1026 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
1027 sk = chan->sk;
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001028 lock_sock(sk);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001029 l2cap_chan_del(chan, err);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001030 release_sock(sk);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001031 chan->ops->close(chan->data);
1032 }
1033
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001034 hci_chan_del(conn->hchan);
1035
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001036 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -02001037 cancel_delayed_work_sync(&conn->info_work);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001038
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001039 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) {
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001040 del_timer(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001041 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001042 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001043
1044 hcon->l2cap_data = NULL;
1045 kfree(conn);
1046}
1047
1048static void security_timeout(unsigned long arg)
1049{
1050 struct l2cap_conn *conn = (void *) arg;
1051
1052 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1053}
1054
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1056{
Marcel Holtmann01394182006-07-03 10:02:46 +02001057 struct l2cap_conn *conn = hcon->l2cap_data;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001058 struct hci_chan *hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059
Marcel Holtmann01394182006-07-03 10:02:46 +02001060 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 return conn;
1062
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001063 hchan = hci_chan_create(hcon);
1064 if (!hchan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001067 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1068 if (!conn) {
1069 hci_chan_del(hchan);
1070 return NULL;
1071 }
1072
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 hcon->l2cap_data = conn;
1074 conn->hcon = hcon;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001075 conn->hchan = hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001077 BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
Marcel Holtmann01394182006-07-03 10:02:46 +02001078
Ville Tervoacd7d372011-02-10 22:38:49 -03001079 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1080 conn->mtu = hcon->hdev->le_mtu;
1081 else
1082 conn->mtu = hcon->hdev->acl_mtu;
1083
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 conn->src = &hcon->hdev->bdaddr;
1085 conn->dst = &hcon->dst;
1086
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001087 conn->feat_mask = 0;
1088
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 spin_lock_init(&conn->lock);
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -02001090 mutex_init(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001091
1092 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001094 if (hcon->type == LE_LINK)
1095 setup_timer(&conn->security_timer, security_timeout,
1096 (unsigned long) conn);
1097 else
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -02001098 INIT_DELAYED_WORK(&conn->info_work, l2cap_info_timeout);
Dave Young45054dc2009-10-18 20:28:30 +00001099
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001100 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01001101
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 return conn;
1103}
1104
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001105static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106{
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -02001107 mutex_lock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001108 __l2cap_chan_add(conn, chan);
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -02001109 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110}
1111
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113
1114/* Find socket with psm and source bdaddr.
1115 * Returns closest match.
1116 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001117static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001119 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001121 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001122
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001123 list_for_each_entry(c, &chan_list, global_l) {
1124 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001125
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001126 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 continue;
1128
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001129 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001131 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001132 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001133 return c;
1134 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
1136 /* Closest match */
1137 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001138 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 }
1140 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001142 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001143
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001144 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145}
1146
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001147int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001149 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 bdaddr_t *src = &bt_sk(sk)->src;
1151 bdaddr_t *dst = &bt_sk(sk)->dst;
1152 struct l2cap_conn *conn;
1153 struct hci_conn *hcon;
1154 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001155 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001156 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001158 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001159 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001161 hdev = hci_get_route(dst, src);
1162 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 return -EHOSTUNREACH;
1164
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001165 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001167 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001168
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001169 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001170 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001171 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001172 else
1173 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001174 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001175
Ville Tervo30e76272011-02-22 16:10:53 -03001176 if (IS_ERR(hcon)) {
1177 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001179 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180
1181 conn = l2cap_conn_add(hcon, 0);
1182 if (!conn) {
1183 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001184 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 goto done;
1186 }
1187
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 /* Update source addr of the socket */
1189 bacpy(src, conn->src);
1190
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001191 l2cap_chan_add(conn, chan);
1192
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001193 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001194 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195
1196 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001197 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001198 __clear_chan_timer(chan);
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001199 if (l2cap_chan_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001200 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001201 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001202 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 }
1204
Ville Tervo30e76272011-02-22 16:10:53 -03001205 err = 0;
1206
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001208 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 hci_dev_put(hdev);
1210 return err;
1211}
1212
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001213int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001214{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001215 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001216 DECLARE_WAITQUEUE(wait, current);
1217 int err = 0;
1218 int timeo = HZ/5;
1219
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001220 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001221 set_current_state(TASK_INTERRUPTIBLE);
1222 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001223 if (!timeo)
1224 timeo = HZ/5;
1225
1226 if (signal_pending(current)) {
1227 err = sock_intr_errno(timeo);
1228 break;
1229 }
1230
1231 release_sock(sk);
1232 timeo = schedule_timeout(timeo);
1233 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001234 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001235
1236 err = sock_error(sk);
1237 if (err)
1238 break;
1239 }
1240 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001241 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001242 return err;
1243}
1244
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001245static void l2cap_monitor_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001246{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001247 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1248 monitor_timer.work);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001249 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001250
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001251 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001252
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001253 lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001254 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001255 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001256 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001257 return;
1258 }
1259
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001260 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001261 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001262
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001263 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001264 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001265}
1266
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001267static void l2cap_retrans_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001268{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001269 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1270 retrans_timer.work);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001271 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001272
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001273 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001274
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001275 lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001276 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001277 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001278
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001279 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001280
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001281 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001282 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001283}
1284
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001285static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001286{
1287 struct sk_buff *skb;
1288
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001289 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001290 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001291 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001292 break;
1293
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001294 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001295 kfree_skb(skb);
1296
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001297 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001298 }
1299
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001300 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001301 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001302}
1303
Szymon Janc67c9e842011-07-28 16:24:33 +02001304static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001305{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001306 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001307 u32 control;
1308 u16 fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001309
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001310 while ((skb = skb_dequeue(&chan->tx_q))) {
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001311 control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001312 control |= __set_txseq(chan, chan->next_tx_seq);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001313 __put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001314
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001315 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001316 fcs = crc16(0, (u8 *)skb->data,
1317 skb->len - L2CAP_FCS_SIZE);
1318 put_unaligned_le16(fcs,
1319 skb->data + skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001320 }
1321
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001322 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001323
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001324 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001325 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001326}
1327
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001328static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001329{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001330 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001331 u16 fcs;
1332 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001333
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001334 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001335 if (!skb)
1336 return;
1337
Szymon Jancd1726b62011-11-16 09:32:20 +01001338 while (bt_cb(skb)->tx_seq != tx_seq) {
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001339 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001340 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001341
Szymon Jancd1726b62011-11-16 09:32:20 +01001342 skb = skb_queue_next(&chan->tx_q, skb);
1343 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001344
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001345 if (chan->remote_max_tx &&
1346 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001347 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001348 return;
1349 }
1350
1351 tx_skb = skb_clone(skb, GFP_ATOMIC);
1352 bt_cb(skb)->retries++;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001353
1354 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001355 control &= __get_sar_mask(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001356
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001357 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001358 control |= __set_ctrl_final(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001359
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001360 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001361 control |= __set_txseq(chan, tx_seq);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001362
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001363 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001364
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001365 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001366 fcs = crc16(0, (u8 *)tx_skb->data,
1367 tx_skb->len - L2CAP_FCS_SIZE);
1368 put_unaligned_le16(fcs,
1369 tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001370 }
1371
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001372 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001373}
1374
Szymon Janc67c9e842011-07-28 16:24:33 +02001375static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001376{
1377 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001378 u16 fcs;
1379 u32 control;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001380 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001381
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001382 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001383 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001384
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001385 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001386
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001387 if (chan->remote_max_tx &&
1388 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001389 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001390 break;
1391 }
1392
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001393 tx_skb = skb_clone(skb, GFP_ATOMIC);
1394
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001395 bt_cb(skb)->retries++;
1396
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001397 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001398 control &= __get_sar_mask(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001399
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001400 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001401 control |= __set_ctrl_final(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001402
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001403 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001404 control |= __set_txseq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001405
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001406 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001407
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001408 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001409 fcs = crc16(0, (u8 *)skb->data,
1410 tx_skb->len - L2CAP_FCS_SIZE);
1411 put_unaligned_le16(fcs, skb->data +
1412 tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001413 }
1414
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001415 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001416
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001417 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001418
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001419 bt_cb(skb)->tx_seq = chan->next_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001420
1421 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001422
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301423 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001424 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301425
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001426 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001427
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001428 if (skb_queue_is_last(&chan->tx_q, skb))
1429 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001430 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001431 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001432
1433 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001434 }
1435
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001436 return nsent;
1437}
1438
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001439static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001440{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001441 int ret;
1442
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001443 if (!skb_queue_empty(&chan->tx_q))
1444 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001445
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001446 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001447 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001448 return ret;
1449}
1450
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001451static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001452{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001453 u32 control = 0;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001454
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001455 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001456
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001457 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001458 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001459 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001460 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001461 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001462 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001463
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001464 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001465 return;
1466
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001467 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001468 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001469}
1470
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001471static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001472{
1473 struct srej_list *tail;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001474 u32 control;
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001475
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001476 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001477 control |= __set_ctrl_final(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001478
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001479 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001480 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001481
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001482 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001483}
1484
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001485static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001487 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001488 struct sk_buff **frag;
1489 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001491 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001492 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493
1494 sent += count;
1495 len -= count;
1496
1497 /* Continuation fragments (no L2CAP header) */
1498 frag = &skb_shinfo(skb)->frag_list;
1499 while (len) {
1500 count = min_t(unsigned int, conn->mtu, len);
1501
1502 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1503 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001504 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001505 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1506 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001508 (*frag)->priority = skb->priority;
1509
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 sent += count;
1511 len -= count;
1512
1513 frag = &(*frag)->next;
1514 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515
1516 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001517}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001519static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
1520 struct msghdr *msg, size_t len,
1521 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001522{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001523 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001524 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001525 struct sk_buff *skb;
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001526 int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001527 struct l2cap_hdr *lh;
1528
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001529 BT_DBG("sk %p len %d priority %u", sk, (int)len, priority);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001530
1531 count = min_t(unsigned int, (conn->mtu - hlen), len);
1532 skb = bt_skb_send_alloc(sk, count + hlen,
1533 msg->msg_flags & MSG_DONTWAIT, &err);
1534 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001535 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001536
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001537 skb->priority = priority;
1538
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001539 /* Create L2CAP header */
1540 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001541 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001542 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001543 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001544
1545 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1546 if (unlikely(err < 0)) {
1547 kfree_skb(skb);
1548 return ERR_PTR(err);
1549 }
1550 return skb;
1551}
1552
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001553static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
1554 struct msghdr *msg, size_t len,
1555 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001556{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001557 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001558 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001559 struct sk_buff *skb;
1560 int err, count, hlen = L2CAP_HDR_SIZE;
1561 struct l2cap_hdr *lh;
1562
1563 BT_DBG("sk %p len %d", sk, (int)len);
1564
1565 count = min_t(unsigned int, (conn->mtu - hlen), len);
1566 skb = bt_skb_send_alloc(sk, count + hlen,
1567 msg->msg_flags & MSG_DONTWAIT, &err);
1568 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001569 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001570
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001571 skb->priority = priority;
1572
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001573 /* Create L2CAP header */
1574 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001575 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001576 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1577
1578 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1579 if (unlikely(err < 0)) {
1580 kfree_skb(skb);
1581 return ERR_PTR(err);
1582 }
1583 return skb;
1584}
1585
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001586static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1587 struct msghdr *msg, size_t len,
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001588 u32 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001589{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001590 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001591 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001592 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001593 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001594 struct l2cap_hdr *lh;
1595
1596 BT_DBG("sk %p len %d", sk, (int)len);
1597
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001598 if (!conn)
1599 return ERR_PTR(-ENOTCONN);
1600
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001601 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1602 hlen = L2CAP_EXT_HDR_SIZE;
1603 else
1604 hlen = L2CAP_ENH_HDR_SIZE;
1605
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001606 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001607 hlen += L2CAP_SDULEN_SIZE;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001608
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001609 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001610 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001611
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001612 count = min_t(unsigned int, (conn->mtu - hlen), len);
1613 skb = bt_skb_send_alloc(sk, count + hlen,
1614 msg->msg_flags & MSG_DONTWAIT, &err);
1615 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001616 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001617
1618 /* Create L2CAP header */
1619 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001620 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001621 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001622
1623 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
1624
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001625 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001626 put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001627
1628 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1629 if (unlikely(err < 0)) {
1630 kfree_skb(skb);
1631 return ERR_PTR(err);
1632 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001633
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001634 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001635 put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001636
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001637 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001638 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639}
1640
Szymon Janc67c9e842011-07-28 16:24:33 +02001641static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001642{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001643 struct sk_buff *skb;
1644 struct sk_buff_head sar_queue;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001645 u32 control;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001646 size_t size = 0;
1647
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001648 skb_queue_head_init(&sar_queue);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001649 control = __set_ctrl_sar(chan, L2CAP_SAR_START);
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001650 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001651 if (IS_ERR(skb))
1652 return PTR_ERR(skb);
1653
1654 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001655 len -= chan->remote_mps;
1656 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001657
1658 while (len > 0) {
1659 size_t buflen;
1660
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001661 if (len > chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001662 control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001663 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001664 } else {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001665 control = __set_ctrl_sar(chan, L2CAP_SAR_END);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001666 buflen = len;
1667 }
1668
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001669 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001670 if (IS_ERR(skb)) {
1671 skb_queue_purge(&sar_queue);
1672 return PTR_ERR(skb);
1673 }
1674
1675 __skb_queue_tail(&sar_queue, skb);
1676 len -= buflen;
1677 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001678 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001679 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1680 if (chan->tx_send_head == NULL)
1681 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001682
1683 return size;
1684}
1685
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001686int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
1687 u32 priority)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001688{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001689 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001690 u32 control;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001691 int err;
1692
1693 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001694 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001695 skb = l2cap_create_connless_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001696 if (IS_ERR(skb))
1697 return PTR_ERR(skb);
1698
1699 l2cap_do_send(chan, skb);
1700 return len;
1701 }
1702
1703 switch (chan->mode) {
1704 case L2CAP_MODE_BASIC:
1705 /* Check outgoing MTU */
1706 if (len > chan->omtu)
1707 return -EMSGSIZE;
1708
1709 /* Create a basic PDU */
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001710 skb = l2cap_create_basic_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001711 if (IS_ERR(skb))
1712 return PTR_ERR(skb);
1713
1714 l2cap_do_send(chan, skb);
1715 err = len;
1716 break;
1717
1718 case L2CAP_MODE_ERTM:
1719 case L2CAP_MODE_STREAMING:
1720 /* Entire SDU fits into one PDU */
1721 if (len <= chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001722 control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001723 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1724 0);
1725 if (IS_ERR(skb))
1726 return PTR_ERR(skb);
1727
1728 __skb_queue_tail(&chan->tx_q, skb);
1729
1730 if (chan->tx_send_head == NULL)
1731 chan->tx_send_head = skb;
1732
1733 } else {
1734 /* Segment SDU into multiples PDUs */
1735 err = l2cap_sar_segment_sdu(chan, msg, len);
1736 if (err < 0)
1737 return err;
1738 }
1739
1740 if (chan->mode == L2CAP_MODE_STREAMING) {
1741 l2cap_streaming_send(chan);
1742 err = len;
1743 break;
1744 }
1745
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001746 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1747 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001748 err = len;
1749 break;
1750 }
1751
1752 err = l2cap_ertm_send(chan);
1753 if (err >= 0)
1754 err = len;
1755
1756 break;
1757
1758 default:
1759 BT_DBG("bad state %1.1x", chan->mode);
1760 err = -EBADFD;
1761 }
1762
1763 return err;
1764}
1765
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766/* Copy frame to all raw sockets on that connection */
1767static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1768{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001770 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771
1772 BT_DBG("conn %p", conn);
1773
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -02001774 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001775 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001776 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001777 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 continue;
1779
1780 /* Don't send frame to the socket it came from */
1781 if (skb->sk == sk)
1782 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001783 nskb = skb_clone(skb, GFP_ATOMIC);
1784 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 continue;
1786
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001787 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 kfree_skb(nskb);
1789 }
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -02001790 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791}
1792
1793/* ---- L2CAP signalling commands ---- */
1794static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1795 u8 code, u8 ident, u16 dlen, void *data)
1796{
1797 struct sk_buff *skb, **frag;
1798 struct l2cap_cmd_hdr *cmd;
1799 struct l2cap_hdr *lh;
1800 int len, count;
1801
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001802 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1803 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804
1805 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1806 count = min_t(unsigned int, conn->mtu, len);
1807
1808 skb = bt_skb_alloc(count, GFP_ATOMIC);
1809 if (!skb)
1810 return NULL;
1811
1812 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001813 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001814
1815 if (conn->hcon->type == LE_LINK)
1816 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1817 else
1818 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819
1820 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1821 cmd->code = code;
1822 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001823 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824
1825 if (dlen) {
1826 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1827 memcpy(skb_put(skb, count), data, count);
1828 data += count;
1829 }
1830
1831 len -= skb->len;
1832
1833 /* Continuation fragments (no L2CAP header) */
1834 frag = &skb_shinfo(skb)->frag_list;
1835 while (len) {
1836 count = min_t(unsigned int, conn->mtu, len);
1837
1838 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1839 if (!*frag)
1840 goto fail;
1841
1842 memcpy(skb_put(*frag, count), data, count);
1843
1844 len -= count;
1845 data += count;
1846
1847 frag = &(*frag)->next;
1848 }
1849
1850 return skb;
1851
1852fail:
1853 kfree_skb(skb);
1854 return NULL;
1855}
1856
1857static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1858{
1859 struct l2cap_conf_opt *opt = *ptr;
1860 int len;
1861
1862 len = L2CAP_CONF_OPT_SIZE + opt->len;
1863 *ptr += len;
1864
1865 *type = opt->type;
1866 *olen = opt->len;
1867
1868 switch (opt->len) {
1869 case 1:
1870 *val = *((u8 *) opt->val);
1871 break;
1872
1873 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001874 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875 break;
1876
1877 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001878 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 break;
1880
1881 default:
1882 *val = (unsigned long) opt->val;
1883 break;
1884 }
1885
1886 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1887 return len;
1888}
1889
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1891{
1892 struct l2cap_conf_opt *opt = *ptr;
1893
1894 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1895
1896 opt->type = type;
1897 opt->len = len;
1898
1899 switch (len) {
1900 case 1:
1901 *((u8 *) opt->val) = val;
1902 break;
1903
1904 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001905 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906 break;
1907
1908 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001909 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910 break;
1911
1912 default:
1913 memcpy(opt->val, (void *) val, len);
1914 break;
1915 }
1916
1917 *ptr += L2CAP_CONF_OPT_SIZE + len;
1918}
1919
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001920static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
1921{
1922 struct l2cap_conf_efs efs;
1923
Szymon Janc1ec918c2011-11-16 09:32:21 +01001924 switch (chan->mode) {
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001925 case L2CAP_MODE_ERTM:
1926 efs.id = chan->local_id;
1927 efs.stype = chan->local_stype;
1928 efs.msdu = cpu_to_le16(chan->local_msdu);
1929 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1930 efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
1931 efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
1932 break;
1933
1934 case L2CAP_MODE_STREAMING:
1935 efs.id = 1;
1936 efs.stype = L2CAP_SERV_BESTEFFORT;
1937 efs.msdu = cpu_to_le16(chan->local_msdu);
1938 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1939 efs.acc_lat = 0;
1940 efs.flush_to = 0;
1941 break;
1942
1943 default:
1944 return;
1945 }
1946
1947 l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
1948 (unsigned long) &efs);
1949}
1950
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001951static void l2cap_ack_timeout(struct work_struct *work)
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001952{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001953 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1954 ack_timer.work);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001955
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001956 lock_sock(chan->sk);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001957 l2cap_send_ack(chan);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001958 release_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001959}
1960
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001961static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001962{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001963 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001964 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001965 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001966 chan->num_acked = 0;
1967 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001968
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001969 INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
1970 INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
1971 INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001972
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001973 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001974
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001975 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001976}
1977
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001978static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1979{
1980 switch (mode) {
1981 case L2CAP_MODE_STREAMING:
1982 case L2CAP_MODE_ERTM:
1983 if (l2cap_mode_supported(mode, remote_feat_mask))
1984 return mode;
1985 /* fall through */
1986 default:
1987 return L2CAP_MODE_BASIC;
1988 }
1989}
1990
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001991static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
1992{
1993 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
1994}
1995
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001996static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
1997{
1998 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
1999}
2000
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002001static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
2002{
2003 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002004 __l2cap_ews_supported(chan)) {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002005 /* use extended control field */
2006 set_bit(FLAG_EXT_CTRL, &chan->flags);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002007 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2008 } else {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002009 chan->tx_win = min_t(u16, chan->tx_win,
2010 L2CAP_DEFAULT_TX_WINDOW);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002011 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2012 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002013}
2014
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002015static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002018 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 void *ptr = req->data;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002020 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002022 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002024 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002025 goto done;
2026
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002027 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002028 case L2CAP_MODE_STREAMING:
2029 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002030 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002031 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002032
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002033 if (__l2cap_efs_supported(chan))
2034 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2035
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002036 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002037 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002038 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002039 break;
2040 }
2041
2042done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002043 if (chan->imtu != L2CAP_DEFAULT_MTU)
2044 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002045
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002046 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002047 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002048 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2049 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002050 break;
2051
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002052 rfc.mode = L2CAP_MODE_BASIC;
2053 rfc.txwin_size = 0;
2054 rfc.max_transmit = 0;
2055 rfc.retrans_timeout = 0;
2056 rfc.monitor_timeout = 0;
2057 rfc.max_pdu_size = 0;
2058
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002059 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2060 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002061 break;
2062
2063 case L2CAP_MODE_ERTM:
2064 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002065 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002066 rfc.retrans_timeout = 0;
2067 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002068
2069 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2070 L2CAP_EXT_HDR_SIZE -
2071 L2CAP_SDULEN_SIZE -
2072 L2CAP_FCS_SIZE);
2073 rfc.max_pdu_size = cpu_to_le16(size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002074
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002075 l2cap_txwin_setup(chan);
2076
2077 rfc.txwin_size = min_t(u16, chan->tx_win,
2078 L2CAP_DEFAULT_TX_WINDOW);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002079
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002080 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2081 (unsigned long) &rfc);
2082
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002083 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2084 l2cap_add_opt_efs(&ptr, chan);
2085
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002086 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002087 break;
2088
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002089 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002090 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002091 chan->fcs = L2CAP_FCS_NONE;
2092 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002093 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002094
2095 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2096 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2097 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002098 break;
2099
2100 case L2CAP_MODE_STREAMING:
2101 rfc.mode = L2CAP_MODE_STREAMING;
2102 rfc.txwin_size = 0;
2103 rfc.max_transmit = 0;
2104 rfc.retrans_timeout = 0;
2105 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002106
2107 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2108 L2CAP_EXT_HDR_SIZE -
2109 L2CAP_SDULEN_SIZE -
2110 L2CAP_FCS_SIZE);
2111 rfc.max_pdu_size = cpu_to_le16(size);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002112
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002113 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2114 (unsigned long) &rfc);
2115
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002116 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2117 l2cap_add_opt_efs(&ptr, chan);
2118
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002119 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002120 break;
2121
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002122 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002123 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002124 chan->fcs = L2CAP_FCS_NONE;
2125 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002126 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002127 break;
2128 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002130 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002131 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132
2133 return ptr - data;
2134}
2135
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002136static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002138 struct l2cap_conf_rsp *rsp = data;
2139 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002140 void *req = chan->conf_req;
2141 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002142 int type, hint, olen;
2143 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002144 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002145 struct l2cap_conf_efs efs;
2146 u8 remote_efs = 0;
Marcel Holtmann861d6882007-10-20 13:37:06 +02002147 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002148 u16 result = L2CAP_CONF_SUCCESS;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002149 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002151 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002152
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002153 while (len >= L2CAP_CONF_OPT_SIZE) {
2154 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002156 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002157 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002158
2159 switch (type) {
2160 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002161 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002162 break;
2163
2164 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002165 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002166 break;
2167
2168 case L2CAP_CONF_QOS:
2169 break;
2170
Marcel Holtmann6464f352007-10-20 13:39:51 +02002171 case L2CAP_CONF_RFC:
2172 if (olen == sizeof(rfc))
2173 memcpy(&rfc, (void *) val, olen);
2174 break;
2175
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002176 case L2CAP_CONF_FCS:
2177 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002178 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002179 break;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002180
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002181 case L2CAP_CONF_EFS:
2182 remote_efs = 1;
2183 if (olen == sizeof(efs))
2184 memcpy(&efs, (void *) val, olen);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002185 break;
2186
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002187 case L2CAP_CONF_EWS:
2188 if (!enable_hs)
2189 return -ECONNREFUSED;
2190
2191 set_bit(FLAG_EXT_CTRL, &chan->flags);
2192 set_bit(CONF_EWS_RECV, &chan->conf_state);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002193 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002194 chan->remote_tx_win = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002195 break;
2196
2197 default:
2198 if (hint)
2199 break;
2200
2201 result = L2CAP_CONF_UNKNOWN;
2202 *((u8 *) ptr++) = type;
2203 break;
2204 }
2205 }
2206
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002207 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002208 goto done;
2209
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002210 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002211 case L2CAP_MODE_STREAMING:
2212 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002213 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002214 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002215 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002216 break;
2217 }
2218
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002219 if (remote_efs) {
2220 if (__l2cap_efs_supported(chan))
2221 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2222 else
2223 return -ECONNREFUSED;
2224 }
2225
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002226 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002227 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002228
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002229 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002230 }
2231
2232done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002233 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002234 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002235 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002236
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002237 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002238 return -ECONNREFUSED;
2239
2240 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2241 sizeof(rfc), (unsigned long) &rfc);
2242 }
2243
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002244 if (result == L2CAP_CONF_SUCCESS) {
2245 /* Configure output options and let the other side know
2246 * which ones we don't like. */
2247
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002248 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2249 result = L2CAP_CONF_UNACCEPT;
2250 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002251 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002252 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002253 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002254 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002255
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002256 if (remote_efs) {
2257 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2258 efs.stype != L2CAP_SERV_NOTRAFIC &&
2259 efs.stype != chan->local_stype) {
2260
2261 result = L2CAP_CONF_UNACCEPT;
2262
2263 if (chan->num_conf_req >= 1)
2264 return -ECONNREFUSED;
2265
2266 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002267 sizeof(efs),
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002268 (unsigned long) &efs);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002269 } else {
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002270 /* Send PENDING Conf Rsp */
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002271 result = L2CAP_CONF_PENDING;
2272 set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002273 }
2274 }
2275
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002276 switch (rfc.mode) {
2277 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002278 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002279 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002280 break;
2281
2282 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002283 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2284 chan->remote_tx_win = rfc.txwin_size;
2285 else
2286 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2287
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002288 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002289
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002290 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2291 chan->conn->mtu -
2292 L2CAP_EXT_HDR_SIZE -
2293 L2CAP_SDULEN_SIZE -
2294 L2CAP_FCS_SIZE);
2295 rfc.max_pdu_size = cpu_to_le16(size);
2296 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002297
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002298 rfc.retrans_timeout =
2299 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2300 rfc.monitor_timeout =
2301 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002302
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002303 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002304
2305 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2306 sizeof(rfc), (unsigned long) &rfc);
2307
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002308 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2309 chan->remote_id = efs.id;
2310 chan->remote_stype = efs.stype;
2311 chan->remote_msdu = le16_to_cpu(efs.msdu);
2312 chan->remote_flush_to =
2313 le32_to_cpu(efs.flush_to);
2314 chan->remote_acc_lat =
2315 le32_to_cpu(efs.acc_lat);
2316 chan->remote_sdu_itime =
2317 le32_to_cpu(efs.sdu_itime);
2318 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2319 sizeof(efs), (unsigned long) &efs);
2320 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002321 break;
2322
2323 case L2CAP_MODE_STREAMING:
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002324 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2325 chan->conn->mtu -
2326 L2CAP_EXT_HDR_SIZE -
2327 L2CAP_SDULEN_SIZE -
2328 L2CAP_FCS_SIZE);
2329 rfc.max_pdu_size = cpu_to_le16(size);
2330 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002331
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002332 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002333
2334 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2335 sizeof(rfc), (unsigned long) &rfc);
2336
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002337 break;
2338
2339 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002340 result = L2CAP_CONF_UNACCEPT;
2341
2342 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002343 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002344 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002345
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002346 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002347 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002348 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002349 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002350 rsp->result = cpu_to_le16(result);
2351 rsp->flags = cpu_to_le16(0x0000);
2352
2353 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354}
2355
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002356static 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 -03002357{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002358 struct l2cap_conf_req *req = data;
2359 void *ptr = req->data;
2360 int type, olen;
2361 unsigned long val;
2362 struct l2cap_conf_rfc rfc;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002363 struct l2cap_conf_efs efs;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002364
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002365 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002366
2367 while (len >= L2CAP_CONF_OPT_SIZE) {
2368 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2369
2370 switch (type) {
2371 case L2CAP_CONF_MTU:
2372 if (val < L2CAP_DEFAULT_MIN_MTU) {
2373 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002374 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002375 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002376 chan->imtu = val;
2377 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002378 break;
2379
2380 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002381 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002382 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002383 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002384 break;
2385
2386 case L2CAP_CONF_RFC:
2387 if (olen == sizeof(rfc))
2388 memcpy(&rfc, (void *)val, olen);
2389
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002390 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002391 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002392 return -ECONNREFUSED;
2393
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002394 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002395
2396 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2397 sizeof(rfc), (unsigned long) &rfc);
2398 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002399
2400 case L2CAP_CONF_EWS:
2401 chan->tx_win = min_t(u16, val,
2402 L2CAP_DEFAULT_EXT_WINDOW);
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002403 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2404 chan->tx_win);
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002405 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002406
2407 case L2CAP_CONF_EFS:
2408 if (olen == sizeof(efs))
2409 memcpy(&efs, (void *)val, olen);
2410
2411 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2412 efs.stype != L2CAP_SERV_NOTRAFIC &&
2413 efs.stype != chan->local_stype)
2414 return -ECONNREFUSED;
2415
2416 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2417 sizeof(efs), (unsigned long) &efs);
2418 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002419 }
2420 }
2421
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002422 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002423 return -ECONNREFUSED;
2424
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002425 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002426
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002427 if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002428 switch (rfc.mode) {
2429 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002430 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2431 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2432 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002433
2434 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2435 chan->local_msdu = le16_to_cpu(efs.msdu);
2436 chan->local_sdu_itime =
2437 le32_to_cpu(efs.sdu_itime);
2438 chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
2439 chan->local_flush_to =
2440 le32_to_cpu(efs.flush_to);
2441 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002442 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002443
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002444 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002445 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002446 }
2447 }
2448
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002449 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002450 req->flags = cpu_to_le16(0x0000);
2451
2452 return ptr - data;
2453}
2454
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002455static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456{
2457 struct l2cap_conf_rsp *rsp = data;
2458 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002460 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002462 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002463 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002464 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465
2466 return ptr - data;
2467}
2468
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002469void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002470{
2471 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002472 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002473 u8 buf[128];
2474
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002475 rsp.scid = cpu_to_le16(chan->dcid);
2476 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002477 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2478 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2479 l2cap_send_cmd(conn, chan->ident,
2480 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2481
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002482 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002483 return;
2484
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002485 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2486 l2cap_build_conf_req(chan, buf), buf);
2487 chan->num_conf_req++;
2488}
2489
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002490static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002491{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002492 int type, olen;
2493 unsigned long val;
2494 struct l2cap_conf_rfc rfc;
2495
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002496 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002497
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002498 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002499 return;
2500
2501 while (len >= L2CAP_CONF_OPT_SIZE) {
2502 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2503
2504 switch (type) {
2505 case L2CAP_CONF_RFC:
2506 if (olen == sizeof(rfc))
2507 memcpy(&rfc, (void *)val, olen);
2508 goto done;
2509 }
2510 }
2511
2512done:
2513 switch (rfc.mode) {
2514 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002515 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2516 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2517 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002518 break;
2519 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002520 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002521 }
2522}
2523
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002524static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2525{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002526 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002527
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002528 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002529 return 0;
2530
2531 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2532 cmd->ident == conn->info_ident) {
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -02002533 cancel_delayed_work_sync(&conn->info_work);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002534
2535 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002536 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002537
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002538 l2cap_conn_start(conn);
2539 }
2540
2541 return 0;
2542}
2543
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2545{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2547 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002548 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002549 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002550 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551
2552 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002553 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554
2555 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2556
2557 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002558 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2559 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 result = L2CAP_CR_BAD_PSM;
2561 goto sendresp;
2562 }
2563
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002564 parent = pchan->sk;
2565
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002566 lock_sock(parent);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002567
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002568 /* Check if the ACL is secure enough (if not SDP) */
2569 if (psm != cpu_to_le16(0x0001) &&
2570 !hci_conn_check_link_mode(conn->hcon)) {
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002571 conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002572 result = L2CAP_CR_SEC_BLOCK;
2573 goto response;
2574 }
2575
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576 result = L2CAP_CR_NO_MEM;
2577
2578 /* Check for backlog size */
2579 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002580 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581 goto response;
2582 }
2583
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002584 chan = pchan->ops->new_connection(pchan->data);
2585 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 goto response;
2587
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002588 sk = chan->sk;
2589
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -02002590 mutex_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591
2592 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002593 if (__l2cap_get_chan_by_dcid(conn, scid)) {
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -02002594 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002596 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597 goto response;
2598 }
2599
2600 hci_conn_hold(conn->hcon);
2601
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602 bacpy(&bt_sk(sk)->src, conn->src);
2603 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002604 chan->psm = psm;
2605 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002607 bt_accept_enqueue(parent, sk);
2608
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002609 __l2cap_chan_add(conn, chan);
2610
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002611 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002613 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002615 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616
Marcel Holtmann984947d2009-02-06 23:35:19 +01002617 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02002618 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002619 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002620 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002621 result = L2CAP_CR_PEND;
2622 status = L2CAP_CS_AUTHOR_PEND;
2623 parent->sk_data_ready(parent, 0);
2624 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002625 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002626 result = L2CAP_CR_SUCCESS;
2627 status = L2CAP_CS_NO_INFO;
2628 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002629 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002630 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002631 result = L2CAP_CR_PEND;
2632 status = L2CAP_CS_AUTHEN_PEND;
2633 }
2634 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002635 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002636 result = L2CAP_CR_PEND;
2637 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638 }
2639
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -02002640 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641
2642response:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002643 release_sock(parent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644
2645sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002646 rsp.scid = cpu_to_le16(scid);
2647 rsp.dcid = cpu_to_le16(dcid);
2648 rsp.result = cpu_to_le16(result);
2649 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002651
2652 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2653 struct l2cap_info_req info;
2654 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2655
2656 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2657 conn->info_ident = l2cap_get_ident(conn);
2658
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -02002659 schedule_delayed_work(&conn->info_work,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002660 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2661
2662 l2cap_send_cmd(conn, conn->info_ident,
2663 L2CAP_INFO_REQ, sizeof(info), &info);
2664 }
2665
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002666 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002667 result == L2CAP_CR_SUCCESS) {
2668 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002669 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002670 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002671 l2cap_build_conf_req(chan, buf), buf);
2672 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002673 }
2674
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675 return 0;
2676}
2677
2678static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2679{
2680 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2681 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002682 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683 struct sock *sk;
2684 u8 req[128];
2685
2686 scid = __le16_to_cpu(rsp->scid);
2687 dcid = __le16_to_cpu(rsp->dcid);
2688 result = __le16_to_cpu(rsp->result);
2689 status = __le16_to_cpu(rsp->status);
2690
2691 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2692
2693 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002694 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002695 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002696 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002698 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002699 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002700 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701 }
2702
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002703 sk = chan->sk;
2704
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705 switch (result) {
2706 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002707 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002708 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002709 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002710 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002711
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002712 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002713 break;
2714
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002716 l2cap_build_conf_req(chan, req), req);
2717 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718 break;
2719
2720 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002721 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722 break;
2723
2724 default:
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002725 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 break;
2727 }
2728
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002729 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 return 0;
2731}
2732
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002733static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002734{
2735 /* FCS is enabled only in ERTM or streaming mode, if one or both
2736 * sides request it.
2737 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002738 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002739 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002740 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002741 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002742}
2743
Al Viro88219a02007-07-29 00:17:25 -07002744static 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 -07002745{
2746 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2747 u16 dcid, flags;
2748 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002749 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002751 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752
2753 dcid = __le16_to_cpu(req->dcid);
2754 flags = __le16_to_cpu(req->flags);
2755
2756 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2757
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002758 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002759 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760 return -ENOENT;
2761
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002762 sk = chan->sk;
2763
David S. Miller033b1142011-07-21 13:38:42 -07002764 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002765 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002766
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002767 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2768 rej.scid = cpu_to_le16(chan->scid);
2769 rej.dcid = cpu_to_le16(chan->dcid);
2770
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002771 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2772 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002773 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002774 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002775
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002776 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002777 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002778 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002779 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002780 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002781 L2CAP_CONF_REJECT, flags), rsp);
2782 goto unlock;
2783 }
2784
2785 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002786 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2787 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788
2789 if (flags & 0x0001) {
2790 /* Incomplete config. Send empty response. */
2791 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002792 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002793 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794 goto unlock;
2795 }
2796
2797 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002798 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002799 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002800 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002802 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002804 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002805 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002806
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002807 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002808 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002809
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002810 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002811 goto unlock;
2812
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002813 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002814 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002815
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002816 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002817
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002818 chan->next_tx_seq = 0;
2819 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002820 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002821 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002822 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002823
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002825 goto unlock;
2826 }
2827
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002828 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002829 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002831 l2cap_build_conf_req(chan, buf), buf);
2832 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833 }
2834
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002835 /* Got Conf Rsp PENDING from remote side and asume we sent
2836 Conf Rsp PENDING in the code above */
2837 if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
2838 test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2839
2840 /* check compatibility */
2841
2842 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2843 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2844
2845 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002846 l2cap_build_conf_rsp(chan, rsp,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002847 L2CAP_CONF_SUCCESS, 0x0000), rsp);
2848 }
2849
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850unlock:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002851 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852 return 0;
2853}
2854
2855static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2856{
2857 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2858 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002859 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002861 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862
2863 scid = __le16_to_cpu(rsp->scid);
2864 flags = __le16_to_cpu(rsp->flags);
2865 result = __le16_to_cpu(rsp->result);
2866
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002867 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2868 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002870 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002871 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002872 return 0;
2873
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002874 sk = chan->sk;
2875
Linus Torvalds1da177e2005-04-16 15:20:36 -07002876 switch (result) {
2877 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002878 l2cap_conf_rfc_get(chan, rsp->data, len);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002879 clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002880 break;
2881
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002882 case L2CAP_CONF_PENDING:
2883 set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
2884
2885 if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2886 char buf[64];
2887
2888 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2889 buf, &result);
2890 if (len < 0) {
2891 l2cap_send_disconn_req(conn, chan, ECONNRESET);
2892 goto done;
2893 }
2894
2895 /* check compatibility */
2896
2897 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2898 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2899
2900 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002901 l2cap_build_conf_rsp(chan, buf,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002902 L2CAP_CONF_SUCCESS, 0x0000), buf);
2903 }
2904 goto done;
2905
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002907 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002908 char req[64];
2909
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002910 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002911 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002912 goto done;
2913 }
2914
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002915 /* throw out any old stored conf requests */
2916 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002917 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2918 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002919 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002920 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002921 goto done;
2922 }
2923
2924 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2925 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002926 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002927 if (result != L2CAP_CONF_SUCCESS)
2928 goto done;
2929 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930 }
2931
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002932 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002933 sk->sk_err = ECONNRESET;
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02002934 __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002935 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936 goto done;
2937 }
2938
2939 if (flags & 0x01)
2940 goto done;
2941
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002942 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002943
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002944 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002945 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002946
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002947 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002948 chan->next_tx_seq = 0;
2949 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002950 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002951 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002952 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002953
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954 l2cap_chan_ready(sk);
2955 }
2956
2957done:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002958 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959 return 0;
2960}
2961
2962static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2963{
2964 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2965 struct l2cap_disconn_rsp rsp;
2966 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002967 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968 struct sock *sk;
2969
2970 scid = __le16_to_cpu(req->scid);
2971 dcid = __le16_to_cpu(req->dcid);
2972
2973 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2974
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002975 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002976 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977 return 0;
2978
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002979 sk = chan->sk;
2980
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002981 rsp.dcid = cpu_to_le16(chan->scid);
2982 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2984
2985 sk->sk_shutdown = SHUTDOWN_MASK;
2986
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002987 l2cap_chan_del(chan, ECONNRESET);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002988 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002990 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991 return 0;
2992}
2993
2994static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2995{
2996 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2997 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002998 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999 struct sock *sk;
3000
3001 scid = __le16_to_cpu(rsp->scid);
3002 dcid = __le16_to_cpu(rsp->dcid);
3003
3004 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3005
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003006 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003007 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008 return 0;
3009
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003010 sk = chan->sk;
3011
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003012 l2cap_chan_del(chan, 0);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003013 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003015 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016 return 0;
3017}
3018
3019static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3020{
3021 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022 u16 type;
3023
3024 type = __le16_to_cpu(req->type);
3025
3026 BT_DBG("type 0x%4.4x", type);
3027
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003028 if (type == L2CAP_IT_FEAT_MASK) {
3029 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003030 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003031 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3032 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3033 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003034 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003035 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3036 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003037 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003038 feat_mask |= L2CAP_FEAT_EXT_FLOW
3039 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003040
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003041 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003042 l2cap_send_cmd(conn, cmd->ident,
3043 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003044 } else if (type == L2CAP_IT_FIXED_CHAN) {
3045 u8 buf[12];
3046 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
Mat Martineau50a147c2011-11-02 16:18:34 -07003047
3048 if (enable_hs)
3049 l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
3050 else
3051 l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
3052
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003053 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3054 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003055 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003056 l2cap_send_cmd(conn, cmd->ident,
3057 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003058 } else {
3059 struct l2cap_info_rsp rsp;
3060 rsp.type = cpu_to_le16(type);
3061 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3062 l2cap_send_cmd(conn, cmd->ident,
3063 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3064 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065
3066 return 0;
3067}
3068
3069static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3070{
3071 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3072 u16 type, result;
3073
3074 type = __le16_to_cpu(rsp->type);
3075 result = __le16_to_cpu(rsp->result);
3076
3077 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3078
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003079 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3080 if (cmd->ident != conn->info_ident ||
3081 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3082 return 0;
3083
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -02003084 cancel_delayed_work_sync(&conn->info_work);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003085
Ville Tervoadb08ed2010-08-04 09:43:33 +03003086 if (result != L2CAP_IR_SUCCESS) {
3087 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3088 conn->info_ident = 0;
3089
3090 l2cap_conn_start(conn);
3091
3092 return 0;
3093 }
3094
Marcel Holtmann984947d2009-02-06 23:35:19 +01003095 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003096 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003097
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003098 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003099 struct l2cap_info_req req;
3100 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3101
3102 conn->info_ident = l2cap_get_ident(conn);
3103
3104 l2cap_send_cmd(conn, conn->info_ident,
3105 L2CAP_INFO_REQ, sizeof(req), &req);
3106 } else {
3107 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3108 conn->info_ident = 0;
3109
3110 l2cap_conn_start(conn);
3111 }
3112 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003113 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003114 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003115
3116 l2cap_conn_start(conn);
3117 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003118
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119 return 0;
3120}
3121
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003122static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3123 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3124 void *data)
3125{
3126 struct l2cap_create_chan_req *req = data;
3127 struct l2cap_create_chan_rsp rsp;
3128 u16 psm, scid;
3129
3130 if (cmd_len != sizeof(*req))
3131 return -EPROTO;
3132
3133 if (!enable_hs)
3134 return -EINVAL;
3135
3136 psm = le16_to_cpu(req->psm);
3137 scid = le16_to_cpu(req->scid);
3138
3139 BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3140
3141 /* Placeholder: Always reject */
3142 rsp.dcid = 0;
3143 rsp.scid = cpu_to_le16(scid);
3144 rsp.result = L2CAP_CR_NO_MEM;
3145 rsp.status = L2CAP_CS_NO_INFO;
3146
3147 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3148 sizeof(rsp), &rsp);
3149
3150 return 0;
3151}
3152
3153static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3154 struct l2cap_cmd_hdr *cmd, void *data)
3155{
3156 BT_DBG("conn %p", conn);
3157
3158 return l2cap_connect_rsp(conn, cmd, data);
3159}
3160
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003161static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
3162 u16 icid, u16 result)
3163{
3164 struct l2cap_move_chan_rsp rsp;
3165
3166 BT_DBG("icid %d, result %d", icid, result);
3167
3168 rsp.icid = cpu_to_le16(icid);
3169 rsp.result = cpu_to_le16(result);
3170
3171 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
3172}
3173
3174static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
3175 struct l2cap_chan *chan, u16 icid, u16 result)
3176{
3177 struct l2cap_move_chan_cfm cfm;
3178 u8 ident;
3179
3180 BT_DBG("icid %d, result %d", icid, result);
3181
3182 ident = l2cap_get_ident(conn);
3183 if (chan)
3184 chan->ident = ident;
3185
3186 cfm.icid = cpu_to_le16(icid);
3187 cfm.result = cpu_to_le16(result);
3188
3189 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
3190}
3191
3192static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
3193 u16 icid)
3194{
3195 struct l2cap_move_chan_cfm_rsp rsp;
3196
3197 BT_DBG("icid %d", icid);
3198
3199 rsp.icid = cpu_to_le16(icid);
3200 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
3201}
3202
3203static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
3204 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3205{
3206 struct l2cap_move_chan_req *req = data;
3207 u16 icid = 0;
3208 u16 result = L2CAP_MR_NOT_ALLOWED;
3209
3210 if (cmd_len != sizeof(*req))
3211 return -EPROTO;
3212
3213 icid = le16_to_cpu(req->icid);
3214
3215 BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
3216
3217 if (!enable_hs)
3218 return -EINVAL;
3219
3220 /* Placeholder: Always refuse */
3221 l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
3222
3223 return 0;
3224}
3225
3226static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
3227 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3228{
3229 struct l2cap_move_chan_rsp *rsp = data;
3230 u16 icid, result;
3231
3232 if (cmd_len != sizeof(*rsp))
3233 return -EPROTO;
3234
3235 icid = le16_to_cpu(rsp->icid);
3236 result = le16_to_cpu(rsp->result);
3237
3238 BT_DBG("icid %d, result %d", icid, result);
3239
3240 /* Placeholder: Always unconfirmed */
3241 l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
3242
3243 return 0;
3244}
3245
3246static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
3247 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3248{
3249 struct l2cap_move_chan_cfm *cfm = data;
3250 u16 icid, result;
3251
3252 if (cmd_len != sizeof(*cfm))
3253 return -EPROTO;
3254
3255 icid = le16_to_cpu(cfm->icid);
3256 result = le16_to_cpu(cfm->result);
3257
3258 BT_DBG("icid %d, result %d", icid, result);
3259
3260 l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
3261
3262 return 0;
3263}
3264
3265static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
3266 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3267{
3268 struct l2cap_move_chan_cfm_rsp *rsp = data;
3269 u16 icid;
3270
3271 if (cmd_len != sizeof(*rsp))
3272 return -EPROTO;
3273
3274 icid = le16_to_cpu(rsp->icid);
3275
3276 BT_DBG("icid %d", icid);
3277
3278 return 0;
3279}
3280
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003281static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02003282 u16 to_multiplier)
3283{
3284 u16 max_latency;
3285
3286 if (min > max || min < 6 || max > 3200)
3287 return -EINVAL;
3288
3289 if (to_multiplier < 10 || to_multiplier > 3200)
3290 return -EINVAL;
3291
3292 if (max >= to_multiplier * 8)
3293 return -EINVAL;
3294
3295 max_latency = (to_multiplier * 8 / max) - 1;
3296 if (latency > 499 || latency > max_latency)
3297 return -EINVAL;
3298
3299 return 0;
3300}
3301
3302static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3303 struct l2cap_cmd_hdr *cmd, u8 *data)
3304{
3305 struct hci_conn *hcon = conn->hcon;
3306 struct l2cap_conn_param_update_req *req;
3307 struct l2cap_conn_param_update_rsp rsp;
3308 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003309 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02003310
3311 if (!(hcon->link_mode & HCI_LM_MASTER))
3312 return -EINVAL;
3313
3314 cmd_len = __le16_to_cpu(cmd->len);
3315 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3316 return -EPROTO;
3317
3318 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003319 min = __le16_to_cpu(req->min);
3320 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02003321 latency = __le16_to_cpu(req->latency);
3322 to_multiplier = __le16_to_cpu(req->to_multiplier);
3323
3324 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3325 min, max, latency, to_multiplier);
3326
3327 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003328
3329 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
3330 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02003331 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3332 else
3333 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3334
3335 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3336 sizeof(rsp), &rsp);
3337
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003338 if (!err)
3339 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
3340
Claudio Takahaside731152011-02-11 19:28:55 -02003341 return 0;
3342}
3343
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003344static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
3345 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
3346{
3347 int err = 0;
3348
3349 switch (cmd->code) {
3350 case L2CAP_COMMAND_REJ:
3351 l2cap_command_rej(conn, cmd, data);
3352 break;
3353
3354 case L2CAP_CONN_REQ:
3355 err = l2cap_connect_req(conn, cmd, data);
3356 break;
3357
3358 case L2CAP_CONN_RSP:
3359 err = l2cap_connect_rsp(conn, cmd, data);
3360 break;
3361
3362 case L2CAP_CONF_REQ:
3363 err = l2cap_config_req(conn, cmd, cmd_len, data);
3364 break;
3365
3366 case L2CAP_CONF_RSP:
3367 err = l2cap_config_rsp(conn, cmd, data);
3368 break;
3369
3370 case L2CAP_DISCONN_REQ:
3371 err = l2cap_disconnect_req(conn, cmd, data);
3372 break;
3373
3374 case L2CAP_DISCONN_RSP:
3375 err = l2cap_disconnect_rsp(conn, cmd, data);
3376 break;
3377
3378 case L2CAP_ECHO_REQ:
3379 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3380 break;
3381
3382 case L2CAP_ECHO_RSP:
3383 break;
3384
3385 case L2CAP_INFO_REQ:
3386 err = l2cap_information_req(conn, cmd, data);
3387 break;
3388
3389 case L2CAP_INFO_RSP:
3390 err = l2cap_information_rsp(conn, cmd, data);
3391 break;
3392
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003393 case L2CAP_CREATE_CHAN_REQ:
3394 err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3395 break;
3396
3397 case L2CAP_CREATE_CHAN_RSP:
3398 err = l2cap_create_channel_rsp(conn, cmd, data);
3399 break;
3400
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003401 case L2CAP_MOVE_CHAN_REQ:
3402 err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
3403 break;
3404
3405 case L2CAP_MOVE_CHAN_RSP:
3406 err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
3407 break;
3408
3409 case L2CAP_MOVE_CHAN_CFM:
3410 err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
3411 break;
3412
3413 case L2CAP_MOVE_CHAN_CFM_RSP:
3414 err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
3415 break;
3416
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003417 default:
3418 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3419 err = -EINVAL;
3420 break;
3421 }
3422
3423 return err;
3424}
3425
3426static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3427 struct l2cap_cmd_hdr *cmd, u8 *data)
3428{
3429 switch (cmd->code) {
3430 case L2CAP_COMMAND_REJ:
3431 return 0;
3432
3433 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003434 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003435
3436 case L2CAP_CONN_PARAM_UPDATE_RSP:
3437 return 0;
3438
3439 default:
3440 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3441 return -EINVAL;
3442 }
3443}
3444
3445static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3446 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003447{
3448 u8 *data = skb->data;
3449 int len = skb->len;
3450 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003451 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003452
3453 l2cap_raw_recv(conn, skb);
3454
3455 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003456 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3458 data += L2CAP_CMD_HDR_SIZE;
3459 len -= L2CAP_CMD_HDR_SIZE;
3460
Al Viro88219a02007-07-29 00:17:25 -07003461 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462
Al Viro88219a02007-07-29 00:17:25 -07003463 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 -07003464
Al Viro88219a02007-07-29 00:17:25 -07003465 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466 BT_DBG("corrupted command");
3467 break;
3468 }
3469
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003470 if (conn->hcon->type == LE_LINK)
3471 err = l2cap_le_sig_cmd(conn, &cmd, data);
3472 else
3473 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003474
3475 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003476 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003477
3478 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479
3480 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003481 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3483 }
3484
Al Viro88219a02007-07-29 00:17:25 -07003485 data += cmd_len;
3486 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487 }
3488
3489 kfree_skb(skb);
3490}
3491
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003492static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003493{
3494 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003495 int hdr_size;
3496
3497 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3498 hdr_size = L2CAP_EXT_HDR_SIZE;
3499 else
3500 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003501
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003502 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003503 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003504 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3505 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3506
3507 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003508 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003509 }
3510 return 0;
3511}
3512
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003513static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003514{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003515 u32 control = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003516
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003517 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003518
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003519 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003520
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003521 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003522 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003523 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003524 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003525 }
3526
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003527 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003528 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003529
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003530 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003531
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003532 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003533 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003534 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003535 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003536 }
3537}
3538
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003539static 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 -03003540{
3541 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003542 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003543
3544 bt_cb(skb)->tx_seq = tx_seq;
3545 bt_cb(skb)->sar = sar;
3546
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003547 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003548
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003549 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003550
Szymon Janc039d9572011-11-16 09:32:19 +01003551 while (next_skb) {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003552 if (bt_cb(next_skb)->tx_seq == tx_seq)
3553 return -EINVAL;
3554
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003555 next_tx_seq_offset = __seq_offset(chan,
3556 bt_cb(next_skb)->tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003557
3558 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003559 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003560 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003561 }
3562
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003563 if (skb_queue_is_last(&chan->srej_q, next_skb))
Szymon Janc039d9572011-11-16 09:32:19 +01003564 next_skb = NULL;
3565 else
3566 next_skb = skb_queue_next(&chan->srej_q, next_skb);
3567 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003568
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003569 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003570
3571 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003572}
3573
Mat Martineau84084a32011-07-22 14:54:00 -07003574static void append_skb_frag(struct sk_buff *skb,
3575 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003576{
Mat Martineau84084a32011-07-22 14:54:00 -07003577 /* skb->len reflects data in skb as well as all fragments
3578 * skb->data_len reflects only data in fragments
3579 */
3580 if (!skb_has_frag_list(skb))
3581 skb_shinfo(skb)->frag_list = new_frag;
3582
3583 new_frag->next = NULL;
3584
3585 (*last_frag)->next = new_frag;
3586 *last_frag = new_frag;
3587
3588 skb->len += new_frag->len;
3589 skb->data_len += new_frag->len;
3590 skb->truesize += new_frag->truesize;
3591}
3592
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003593static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
Mat Martineau84084a32011-07-22 14:54:00 -07003594{
3595 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003596
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003597 switch (__get_ctrl_sar(chan, control)) {
3598 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003599 if (chan->sdu)
3600 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003601
Mat Martineau84084a32011-07-22 14:54:00 -07003602 err = chan->ops->recv(chan->data, skb);
3603 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003604
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003605 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003606 if (chan->sdu)
3607 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003608
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003609 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003610 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003611
Mat Martineau84084a32011-07-22 14:54:00 -07003612 if (chan->sdu_len > chan->imtu) {
3613 err = -EMSGSIZE;
3614 break;
3615 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003616
Mat Martineau84084a32011-07-22 14:54:00 -07003617 if (skb->len >= chan->sdu_len)
3618 break;
3619
3620 chan->sdu = skb;
3621 chan->sdu_last_frag = skb;
3622
3623 skb = NULL;
3624 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003625 break;
3626
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003627 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003628 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003629 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003630
Mat Martineau84084a32011-07-22 14:54:00 -07003631 append_skb_frag(chan->sdu, skb,
3632 &chan->sdu_last_frag);
3633 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003634
Mat Martineau84084a32011-07-22 14:54:00 -07003635 if (chan->sdu->len >= chan->sdu_len)
3636 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003637
Mat Martineau84084a32011-07-22 14:54:00 -07003638 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003639 break;
3640
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003641 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003642 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003643 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003644
Mat Martineau84084a32011-07-22 14:54:00 -07003645 append_skb_frag(chan->sdu, skb,
3646 &chan->sdu_last_frag);
3647 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003648
Mat Martineau84084a32011-07-22 14:54:00 -07003649 if (chan->sdu->len != chan->sdu_len)
3650 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003651
Mat Martineau84084a32011-07-22 14:54:00 -07003652 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003653
Mat Martineau84084a32011-07-22 14:54:00 -07003654 if (!err) {
3655 /* Reassembly complete */
3656 chan->sdu = NULL;
3657 chan->sdu_last_frag = NULL;
3658 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003659 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003660 break;
3661 }
3662
Mat Martineau84084a32011-07-22 14:54:00 -07003663 if (err) {
3664 kfree_skb(skb);
3665 kfree_skb(chan->sdu);
3666 chan->sdu = NULL;
3667 chan->sdu_last_frag = NULL;
3668 chan->sdu_len = 0;
3669 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003670
Mat Martineau84084a32011-07-22 14:54:00 -07003671 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003672}
3673
Mat Martineau26f880d2011-07-07 09:39:01 -07003674static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003675{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003676 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003677
Mat Martineau26f880d2011-07-07 09:39:01 -07003678 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003679
Mat Martineau26f880d2011-07-07 09:39:01 -07003680 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3681
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003682 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003683 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Mat Martineau26f880d2011-07-07 09:39:01 -07003684 l2cap_send_sframe(chan, control);
3685
3686 set_bit(CONN_RNR_SENT, &chan->conn_state);
3687
3688 __clear_ack_timer(chan);
3689}
3690
3691static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3692{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003693 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003694
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003695 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003696 goto done;
3697
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003698 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003699 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003700 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003701 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003702 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003703
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003704 __clear_retrans_timer(chan);
3705 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003706
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003707 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003708
3709done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003710 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3711 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003712
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003713 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003714}
3715
Mat Martineaue3281402011-07-07 09:39:02 -07003716void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003717{
Mat Martineaue3281402011-07-07 09:39:02 -07003718 if (chan->mode == L2CAP_MODE_ERTM) {
3719 if (busy)
3720 l2cap_ertm_enter_local_busy(chan);
3721 else
3722 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003723 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003724}
3725
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003726static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003727{
3728 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003729 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003730
Mat Martineaue3281402011-07-07 09:39:02 -07003731 while ((skb = skb_peek(&chan->srej_q)) &&
3732 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3733 int err;
3734
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003735 if (bt_cb(skb)->tx_seq != tx_seq)
3736 break;
3737
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003738 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003739 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003740 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003741
3742 if (err < 0) {
3743 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3744 break;
3745 }
3746
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003747 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
3748 tx_seq = __next_seq(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003749 }
3750}
3751
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003752static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003753{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003754 struct srej_list *l, *tmp;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003755 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003756
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003757 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003758 if (l->tx_seq == tx_seq) {
3759 list_del(&l->list);
3760 kfree(l);
3761 return;
3762 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003763 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003764 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003765 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003766 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003767 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003768 }
3769}
3770
Szymon Jancaef89f22011-11-16 09:32:18 +01003771static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003772{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003773 struct srej_list *new;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003774 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003775
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003776 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003777 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003778 control |= __set_reqseq(chan, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003779 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003780
3781 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Szymon Jancaef89f22011-11-16 09:32:18 +01003782 if (!new)
3783 return -ENOMEM;
3784
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003785 new->tx_seq = chan->expected_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003786
3787 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
3788
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003789 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003790 }
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003791
3792 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Szymon Jancaef89f22011-11-16 09:32:18 +01003793
3794 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003795}
3796
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003797static 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 -03003798{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003799 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003800 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003801 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003802 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003803 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003804 int err = 0;
3805
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003806 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 -03003807 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003808
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003809 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003810 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003811 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003812 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003813 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003814 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003815 }
3816
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003817 chan->expected_ack_seq = req_seq;
3818 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003819
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003820 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003821
3822 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003823 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003824 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003825 goto drop;
3826 }
3827
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003828 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003829 goto drop;
3830
Mat Martineau02f1b642011-06-29 14:35:19 -07003831 if (tx_seq == chan->expected_tx_seq)
3832 goto expected;
3833
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003834 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003835 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003836
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003837 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003838 struct srej_list, list);
3839 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003840 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003841 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003842
3843 list_del(&first->list);
3844 kfree(first);
3845
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003846 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003847 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003848 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003849 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003850 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003851 }
3852 } else {
3853 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003854
3855 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003856 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003857 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003858
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003859 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003860 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003861 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003862 return 0;
3863 }
3864 }
Szymon Jancaef89f22011-11-16 09:32:18 +01003865
3866 err = l2cap_send_srejframe(chan, tx_seq);
3867 if (err < 0) {
3868 l2cap_send_disconn_req(chan->conn, chan, -err);
3869 return err;
3870 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003871 }
3872 } else {
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003873 expected_tx_seq_offset = __seq_offset(chan,
3874 chan->expected_tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003875
3876 /* duplicated tx_seq */
3877 if (tx_seq_offset < expected_tx_seq_offset)
3878 goto drop;
3879
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003880 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003881
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003882 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003883
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003884 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003885 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003886
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003887 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003888 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003889
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003890 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003891
Szymon Jancaef89f22011-11-16 09:32:18 +01003892 err = l2cap_send_srejframe(chan, tx_seq);
3893 if (err < 0) {
3894 l2cap_send_disconn_req(chan->conn, chan, -err);
3895 return err;
3896 }
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003897
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003898 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003899 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003900 return 0;
3901
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003902expected:
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003903 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003904
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003905 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003906 bt_cb(skb)->tx_seq = tx_seq;
3907 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003908 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003909 return 0;
3910 }
3911
Mat Martineau84084a32011-07-22 14:54:00 -07003912 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003913 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
3914
Mat Martineaue3281402011-07-07 09:39:02 -07003915 if (err < 0) {
3916 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3917 return err;
3918 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003919
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003920 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003921 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003922 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003923 }
3924
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003925
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003926 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3927 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003928 l2cap_send_ack(chan);
Gustavo F. Padovan4d611e42011-06-23 19:30:48 -03003929 else
3930 __set_ack_timer(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003931
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003932 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003933
3934drop:
3935 kfree_skb(skb);
3936 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003937}
3938
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003939static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003940{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003941 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003942 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003943
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003944 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003945 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003946
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003947 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003948 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3949 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3950 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003951 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003952 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003953
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003954 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003955 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003956 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003957 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003958 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003959
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003960 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003961 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003962
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003963 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003964 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003965
3966 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003967 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003968 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003969 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003970
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003971 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3972 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003973 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003974 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003975 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003976 }
3977}
3978
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003979static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003980{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003981 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003982
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003983 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003984
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003985 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003986
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003987 chan->expected_ack_seq = tx_seq;
3988 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003989
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003990 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003991 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003992 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003993 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003994 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003995
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003996 if (test_bit(CONN_WAIT_F, &chan->conn_state))
3997 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003998 }
3999}
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004000static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004001{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004002 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004003
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004004 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004005
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004006 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004007
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004008 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004009 chan->expected_ack_seq = tx_seq;
4010 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004011
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004012 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004013 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004014
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004015 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004016
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004017 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004018 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004019 set_bit(CONN_SREJ_ACT, &chan->conn_state);
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 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004023 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004024 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004025 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004026 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004027 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004028 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004029 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004030 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004031 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004032 }
4033 }
4034}
4035
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004036static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004037{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004038 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004039
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004040 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004041
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004042 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004043 chan->expected_ack_seq = tx_seq;
4044 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004045
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004046 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004047 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004048
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004049 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004050 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004051 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004052 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004053 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004054 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004055
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004056 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004057 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004058 } else {
4059 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4060 l2cap_send_sframe(chan, rx_control);
4061 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004062}
4063
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004064static 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 -03004065{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004066 BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004067
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004068 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004069 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004070 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004071 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004072 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004073 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004074 }
4075
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004076 switch (__get_ctrl_super(chan, rx_control)) {
4077 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004078 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004079 break;
4080
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004081 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004082 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004083 break;
4084
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004085 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004086 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004087 break;
4088
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004089 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004090 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004091 break;
4092 }
4093
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004094 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004095 return 0;
4096}
4097
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004098static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
4099{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004100 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004101 u32 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004102 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004103 int len, next_tx_seq_offset, req_seq_offset;
4104
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004105 control = __get_control(chan, skb->data);
4106 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004107 len = skb->len;
4108
4109 /*
4110 * We can just drop the corrupted I-frame here.
4111 * Receiver will miss it and start proper recovery
4112 * procedures and ask retransmission.
4113 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004114 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004115 goto drop;
4116
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004117 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004118 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004119
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004120 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004121 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004122
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004123 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004124 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004125 goto drop;
4126 }
4127
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004128 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004129
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004130 req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4131
4132 next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4133 chan->expected_ack_seq);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004134
4135 /* check for invalid req-seq */
4136 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004137 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004138 goto drop;
4139 }
4140
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004141 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004142 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004143 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004144 goto drop;
4145 }
4146
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004147 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004148 } else {
4149 if (len != 0) {
4150 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004151 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004152 goto drop;
4153 }
4154
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004155 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004156 }
4157
4158 return 0;
4159
4160drop:
4161 kfree_skb(skb);
4162 return 0;
4163}
4164
Linus Torvalds1da177e2005-04-16 15:20:36 -07004165static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4166{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004167 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07004168 struct sock *sk = NULL;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004169 u32 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004170 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004171 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004173 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004174 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175 BT_DBG("unknown cid 0x%4.4x", cid);
4176 goto drop;
4177 }
4178
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004179 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004180
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004181 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004183 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184 goto drop;
4185
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004186 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004187 case L2CAP_MODE_BASIC:
4188 /* If socket recv buffers overflows we drop data here
4189 * which is *bad* because L2CAP has to be reliable.
4190 * But we don't have any other choice. L2CAP doesn't
4191 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004193 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004194 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004195
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004196 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004197 goto done;
4198 break;
4199
4200 case L2CAP_MODE_ERTM:
Gustavo F. Padovaneb403a12011-06-24 01:54:50 -03004201 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004202
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004203 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004204
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004205 case L2CAP_MODE_STREAMING:
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004206 control = __get_control(chan, skb->data);
4207 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004208 len = skb->len;
4209
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004210 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004211 goto drop;
4212
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004213 if (__is_sar_start(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004214 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004215
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004216 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004217 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004218
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004219 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004220 goto drop;
4221
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004222 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004223
Mat Martineau84084a32011-07-22 14:54:00 -07004224 if (chan->expected_tx_seq != tx_seq) {
4225 /* Frame(s) missing - must discard partial SDU */
4226 kfree_skb(chan->sdu);
4227 chan->sdu = NULL;
4228 chan->sdu_last_frag = NULL;
4229 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004230
Mat Martineau84084a32011-07-22 14:54:00 -07004231 /* TODO: Notify userland of missing data */
4232 }
4233
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004234 chan->expected_tx_seq = __next_seq(chan, tx_seq);
Mat Martineau84084a32011-07-22 14:54:00 -07004235
4236 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
4237 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004238
4239 goto done;
4240
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004241 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004242 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004243 break;
4244 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245
4246drop:
4247 kfree_skb(skb);
4248
4249done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004250 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004251 release_sock(sk);
Marcel Holtmann01394182006-07-03 10:02:46 +02004252
Linus Torvalds1da177e2005-04-16 15:20:36 -07004253 return 0;
4254}
4255
Al Viro8e036fc2007-07-29 00:16:36 -07004256static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004258 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004259 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004261 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
4262 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004263 goto drop;
4264
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004265 sk = chan->sk;
4266
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004267 lock_sock(sk);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00004268
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269 BT_DBG("sk %p, len %d", sk, skb->len);
4270
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004271 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004272 goto drop;
4273
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004274 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004275 goto drop;
4276
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004277 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278 goto done;
4279
4280drop:
4281 kfree_skb(skb);
4282
4283done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004284 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004285 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004286 return 0;
4287}
4288
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004289static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
4290{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004291 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004292 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004293
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004294 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
4295 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004296 goto drop;
4297
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004298 sk = chan->sk;
4299
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004300 lock_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004301
4302 BT_DBG("sk %p, len %d", sk, skb->len);
4303
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004304 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004305 goto drop;
4306
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004307 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004308 goto drop;
4309
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004310 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004311 goto done;
4312
4313drop:
4314 kfree_skb(skb);
4315
4316done:
4317 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004318 release_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004319 return 0;
4320}
4321
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4323{
4324 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004325 u16 cid, len;
4326 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004327
4328 skb_pull(skb, L2CAP_HDR_SIZE);
4329 cid = __le16_to_cpu(lh->cid);
4330 len = __le16_to_cpu(lh->len);
4331
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004332 if (len != skb->len) {
4333 kfree_skb(skb);
4334 return;
4335 }
4336
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4338
4339 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004340 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004341 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342 l2cap_sig_channel(conn, skb);
4343 break;
4344
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004345 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004346 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347 skb_pull(skb, 2);
4348 l2cap_conless_channel(conn, psm, skb);
4349 break;
4350
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004351 case L2CAP_CID_LE_DATA:
4352 l2cap_att_channel(conn, cid, skb);
4353 break;
4354
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004355 case L2CAP_CID_SMP:
4356 if (smp_sig_channel(conn, skb))
4357 l2cap_conn_del(conn->hcon, EACCES);
4358 break;
4359
Linus Torvalds1da177e2005-04-16 15:20:36 -07004360 default:
4361 l2cap_data_channel(conn, cid, skb);
4362 break;
4363 }
4364}
4365
4366/* ---- L2CAP interface with lower layer (HCI) ---- */
4367
4368static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4369{
4370 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004371 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372
4373 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004374 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375
4376 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4377
4378 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004379 read_lock(&chan_list_lock);
4380 list_for_each_entry(c, &chan_list, global_l) {
4381 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004382
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004383 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384 continue;
4385
4386 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004387 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004388 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004389 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004390 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004391 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4392 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004393 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004394 lm2 |= HCI_LM_MASTER;
4395 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004397 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398
4399 return exact ? lm1 : lm2;
4400}
4401
4402static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4403{
Marcel Holtmann01394182006-07-03 10:02:46 +02004404 struct l2cap_conn *conn;
4405
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4407
Ville Tervoacd7d372011-02-10 22:38:49 -03004408 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004409 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004410
4411 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412 conn = l2cap_conn_add(hcon, status);
4413 if (conn)
4414 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004415 } else
Joe Perchese1750722011-06-29 18:18:29 -07004416 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417
4418 return 0;
4419}
4420
Marcel Holtmann2950f212009-02-12 14:02:50 +01004421static int l2cap_disconn_ind(struct hci_conn *hcon)
4422{
4423 struct l2cap_conn *conn = hcon->l2cap_data;
4424
4425 BT_DBG("hcon %p", hcon);
4426
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03004427 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02004428 return HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01004429
4430 return conn->disc_reason;
4431}
4432
4433static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434{
4435 BT_DBG("hcon %p reason %d", hcon, reason);
4436
Ville Tervoacd7d372011-02-10 22:38:49 -03004437 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004438 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439
Joe Perchese1750722011-06-29 18:18:29 -07004440 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004441
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442 return 0;
4443}
4444
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004445static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004446{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004447 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004448 return;
4449
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004450 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004451 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004452 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02004453 __set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004454 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004455 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004456 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004457 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004458 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004459 }
4460}
4461
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004462static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004463{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004464 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004465 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004466
Marcel Holtmann01394182006-07-03 10:02:46 +02004467 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004468 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004469
Linus Torvalds1da177e2005-04-16 15:20:36 -07004470 BT_DBG("conn %p", conn);
4471
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004472 if (hcon->type == LE_LINK) {
4473 smp_distribute_keys(conn, 0);
4474 del_timer(&conn->security_timer);
4475 }
4476
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -02004477 mutex_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004478
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004479 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004480 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004481
Linus Torvalds1da177e2005-04-16 15:20:36 -07004482 bh_lock_sock(sk);
4483
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004484 BT_DBG("chan->scid %d", chan->scid);
4485
4486 if (chan->scid == L2CAP_CID_LE_DATA) {
4487 if (!status && encrypt) {
4488 chan->sec_level = hcon->sec_level;
4489 l2cap_chan_ready(sk);
4490 }
4491
4492 bh_unlock_sock(sk);
4493 continue;
4494 }
4495
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004496 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004497 bh_unlock_sock(sk);
4498 continue;
4499 }
4500
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004501 if (!status && (chan->state == BT_CONNECTED ||
4502 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004503 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004504 bh_unlock_sock(sk);
4505 continue;
4506 }
4507
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004508 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004509 if (!status) {
4510 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004511 req.scid = cpu_to_le16(chan->scid);
4512 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004513
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004514 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004515 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004516
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004517 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004518 L2CAP_CONN_REQ, sizeof(req), &req);
4519 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004520 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02004521 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004522 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004523 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004524 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004525 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004526
4527 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004528 if (bt_sk(sk)->defer_setup) {
4529 struct sock *parent = bt_sk(sk)->parent;
4530 res = L2CAP_CR_PEND;
4531 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004532 if (parent)
4533 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004534 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004535 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004536 res = L2CAP_CR_SUCCESS;
4537 stat = L2CAP_CS_NO_INFO;
4538 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004539 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004540 l2cap_state_change(chan, BT_DISCONN);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02004541 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004542 res = L2CAP_CR_SEC_BLOCK;
4543 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004544 }
4545
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004546 rsp.scid = cpu_to_le16(chan->dcid);
4547 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004548 rsp.result = cpu_to_le16(res);
4549 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004550 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4551 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004552 }
4553
Linus Torvalds1da177e2005-04-16 15:20:36 -07004554 bh_unlock_sock(sk);
4555 }
4556
Gustavo F. Padovand01b2ff2011-12-09 04:45:12 -02004557 mutex_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004558
Linus Torvalds1da177e2005-04-16 15:20:36 -07004559 return 0;
4560}
4561
4562static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4563{
4564 struct l2cap_conn *conn = hcon->l2cap_data;
4565
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004566 if (!conn)
4567 conn = l2cap_conn_add(hcon, 0);
4568
4569 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004570 goto drop;
4571
4572 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4573
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004574 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004575 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004576 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004577 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004578 int len;
4579
4580 if (conn->rx_len) {
4581 BT_ERR("Unexpected start frame (len %d)", skb->len);
4582 kfree_skb(conn->rx_skb);
4583 conn->rx_skb = NULL;
4584 conn->rx_len = 0;
4585 l2cap_conn_unreliable(conn, ECOMM);
4586 }
4587
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004588 /* Start fragment always begin with Basic L2CAP header */
4589 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004590 BT_ERR("Frame is too short (len %d)", skb->len);
4591 l2cap_conn_unreliable(conn, ECOMM);
4592 goto drop;
4593 }
4594
4595 hdr = (struct l2cap_hdr *) skb->data;
4596 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004597 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004598
4599 if (len == skb->len) {
4600 /* Complete frame received */
4601 l2cap_recv_frame(conn, skb);
4602 return 0;
4603 }
4604
4605 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4606
4607 if (skb->len > len) {
4608 BT_ERR("Frame is too long (len %d, expected len %d)",
4609 skb->len, len);
4610 l2cap_conn_unreliable(conn, ECOMM);
4611 goto drop;
4612 }
4613
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004614 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004615
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004616 if (chan && chan->sk) {
4617 struct sock *sk = chan->sk;
4618
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004619 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004620 BT_ERR("Frame exceeding recv MTU (len %d, "
4621 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004622 chan->imtu);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004623 release_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004624 l2cap_conn_unreliable(conn, ECOMM);
4625 goto drop;
4626 }
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004627 release_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004628 }
4629
Linus Torvalds1da177e2005-04-16 15:20:36 -07004630 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004631 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4632 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004633 goto drop;
4634
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004635 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004636 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004637 conn->rx_len = len - skb->len;
4638 } else {
4639 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4640
4641 if (!conn->rx_len) {
4642 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4643 l2cap_conn_unreliable(conn, ECOMM);
4644 goto drop;
4645 }
4646
4647 if (skb->len > conn->rx_len) {
4648 BT_ERR("Fragment is too long (len %d, expected %d)",
4649 skb->len, conn->rx_len);
4650 kfree_skb(conn->rx_skb);
4651 conn->rx_skb = NULL;
4652 conn->rx_len = 0;
4653 l2cap_conn_unreliable(conn, ECOMM);
4654 goto drop;
4655 }
4656
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004657 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004658 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004659 conn->rx_len -= skb->len;
4660
4661 if (!conn->rx_len) {
4662 /* Complete frame received */
4663 l2cap_recv_frame(conn, conn->rx_skb);
4664 conn->rx_skb = NULL;
4665 }
4666 }
4667
4668drop:
4669 kfree_skb(skb);
4670 return 0;
4671}
4672
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004673static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004674{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004675 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004676
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004677 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004678
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004679 list_for_each_entry(c, &chan_list, global_l) {
4680 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004681
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004682 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 +01004683 batostr(&bt_sk(sk)->src),
4684 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004685 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004686 c->scid, c->dcid, c->imtu, c->omtu,
4687 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004688}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004689
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004690 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004691
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004692 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004693}
4694
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004695static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4696{
4697 return single_open(file, l2cap_debugfs_show, inode->i_private);
4698}
4699
4700static const struct file_operations l2cap_debugfs_fops = {
4701 .open = l2cap_debugfs_open,
4702 .read = seq_read,
4703 .llseek = seq_lseek,
4704 .release = single_release,
4705};
4706
4707static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004708
Linus Torvalds1da177e2005-04-16 15:20:36 -07004709static struct hci_proto l2cap_hci_proto = {
4710 .name = "L2CAP",
4711 .id = HCI_PROTO_L2CAP,
4712 .connect_ind = l2cap_connect_ind,
4713 .connect_cfm = l2cap_connect_cfm,
4714 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004715 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004716 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004717 .recv_acldata = l2cap_recv_acldata
4718};
4719
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004720int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004721{
4722 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004723
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004724 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004725 if (err < 0)
4726 return err;
4727
Linus Torvalds1da177e2005-04-16 15:20:36 -07004728 err = hci_register_proto(&l2cap_hci_proto);
4729 if (err < 0) {
4730 BT_ERR("L2CAP protocol registration failed");
4731 bt_sock_unregister(BTPROTO_L2CAP);
4732 goto error;
4733 }
4734
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004735 if (bt_debugfs) {
4736 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4737 bt_debugfs, NULL, &l2cap_debugfs_fops);
4738 if (!l2cap_debugfs)
4739 BT_ERR("Failed to create L2CAP debug file");
4740 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004741
Linus Torvalds1da177e2005-04-16 15:20:36 -07004742 return 0;
4743
4744error:
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004745 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004746 return err;
4747}
4748
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004749void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004750{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004751 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004752
Linus Torvalds1da177e2005-04-16 15:20:36 -07004753 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4754 BT_ERR("L2CAP protocol unregistration failed");
4755
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004756 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004757}
4758
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004759module_param(disable_ertm, bool, 0644);
4760MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");