blob: ed67ac0ca21c119cce085936bc15e4aa7553414b [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. Padovan710f9b02011-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
118 read_lock(&conn->chan_lock);
119 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. Padovanbaa7e1f2011-03-31 16:17:41 -0300122 read_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
141 read_lock(&conn->chan_lock);
142 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. Padovanbaa7e1f2011-03-31 16:17:41 -0300145 read_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 */
384 write_lock_bh(&conn->chan_lock);
385 list_del(&chan->list);
386 write_unlock_bh(&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
701 mod_timer(&conn->info_timer, jiffies +
702 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. Padovanbaa7e1f2011-03-31 16:17:41 -0300757 read_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. Padovan2461daa2011-06-17 12:57:25 -0300783 read_unlock(&conn->chan_lock);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300784 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300785 read_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. Padovanbaa7e1f2011-03-31 16:17:41 -0300841 read_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. Padovanbaa7e1f2011-03-31 16:17:41 -0300906 write_lock_bh(&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. Padovanbaa7e1f2011-03-31 16:17:41 -0300922 write_unlock_bh(&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. Padovanbaa7e1f2011-03-31 16:17:41 -0300957 read_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. Padovanbaa7e1f2011-03-31 16:17:41 -0300979 read_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. Padovanbaa7e1f2011-03-31 16:17:41 -0300989 read_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. Padovanbaa7e1f2011-03-31 16:17:41 -0300998 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200999}
1000
1001static void l2cap_info_timeout(unsigned long arg)
1002{
1003 struct l2cap_conn *conn = (void *) arg;
1004
Marcel Holtmann984947d2009-02-06 23:35:19 +01001005 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01001006 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01001007
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001008 l2cap_conn_start(conn);
1009}
1010
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001011static void l2cap_conn_del(struct hci_conn *hcon, int err)
1012{
1013 struct l2cap_conn *conn = hcon->l2cap_data;
1014 struct l2cap_chan *chan, *l;
1015 struct sock *sk;
1016
1017 if (!conn)
1018 return;
1019
1020 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
1021
1022 kfree_skb(conn->rx_skb);
1023
1024 /* Kill channels */
1025 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
1026 sk = chan->sk;
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001027 lock_sock(sk);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001028 l2cap_chan_del(chan, err);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001029 release_sock(sk);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001030 chan->ops->close(chan->data);
1031 }
1032
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001033 hci_chan_del(conn->hchan);
1034
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001035 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1036 del_timer_sync(&conn->info_timer);
1037
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001038 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) {
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001039 del_timer(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001040 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001041 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001042
1043 hcon->l2cap_data = NULL;
1044 kfree(conn);
1045}
1046
1047static void security_timeout(unsigned long arg)
1048{
1049 struct l2cap_conn *conn = (void *) arg;
1050
1051 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1052}
1053
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1055{
Marcel Holtmann01394182006-07-03 10:02:46 +02001056 struct l2cap_conn *conn = hcon->l2cap_data;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001057 struct hci_chan *hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058
Marcel Holtmann01394182006-07-03 10:02:46 +02001059 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 return conn;
1061
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001062 hchan = hci_chan_create(hcon);
1063 if (!hchan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001066 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1067 if (!conn) {
1068 hci_chan_del(hchan);
1069 return NULL;
1070 }
1071
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 hcon->l2cap_data = conn;
1073 conn->hcon = hcon;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001074 conn->hchan = hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001076 BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
Marcel Holtmann01394182006-07-03 10:02:46 +02001077
Ville Tervoacd7d372011-02-10 22:38:49 -03001078 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1079 conn->mtu = hcon->hdev->le_mtu;
1080 else
1081 conn->mtu = hcon->hdev->acl_mtu;
1082
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 conn->src = &hcon->hdev->bdaddr;
1084 conn->dst = &hcon->dst;
1085
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001086 conn->feat_mask = 0;
1087
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001089 rwlock_init(&conn->chan_lock);
1090
1091 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001093 if (hcon->type == LE_LINK)
1094 setup_timer(&conn->security_timer, security_timeout,
1095 (unsigned long) conn);
1096 else
Ville Tervob62f3282011-02-10 22:38:50 -03001097 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +00001098 (unsigned long) conn);
1099
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. Padovanbaa7e1f2011-03-31 16:17:41 -03001107 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001108 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001109 write_unlock_bh(&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. Padovanbaa7e1f2011-03-31 16:17:41 -03001774 read_lock(&conn->chan_lock);
1775 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. Padovanbaa7e1f2011-03-31 16:17:41 -03001790 read_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. Padovan525cd182011-03-25 19:43:39 -03001963 struct sock *sk = chan->sk;
1964
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001965 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001966 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001967 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001968 chan->num_acked = 0;
1969 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001970
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001971 INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
1972 INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
1973 INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001974
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001975 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001976
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001977 INIT_LIST_HEAD(&chan->srej_l);
1978
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001979
1980 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001981}
1982
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001983static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1984{
1985 switch (mode) {
1986 case L2CAP_MODE_STREAMING:
1987 case L2CAP_MODE_ERTM:
1988 if (l2cap_mode_supported(mode, remote_feat_mask))
1989 return mode;
1990 /* fall through */
1991 default:
1992 return L2CAP_MODE_BASIC;
1993 }
1994}
1995
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001996static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
1997{
1998 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
1999}
2000
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002001static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2002{
2003 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2004}
2005
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002006static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
2007{
2008 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002009 __l2cap_ews_supported(chan)) {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002010 /* use extended control field */
2011 set_bit(FLAG_EXT_CTRL, &chan->flags);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002012 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2013 } else {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002014 chan->tx_win = min_t(u16, chan->tx_win,
2015 L2CAP_DEFAULT_TX_WINDOW);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002016 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2017 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002018}
2019
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002020static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002023 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024 void *ptr = req->data;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002025 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002027 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002029 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002030 goto done;
2031
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002032 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002033 case L2CAP_MODE_STREAMING:
2034 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002035 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002036 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002037
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002038 if (__l2cap_efs_supported(chan))
2039 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2040
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002041 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002042 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002043 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002044 break;
2045 }
2046
2047done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002048 if (chan->imtu != L2CAP_DEFAULT_MTU)
2049 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002050
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002051 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002052 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002053 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2054 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002055 break;
2056
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002057 rfc.mode = L2CAP_MODE_BASIC;
2058 rfc.txwin_size = 0;
2059 rfc.max_transmit = 0;
2060 rfc.retrans_timeout = 0;
2061 rfc.monitor_timeout = 0;
2062 rfc.max_pdu_size = 0;
2063
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002064 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2065 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002066 break;
2067
2068 case L2CAP_MODE_ERTM:
2069 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002070 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002071 rfc.retrans_timeout = 0;
2072 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002073
2074 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2075 L2CAP_EXT_HDR_SIZE -
2076 L2CAP_SDULEN_SIZE -
2077 L2CAP_FCS_SIZE);
2078 rfc.max_pdu_size = cpu_to_le16(size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002079
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002080 l2cap_txwin_setup(chan);
2081
2082 rfc.txwin_size = min_t(u16, chan->tx_win,
2083 L2CAP_DEFAULT_TX_WINDOW);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002084
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002085 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2086 (unsigned long) &rfc);
2087
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002088 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2089 l2cap_add_opt_efs(&ptr, chan);
2090
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002091 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002092 break;
2093
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002094 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002095 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002096 chan->fcs = L2CAP_FCS_NONE;
2097 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002098 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002099
2100 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2101 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2102 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002103 break;
2104
2105 case L2CAP_MODE_STREAMING:
2106 rfc.mode = L2CAP_MODE_STREAMING;
2107 rfc.txwin_size = 0;
2108 rfc.max_transmit = 0;
2109 rfc.retrans_timeout = 0;
2110 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002111
2112 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2113 L2CAP_EXT_HDR_SIZE -
2114 L2CAP_SDULEN_SIZE -
2115 L2CAP_FCS_SIZE);
2116 rfc.max_pdu_size = cpu_to_le16(size);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002117
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002118 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2119 (unsigned long) &rfc);
2120
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002121 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2122 l2cap_add_opt_efs(&ptr, chan);
2123
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002124 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002125 break;
2126
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002127 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002128 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002129 chan->fcs = L2CAP_FCS_NONE;
2130 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002131 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002132 break;
2133 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002135 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002136 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137
2138 return ptr - data;
2139}
2140
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002141static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002143 struct l2cap_conf_rsp *rsp = data;
2144 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002145 void *req = chan->conf_req;
2146 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002147 int type, hint, olen;
2148 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002149 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002150 struct l2cap_conf_efs efs;
2151 u8 remote_efs = 0;
Marcel Holtmann861d6882007-10-20 13:37:06 +02002152 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002153 u16 result = L2CAP_CONF_SUCCESS;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002154 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002156 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002157
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002158 while (len >= L2CAP_CONF_OPT_SIZE) {
2159 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002161 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002162 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002163
2164 switch (type) {
2165 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002166 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002167 break;
2168
2169 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002170 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002171 break;
2172
2173 case L2CAP_CONF_QOS:
2174 break;
2175
Marcel Holtmann6464f352007-10-20 13:39:51 +02002176 case L2CAP_CONF_RFC:
2177 if (olen == sizeof(rfc))
2178 memcpy(&rfc, (void *) val, olen);
2179 break;
2180
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002181 case L2CAP_CONF_FCS:
2182 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002183 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002184 break;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002185
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002186 case L2CAP_CONF_EFS:
2187 remote_efs = 1;
2188 if (olen == sizeof(efs))
2189 memcpy(&efs, (void *) val, olen);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002190 break;
2191
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002192 case L2CAP_CONF_EWS:
2193 if (!enable_hs)
2194 return -ECONNREFUSED;
2195
2196 set_bit(FLAG_EXT_CTRL, &chan->flags);
2197 set_bit(CONF_EWS_RECV, &chan->conf_state);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002198 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002199 chan->remote_tx_win = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002200 break;
2201
2202 default:
2203 if (hint)
2204 break;
2205
2206 result = L2CAP_CONF_UNKNOWN;
2207 *((u8 *) ptr++) = type;
2208 break;
2209 }
2210 }
2211
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002212 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002213 goto done;
2214
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002215 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002216 case L2CAP_MODE_STREAMING:
2217 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002218 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002219 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002220 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002221 break;
2222 }
2223
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002224 if (remote_efs) {
2225 if (__l2cap_efs_supported(chan))
2226 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2227 else
2228 return -ECONNREFUSED;
2229 }
2230
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002231 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002232 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002233
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002234 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002235 }
2236
2237done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002238 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002239 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002240 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002241
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002242 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002243 return -ECONNREFUSED;
2244
2245 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2246 sizeof(rfc), (unsigned long) &rfc);
2247 }
2248
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002249 if (result == L2CAP_CONF_SUCCESS) {
2250 /* Configure output options and let the other side know
2251 * which ones we don't like. */
2252
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002253 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2254 result = L2CAP_CONF_UNACCEPT;
2255 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002256 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002257 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002258 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002259 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002260
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002261 if (remote_efs) {
2262 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2263 efs.stype != L2CAP_SERV_NOTRAFIC &&
2264 efs.stype != chan->local_stype) {
2265
2266 result = L2CAP_CONF_UNACCEPT;
2267
2268 if (chan->num_conf_req >= 1)
2269 return -ECONNREFUSED;
2270
2271 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002272 sizeof(efs),
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002273 (unsigned long) &efs);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002274 } else {
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002275 /* Send PENDING Conf Rsp */
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002276 result = L2CAP_CONF_PENDING;
2277 set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002278 }
2279 }
2280
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002281 switch (rfc.mode) {
2282 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002283 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002284 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002285 break;
2286
2287 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002288 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2289 chan->remote_tx_win = rfc.txwin_size;
2290 else
2291 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2292
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002293 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002294
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002295 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2296 chan->conn->mtu -
2297 L2CAP_EXT_HDR_SIZE -
2298 L2CAP_SDULEN_SIZE -
2299 L2CAP_FCS_SIZE);
2300 rfc.max_pdu_size = cpu_to_le16(size);
2301 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002302
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002303 rfc.retrans_timeout =
2304 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2305 rfc.monitor_timeout =
2306 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002307
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002308 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002309
2310 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2311 sizeof(rfc), (unsigned long) &rfc);
2312
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002313 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2314 chan->remote_id = efs.id;
2315 chan->remote_stype = efs.stype;
2316 chan->remote_msdu = le16_to_cpu(efs.msdu);
2317 chan->remote_flush_to =
2318 le32_to_cpu(efs.flush_to);
2319 chan->remote_acc_lat =
2320 le32_to_cpu(efs.acc_lat);
2321 chan->remote_sdu_itime =
2322 le32_to_cpu(efs.sdu_itime);
2323 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2324 sizeof(efs), (unsigned long) &efs);
2325 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002326 break;
2327
2328 case L2CAP_MODE_STREAMING:
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002329 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2330 chan->conn->mtu -
2331 L2CAP_EXT_HDR_SIZE -
2332 L2CAP_SDULEN_SIZE -
2333 L2CAP_FCS_SIZE);
2334 rfc.max_pdu_size = cpu_to_le16(size);
2335 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002336
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002337 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002338
2339 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2340 sizeof(rfc), (unsigned long) &rfc);
2341
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002342 break;
2343
2344 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002345 result = L2CAP_CONF_UNACCEPT;
2346
2347 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002348 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002349 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002350
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002351 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002352 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002353 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002354 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002355 rsp->result = cpu_to_le16(result);
2356 rsp->flags = cpu_to_le16(0x0000);
2357
2358 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359}
2360
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002361static 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 -03002362{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002363 struct l2cap_conf_req *req = data;
2364 void *ptr = req->data;
2365 int type, olen;
2366 unsigned long val;
2367 struct l2cap_conf_rfc rfc;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002368 struct l2cap_conf_efs efs;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002369
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002370 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002371
2372 while (len >= L2CAP_CONF_OPT_SIZE) {
2373 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2374
2375 switch (type) {
2376 case L2CAP_CONF_MTU:
2377 if (val < L2CAP_DEFAULT_MIN_MTU) {
2378 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002379 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002380 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002381 chan->imtu = val;
2382 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002383 break;
2384
2385 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002386 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002387 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002388 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002389 break;
2390
2391 case L2CAP_CONF_RFC:
2392 if (olen == sizeof(rfc))
2393 memcpy(&rfc, (void *)val, olen);
2394
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002395 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002396 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002397 return -ECONNREFUSED;
2398
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002399 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002400
2401 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2402 sizeof(rfc), (unsigned long) &rfc);
2403 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002404
2405 case L2CAP_CONF_EWS:
2406 chan->tx_win = min_t(u16, val,
2407 L2CAP_DEFAULT_EXT_WINDOW);
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002408 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2409 chan->tx_win);
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002410 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002411
2412 case L2CAP_CONF_EFS:
2413 if (olen == sizeof(efs))
2414 memcpy(&efs, (void *)val, olen);
2415
2416 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2417 efs.stype != L2CAP_SERV_NOTRAFIC &&
2418 efs.stype != chan->local_stype)
2419 return -ECONNREFUSED;
2420
2421 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2422 sizeof(efs), (unsigned long) &efs);
2423 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002424 }
2425 }
2426
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002427 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002428 return -ECONNREFUSED;
2429
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002430 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002431
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002432 if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002433 switch (rfc.mode) {
2434 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002435 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2436 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2437 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002438
2439 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2440 chan->local_msdu = le16_to_cpu(efs.msdu);
2441 chan->local_sdu_itime =
2442 le32_to_cpu(efs.sdu_itime);
2443 chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
2444 chan->local_flush_to =
2445 le32_to_cpu(efs.flush_to);
2446 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002447 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002448
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002449 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002450 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002451 }
2452 }
2453
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002454 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002455 req->flags = cpu_to_le16(0x0000);
2456
2457 return ptr - data;
2458}
2459
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002460static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461{
2462 struct l2cap_conf_rsp *rsp = data;
2463 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002465 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002467 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002468 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002469 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470
2471 return ptr - data;
2472}
2473
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002474void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002475{
2476 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002477 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002478 u8 buf[128];
2479
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002480 rsp.scid = cpu_to_le16(chan->dcid);
2481 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002482 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2483 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2484 l2cap_send_cmd(conn, chan->ident,
2485 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2486
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002487 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002488 return;
2489
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002490 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2491 l2cap_build_conf_req(chan, buf), buf);
2492 chan->num_conf_req++;
2493}
2494
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002495static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002496{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002497 int type, olen;
2498 unsigned long val;
2499 struct l2cap_conf_rfc rfc;
2500
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002501 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002502
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002503 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002504 return;
2505
2506 while (len >= L2CAP_CONF_OPT_SIZE) {
2507 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2508
2509 switch (type) {
2510 case L2CAP_CONF_RFC:
2511 if (olen == sizeof(rfc))
2512 memcpy(&rfc, (void *)val, olen);
2513 goto done;
2514 }
2515 }
2516
2517done:
2518 switch (rfc.mode) {
2519 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002520 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2521 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2522 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002523 break;
2524 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002525 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002526 }
2527}
2528
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002529static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2530{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002531 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002532
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002533 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002534 return 0;
2535
2536 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2537 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002538 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002539
2540 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002541 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002542
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002543 l2cap_conn_start(conn);
2544 }
2545
2546 return 0;
2547}
2548
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2550{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2552 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002553 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002554 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002555 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556
2557 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002558 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559
2560 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2561
2562 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002563 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2564 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565 result = L2CAP_CR_BAD_PSM;
2566 goto sendresp;
2567 }
2568
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002569 parent = pchan->sk;
2570
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002571 lock_sock(parent);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002572
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002573 /* Check if the ACL is secure enough (if not SDP) */
2574 if (psm != cpu_to_le16(0x0001) &&
2575 !hci_conn_check_link_mode(conn->hcon)) {
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002576 conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002577 result = L2CAP_CR_SEC_BLOCK;
2578 goto response;
2579 }
2580
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581 result = L2CAP_CR_NO_MEM;
2582
2583 /* Check for backlog size */
2584 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002585 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 goto response;
2587 }
2588
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002589 chan = pchan->ops->new_connection(pchan->data);
2590 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591 goto response;
2592
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002593 sk = chan->sk;
2594
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002595 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596
2597 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002598 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2599 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002601 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602 goto response;
2603 }
2604
2605 hci_conn_hold(conn->hcon);
2606
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607 bacpy(&bt_sk(sk)->src, conn->src);
2608 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002609 chan->psm = psm;
2610 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002612 bt_accept_enqueue(parent, sk);
2613
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002614 __l2cap_chan_add(conn, chan);
2615
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002616 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002618 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002620 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621
Marcel Holtmann984947d2009-02-06 23:35:19 +01002622 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02002623 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002624 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002625 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002626 result = L2CAP_CR_PEND;
2627 status = L2CAP_CS_AUTHOR_PEND;
2628 parent->sk_data_ready(parent, 0);
2629 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002630 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002631 result = L2CAP_CR_SUCCESS;
2632 status = L2CAP_CS_NO_INFO;
2633 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002634 } 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_AUTHEN_PEND;
2638 }
2639 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002640 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002641 result = L2CAP_CR_PEND;
2642 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643 }
2644
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002645 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646
2647response:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002648 release_sock(parent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649
2650sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002651 rsp.scid = cpu_to_le16(scid);
2652 rsp.dcid = cpu_to_le16(dcid);
2653 rsp.result = cpu_to_le16(result);
2654 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002656
2657 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2658 struct l2cap_info_req info;
2659 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2660
2661 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2662 conn->info_ident = l2cap_get_ident(conn);
2663
2664 mod_timer(&conn->info_timer, jiffies +
2665 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2666
2667 l2cap_send_cmd(conn, conn->info_ident,
2668 L2CAP_INFO_REQ, sizeof(info), &info);
2669 }
2670
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002671 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002672 result == L2CAP_CR_SUCCESS) {
2673 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002674 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002675 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002676 l2cap_build_conf_req(chan, buf), buf);
2677 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002678 }
2679
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 return 0;
2681}
2682
2683static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2684{
2685 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2686 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002687 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688 struct sock *sk;
2689 u8 req[128];
2690
2691 scid = __le16_to_cpu(rsp->scid);
2692 dcid = __le16_to_cpu(rsp->dcid);
2693 result = __le16_to_cpu(rsp->result);
2694 status = __le16_to_cpu(rsp->status);
2695
2696 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2697
2698 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002699 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002700 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002701 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002703 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002704 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002705 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706 }
2707
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002708 sk = chan->sk;
2709
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710 switch (result) {
2711 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002712 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002713 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002714 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002715 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002716
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002717 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002718 break;
2719
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002721 l2cap_build_conf_req(chan, req), req);
2722 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723 break;
2724
2725 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002726 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727 break;
2728
2729 default:
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002730 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731 break;
2732 }
2733
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002734 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735 return 0;
2736}
2737
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002738static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002739{
2740 /* FCS is enabled only in ERTM or streaming mode, if one or both
2741 * sides request it.
2742 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002743 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002744 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002745 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002746 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002747}
2748
Al Viro88219a02007-07-29 00:17:25 -07002749static 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 -07002750{
2751 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2752 u16 dcid, flags;
2753 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002754 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002756 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757
2758 dcid = __le16_to_cpu(req->dcid);
2759 flags = __le16_to_cpu(req->flags);
2760
2761 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2762
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002763 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002764 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 return -ENOENT;
2766
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002767 sk = chan->sk;
2768
David S. Miller033b1142011-07-21 13:38:42 -07002769 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002770 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002771
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002772 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2773 rej.scid = cpu_to_le16(chan->scid);
2774 rej.dcid = cpu_to_le16(chan->dcid);
2775
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002776 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2777 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002778 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002779 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002780
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002781 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002782 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002783 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002784 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002785 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002786 L2CAP_CONF_REJECT, flags), rsp);
2787 goto unlock;
2788 }
2789
2790 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002791 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2792 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793
2794 if (flags & 0x0001) {
2795 /* Incomplete config. Send empty response. */
2796 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002797 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002798 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799 goto unlock;
2800 }
2801
2802 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002803 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002804 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002805 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002807 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002809 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002810 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002811
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002812 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002813 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002814
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002815 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002816 goto unlock;
2817
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002818 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002819 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002820
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002821 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002822
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002823 chan->next_tx_seq = 0;
2824 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002825 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002826 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002827 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002828
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002830 goto unlock;
2831 }
2832
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002833 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002834 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002836 l2cap_build_conf_req(chan, buf), buf);
2837 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838 }
2839
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002840 /* Got Conf Rsp PENDING from remote side and asume we sent
2841 Conf Rsp PENDING in the code above */
2842 if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
2843 test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2844
2845 /* check compatibility */
2846
2847 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2848 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2849
2850 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002851 l2cap_build_conf_rsp(chan, rsp,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002852 L2CAP_CONF_SUCCESS, 0x0000), rsp);
2853 }
2854
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855unlock:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002856 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857 return 0;
2858}
2859
2860static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2861{
2862 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2863 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002864 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002866 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867
2868 scid = __le16_to_cpu(rsp->scid);
2869 flags = __le16_to_cpu(rsp->flags);
2870 result = __le16_to_cpu(rsp->result);
2871
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002872 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2873 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002875 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002876 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002877 return 0;
2878
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002879 sk = chan->sk;
2880
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881 switch (result) {
2882 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002883 l2cap_conf_rfc_get(chan, rsp->data, len);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002884 clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002885 break;
2886
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002887 case L2CAP_CONF_PENDING:
2888 set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
2889
2890 if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2891 char buf[64];
2892
2893 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2894 buf, &result);
2895 if (len < 0) {
2896 l2cap_send_disconn_req(conn, chan, ECONNRESET);
2897 goto done;
2898 }
2899
2900 /* check compatibility */
2901
2902 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2903 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2904
2905 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002906 l2cap_build_conf_rsp(chan, buf,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002907 L2CAP_CONF_SUCCESS, 0x0000), buf);
2908 }
2909 goto done;
2910
Linus Torvalds1da177e2005-04-16 15:20:36 -07002911 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002912 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002913 char req[64];
2914
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002915 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002916 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002917 goto done;
2918 }
2919
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002920 /* throw out any old stored conf requests */
2921 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002922 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2923 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002924 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002925 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002926 goto done;
2927 }
2928
2929 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2930 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002931 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002932 if (result != L2CAP_CONF_SUCCESS)
2933 goto done;
2934 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935 }
2936
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002937 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002938 sk->sk_err = ECONNRESET;
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02002939 __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002940 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002941 goto done;
2942 }
2943
2944 if (flags & 0x01)
2945 goto done;
2946
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002947 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002949 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002950 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002951
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002952 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002953 chan->next_tx_seq = 0;
2954 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002955 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002956 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002957 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002958
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959 l2cap_chan_ready(sk);
2960 }
2961
2962done:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002963 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964 return 0;
2965}
2966
2967static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2968{
2969 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2970 struct l2cap_disconn_rsp rsp;
2971 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002972 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973 struct sock *sk;
2974
2975 scid = __le16_to_cpu(req->scid);
2976 dcid = __le16_to_cpu(req->dcid);
2977
2978 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2979
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002980 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002981 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002982 return 0;
2983
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002984 sk = chan->sk;
2985
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002986 rsp.dcid = cpu_to_le16(chan->scid);
2987 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2989
2990 sk->sk_shutdown = SHUTDOWN_MASK;
2991
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002992 l2cap_chan_del(chan, ECONNRESET);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002993 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002995 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996 return 0;
2997}
2998
2999static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3000{
3001 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3002 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003003 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004 struct sock *sk;
3005
3006 scid = __le16_to_cpu(rsp->scid);
3007 dcid = __le16_to_cpu(rsp->dcid);
3008
3009 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3010
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003011 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003012 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013 return 0;
3014
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003015 sk = chan->sk;
3016
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003017 l2cap_chan_del(chan, 0);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003018 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003020 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021 return 0;
3022}
3023
3024static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3025{
3026 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027 u16 type;
3028
3029 type = __le16_to_cpu(req->type);
3030
3031 BT_DBG("type 0x%4.4x", type);
3032
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003033 if (type == L2CAP_IT_FEAT_MASK) {
3034 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003035 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003036 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3037 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3038 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003039 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003040 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3041 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003042 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003043 feat_mask |= L2CAP_FEAT_EXT_FLOW
3044 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003045
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003046 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003047 l2cap_send_cmd(conn, cmd->ident,
3048 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003049 } else if (type == L2CAP_IT_FIXED_CHAN) {
3050 u8 buf[12];
3051 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
Mat Martineau50a147c2011-11-02 16:18:34 -07003052
3053 if (enable_hs)
3054 l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
3055 else
3056 l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
3057
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003058 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3059 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003060 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003061 l2cap_send_cmd(conn, cmd->ident,
3062 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003063 } else {
3064 struct l2cap_info_rsp rsp;
3065 rsp.type = cpu_to_le16(type);
3066 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3067 l2cap_send_cmd(conn, cmd->ident,
3068 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3069 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070
3071 return 0;
3072}
3073
3074static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3075{
3076 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3077 u16 type, result;
3078
3079 type = __le16_to_cpu(rsp->type);
3080 result = __le16_to_cpu(rsp->result);
3081
3082 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3083
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003084 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3085 if (cmd->ident != conn->info_ident ||
3086 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3087 return 0;
3088
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003089 del_timer(&conn->info_timer);
3090
Ville Tervoadb08ed2010-08-04 09:43:33 +03003091 if (result != L2CAP_IR_SUCCESS) {
3092 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3093 conn->info_ident = 0;
3094
3095 l2cap_conn_start(conn);
3096
3097 return 0;
3098 }
3099
Marcel Holtmann984947d2009-02-06 23:35:19 +01003100 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003101 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003102
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003103 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003104 struct l2cap_info_req req;
3105 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3106
3107 conn->info_ident = l2cap_get_ident(conn);
3108
3109 l2cap_send_cmd(conn, conn->info_ident,
3110 L2CAP_INFO_REQ, sizeof(req), &req);
3111 } else {
3112 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3113 conn->info_ident = 0;
3114
3115 l2cap_conn_start(conn);
3116 }
3117 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003118 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003119 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003120
3121 l2cap_conn_start(conn);
3122 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003123
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124 return 0;
3125}
3126
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003127static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3128 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3129 void *data)
3130{
3131 struct l2cap_create_chan_req *req = data;
3132 struct l2cap_create_chan_rsp rsp;
3133 u16 psm, scid;
3134
3135 if (cmd_len != sizeof(*req))
3136 return -EPROTO;
3137
3138 if (!enable_hs)
3139 return -EINVAL;
3140
3141 psm = le16_to_cpu(req->psm);
3142 scid = le16_to_cpu(req->scid);
3143
3144 BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3145
3146 /* Placeholder: Always reject */
3147 rsp.dcid = 0;
3148 rsp.scid = cpu_to_le16(scid);
3149 rsp.result = L2CAP_CR_NO_MEM;
3150 rsp.status = L2CAP_CS_NO_INFO;
3151
3152 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3153 sizeof(rsp), &rsp);
3154
3155 return 0;
3156}
3157
3158static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3159 struct l2cap_cmd_hdr *cmd, void *data)
3160{
3161 BT_DBG("conn %p", conn);
3162
3163 return l2cap_connect_rsp(conn, cmd, data);
3164}
3165
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003166static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
3167 u16 icid, u16 result)
3168{
3169 struct l2cap_move_chan_rsp rsp;
3170
3171 BT_DBG("icid %d, result %d", icid, result);
3172
3173 rsp.icid = cpu_to_le16(icid);
3174 rsp.result = cpu_to_le16(result);
3175
3176 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
3177}
3178
3179static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
3180 struct l2cap_chan *chan, u16 icid, u16 result)
3181{
3182 struct l2cap_move_chan_cfm cfm;
3183 u8 ident;
3184
3185 BT_DBG("icid %d, result %d", icid, result);
3186
3187 ident = l2cap_get_ident(conn);
3188 if (chan)
3189 chan->ident = ident;
3190
3191 cfm.icid = cpu_to_le16(icid);
3192 cfm.result = cpu_to_le16(result);
3193
3194 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
3195}
3196
3197static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
3198 u16 icid)
3199{
3200 struct l2cap_move_chan_cfm_rsp rsp;
3201
3202 BT_DBG("icid %d", icid);
3203
3204 rsp.icid = cpu_to_le16(icid);
3205 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
3206}
3207
3208static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
3209 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3210{
3211 struct l2cap_move_chan_req *req = data;
3212 u16 icid = 0;
3213 u16 result = L2CAP_MR_NOT_ALLOWED;
3214
3215 if (cmd_len != sizeof(*req))
3216 return -EPROTO;
3217
3218 icid = le16_to_cpu(req->icid);
3219
3220 BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
3221
3222 if (!enable_hs)
3223 return -EINVAL;
3224
3225 /* Placeholder: Always refuse */
3226 l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
3227
3228 return 0;
3229}
3230
3231static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
3232 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3233{
3234 struct l2cap_move_chan_rsp *rsp = data;
3235 u16 icid, result;
3236
3237 if (cmd_len != sizeof(*rsp))
3238 return -EPROTO;
3239
3240 icid = le16_to_cpu(rsp->icid);
3241 result = le16_to_cpu(rsp->result);
3242
3243 BT_DBG("icid %d, result %d", icid, result);
3244
3245 /* Placeholder: Always unconfirmed */
3246 l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
3247
3248 return 0;
3249}
3250
3251static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
3252 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3253{
3254 struct l2cap_move_chan_cfm *cfm = data;
3255 u16 icid, result;
3256
3257 if (cmd_len != sizeof(*cfm))
3258 return -EPROTO;
3259
3260 icid = le16_to_cpu(cfm->icid);
3261 result = le16_to_cpu(cfm->result);
3262
3263 BT_DBG("icid %d, result %d", icid, result);
3264
3265 l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
3266
3267 return 0;
3268}
3269
3270static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
3271 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3272{
3273 struct l2cap_move_chan_cfm_rsp *rsp = data;
3274 u16 icid;
3275
3276 if (cmd_len != sizeof(*rsp))
3277 return -EPROTO;
3278
3279 icid = le16_to_cpu(rsp->icid);
3280
3281 BT_DBG("icid %d", icid);
3282
3283 return 0;
3284}
3285
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003286static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02003287 u16 to_multiplier)
3288{
3289 u16 max_latency;
3290
3291 if (min > max || min < 6 || max > 3200)
3292 return -EINVAL;
3293
3294 if (to_multiplier < 10 || to_multiplier > 3200)
3295 return -EINVAL;
3296
3297 if (max >= to_multiplier * 8)
3298 return -EINVAL;
3299
3300 max_latency = (to_multiplier * 8 / max) - 1;
3301 if (latency > 499 || latency > max_latency)
3302 return -EINVAL;
3303
3304 return 0;
3305}
3306
3307static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3308 struct l2cap_cmd_hdr *cmd, u8 *data)
3309{
3310 struct hci_conn *hcon = conn->hcon;
3311 struct l2cap_conn_param_update_req *req;
3312 struct l2cap_conn_param_update_rsp rsp;
3313 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003314 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02003315
3316 if (!(hcon->link_mode & HCI_LM_MASTER))
3317 return -EINVAL;
3318
3319 cmd_len = __le16_to_cpu(cmd->len);
3320 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3321 return -EPROTO;
3322
3323 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003324 min = __le16_to_cpu(req->min);
3325 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02003326 latency = __le16_to_cpu(req->latency);
3327 to_multiplier = __le16_to_cpu(req->to_multiplier);
3328
3329 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3330 min, max, latency, to_multiplier);
3331
3332 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003333
3334 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
3335 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02003336 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3337 else
3338 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3339
3340 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3341 sizeof(rsp), &rsp);
3342
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003343 if (!err)
3344 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
3345
Claudio Takahaside731152011-02-11 19:28:55 -02003346 return 0;
3347}
3348
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003349static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
3350 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
3351{
3352 int err = 0;
3353
3354 switch (cmd->code) {
3355 case L2CAP_COMMAND_REJ:
3356 l2cap_command_rej(conn, cmd, data);
3357 break;
3358
3359 case L2CAP_CONN_REQ:
3360 err = l2cap_connect_req(conn, cmd, data);
3361 break;
3362
3363 case L2CAP_CONN_RSP:
3364 err = l2cap_connect_rsp(conn, cmd, data);
3365 break;
3366
3367 case L2CAP_CONF_REQ:
3368 err = l2cap_config_req(conn, cmd, cmd_len, data);
3369 break;
3370
3371 case L2CAP_CONF_RSP:
3372 err = l2cap_config_rsp(conn, cmd, data);
3373 break;
3374
3375 case L2CAP_DISCONN_REQ:
3376 err = l2cap_disconnect_req(conn, cmd, data);
3377 break;
3378
3379 case L2CAP_DISCONN_RSP:
3380 err = l2cap_disconnect_rsp(conn, cmd, data);
3381 break;
3382
3383 case L2CAP_ECHO_REQ:
3384 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3385 break;
3386
3387 case L2CAP_ECHO_RSP:
3388 break;
3389
3390 case L2CAP_INFO_REQ:
3391 err = l2cap_information_req(conn, cmd, data);
3392 break;
3393
3394 case L2CAP_INFO_RSP:
3395 err = l2cap_information_rsp(conn, cmd, data);
3396 break;
3397
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003398 case L2CAP_CREATE_CHAN_REQ:
3399 err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3400 break;
3401
3402 case L2CAP_CREATE_CHAN_RSP:
3403 err = l2cap_create_channel_rsp(conn, cmd, data);
3404 break;
3405
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003406 case L2CAP_MOVE_CHAN_REQ:
3407 err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
3408 break;
3409
3410 case L2CAP_MOVE_CHAN_RSP:
3411 err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
3412 break;
3413
3414 case L2CAP_MOVE_CHAN_CFM:
3415 err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
3416 break;
3417
3418 case L2CAP_MOVE_CHAN_CFM_RSP:
3419 err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
3420 break;
3421
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003422 default:
3423 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3424 err = -EINVAL;
3425 break;
3426 }
3427
3428 return err;
3429}
3430
3431static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3432 struct l2cap_cmd_hdr *cmd, u8 *data)
3433{
3434 switch (cmd->code) {
3435 case L2CAP_COMMAND_REJ:
3436 return 0;
3437
3438 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003439 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003440
3441 case L2CAP_CONN_PARAM_UPDATE_RSP:
3442 return 0;
3443
3444 default:
3445 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3446 return -EINVAL;
3447 }
3448}
3449
3450static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3451 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003452{
3453 u8 *data = skb->data;
3454 int len = skb->len;
3455 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003456 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457
3458 l2cap_raw_recv(conn, skb);
3459
3460 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003461 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3463 data += L2CAP_CMD_HDR_SIZE;
3464 len -= L2CAP_CMD_HDR_SIZE;
3465
Al Viro88219a02007-07-29 00:17:25 -07003466 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467
Al Viro88219a02007-07-29 00:17:25 -07003468 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 -07003469
Al Viro88219a02007-07-29 00:17:25 -07003470 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003471 BT_DBG("corrupted command");
3472 break;
3473 }
3474
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003475 if (conn->hcon->type == LE_LINK)
3476 err = l2cap_le_sig_cmd(conn, &cmd, data);
3477 else
3478 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479
3480 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003481 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003482
3483 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484
3485 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003486 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3488 }
3489
Al Viro88219a02007-07-29 00:17:25 -07003490 data += cmd_len;
3491 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003492 }
3493
3494 kfree_skb(skb);
3495}
3496
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003497static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003498{
3499 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003500 int hdr_size;
3501
3502 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3503 hdr_size = L2CAP_EXT_HDR_SIZE;
3504 else
3505 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003506
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003507 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003508 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003509 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3510 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3511
3512 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003513 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003514 }
3515 return 0;
3516}
3517
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003518static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003519{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003520 u32 control = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003521
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003522 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003523
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003524 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003525
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003526 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003527 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003528 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003529 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003530 }
3531
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003532 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003533 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003534
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003535 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003536
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003537 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003538 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003539 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003540 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003541 }
3542}
3543
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003544static 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 -03003545{
3546 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003547 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003548
3549 bt_cb(skb)->tx_seq = tx_seq;
3550 bt_cb(skb)->sar = sar;
3551
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003552 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003553
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003554 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003555
Szymon Janc039d9572011-11-16 09:32:19 +01003556 while (next_skb) {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003557 if (bt_cb(next_skb)->tx_seq == tx_seq)
3558 return -EINVAL;
3559
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003560 next_tx_seq_offset = __seq_offset(chan,
3561 bt_cb(next_skb)->tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003562
3563 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003564 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003565 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003566 }
3567
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003568 if (skb_queue_is_last(&chan->srej_q, next_skb))
Szymon Janc039d9572011-11-16 09:32:19 +01003569 next_skb = NULL;
3570 else
3571 next_skb = skb_queue_next(&chan->srej_q, next_skb);
3572 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003573
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003574 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003575
3576 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003577}
3578
Mat Martineau84084a32011-07-22 14:54:00 -07003579static void append_skb_frag(struct sk_buff *skb,
3580 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003581{
Mat Martineau84084a32011-07-22 14:54:00 -07003582 /* skb->len reflects data in skb as well as all fragments
3583 * skb->data_len reflects only data in fragments
3584 */
3585 if (!skb_has_frag_list(skb))
3586 skb_shinfo(skb)->frag_list = new_frag;
3587
3588 new_frag->next = NULL;
3589
3590 (*last_frag)->next = new_frag;
3591 *last_frag = new_frag;
3592
3593 skb->len += new_frag->len;
3594 skb->data_len += new_frag->len;
3595 skb->truesize += new_frag->truesize;
3596}
3597
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003598static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
Mat Martineau84084a32011-07-22 14:54:00 -07003599{
3600 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003601
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003602 switch (__get_ctrl_sar(chan, control)) {
3603 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003604 if (chan->sdu)
3605 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003606
Mat Martineau84084a32011-07-22 14:54:00 -07003607 err = chan->ops->recv(chan->data, skb);
3608 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003609
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003610 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003611 if (chan->sdu)
3612 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003613
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003614 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003615 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003616
Mat Martineau84084a32011-07-22 14:54:00 -07003617 if (chan->sdu_len > chan->imtu) {
3618 err = -EMSGSIZE;
3619 break;
3620 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003621
Mat Martineau84084a32011-07-22 14:54:00 -07003622 if (skb->len >= chan->sdu_len)
3623 break;
3624
3625 chan->sdu = skb;
3626 chan->sdu_last_frag = skb;
3627
3628 skb = NULL;
3629 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003630 break;
3631
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003632 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003633 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003634 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003635
Mat Martineau84084a32011-07-22 14:54:00 -07003636 append_skb_frag(chan->sdu, skb,
3637 &chan->sdu_last_frag);
3638 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003639
Mat Martineau84084a32011-07-22 14:54:00 -07003640 if (chan->sdu->len >= chan->sdu_len)
3641 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003642
Mat Martineau84084a32011-07-22 14:54:00 -07003643 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003644 break;
3645
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003646 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003647 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003648 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003649
Mat Martineau84084a32011-07-22 14:54:00 -07003650 append_skb_frag(chan->sdu, skb,
3651 &chan->sdu_last_frag);
3652 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003653
Mat Martineau84084a32011-07-22 14:54:00 -07003654 if (chan->sdu->len != chan->sdu_len)
3655 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003656
Mat Martineau84084a32011-07-22 14:54:00 -07003657 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003658
Mat Martineau84084a32011-07-22 14:54:00 -07003659 if (!err) {
3660 /* Reassembly complete */
3661 chan->sdu = NULL;
3662 chan->sdu_last_frag = NULL;
3663 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003664 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003665 break;
3666 }
3667
Mat Martineau84084a32011-07-22 14:54:00 -07003668 if (err) {
3669 kfree_skb(skb);
3670 kfree_skb(chan->sdu);
3671 chan->sdu = NULL;
3672 chan->sdu_last_frag = NULL;
3673 chan->sdu_len = 0;
3674 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003675
Mat Martineau84084a32011-07-22 14:54:00 -07003676 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003677}
3678
Mat Martineau26f880d2011-07-07 09:39:01 -07003679static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003680{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003681 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003682
Mat Martineau26f880d2011-07-07 09:39:01 -07003683 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003684
Mat Martineau26f880d2011-07-07 09:39:01 -07003685 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3686
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003687 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003688 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Mat Martineau26f880d2011-07-07 09:39:01 -07003689 l2cap_send_sframe(chan, control);
3690
3691 set_bit(CONN_RNR_SENT, &chan->conn_state);
3692
3693 __clear_ack_timer(chan);
3694}
3695
3696static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3697{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003698 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003699
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003700 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003701 goto done;
3702
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003703 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003704 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003705 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003706 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003707 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003708
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003709 __clear_retrans_timer(chan);
3710 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003711
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003712 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003713
3714done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003715 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3716 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003717
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003718 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003719}
3720
Mat Martineaue3281402011-07-07 09:39:02 -07003721void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003722{
Mat Martineaue3281402011-07-07 09:39:02 -07003723 if (chan->mode == L2CAP_MODE_ERTM) {
3724 if (busy)
3725 l2cap_ertm_enter_local_busy(chan);
3726 else
3727 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003728 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003729}
3730
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003731static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003732{
3733 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003734 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003735
Mat Martineaue3281402011-07-07 09:39:02 -07003736 while ((skb = skb_peek(&chan->srej_q)) &&
3737 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3738 int err;
3739
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003740 if (bt_cb(skb)->tx_seq != tx_seq)
3741 break;
3742
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003743 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003744 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003745 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003746
3747 if (err < 0) {
3748 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3749 break;
3750 }
3751
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003752 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
3753 tx_seq = __next_seq(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003754 }
3755}
3756
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003757static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003758{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003759 struct srej_list *l, *tmp;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003760 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003761
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003762 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003763 if (l->tx_seq == tx_seq) {
3764 list_del(&l->list);
3765 kfree(l);
3766 return;
3767 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003768 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003769 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003770 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003771 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003772 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003773 }
3774}
3775
Szymon Jancaef89f22011-11-16 09:32:18 +01003776static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003777{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003778 struct srej_list *new;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003779 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003780
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003781 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003782 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003783 control |= __set_reqseq(chan, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003784 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003785
3786 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Szymon Jancaef89f22011-11-16 09:32:18 +01003787 if (!new)
3788 return -ENOMEM;
3789
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003790 new->tx_seq = chan->expected_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003791
3792 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
3793
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003794 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003795 }
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003796
3797 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Szymon Jancaef89f22011-11-16 09:32:18 +01003798
3799 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003800}
3801
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003802static 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 -03003803{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003804 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003805 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003806 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003807 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003808 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003809 int err = 0;
3810
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003811 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 -03003812 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003813
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003814 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003815 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003816 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003817 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003818 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003819 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003820 }
3821
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003822 chan->expected_ack_seq = req_seq;
3823 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003824
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003825 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003826
3827 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003828 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003829 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003830 goto drop;
3831 }
3832
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003833 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003834 goto drop;
3835
Mat Martineau02f1b642011-06-29 14:35:19 -07003836 if (tx_seq == chan->expected_tx_seq)
3837 goto expected;
3838
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003839 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003840 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003841
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003842 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003843 struct srej_list, list);
3844 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003845 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003846 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003847
3848 list_del(&first->list);
3849 kfree(first);
3850
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003851 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003852 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003853 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003854 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003855 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003856 }
3857 } else {
3858 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003859
3860 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003861 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003862 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003863
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003864 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003865 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003866 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003867 return 0;
3868 }
3869 }
Szymon Jancaef89f22011-11-16 09:32:18 +01003870
3871 err = l2cap_send_srejframe(chan, tx_seq);
3872 if (err < 0) {
3873 l2cap_send_disconn_req(chan->conn, chan, -err);
3874 return err;
3875 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003876 }
3877 } else {
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003878 expected_tx_seq_offset = __seq_offset(chan,
3879 chan->expected_tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003880
3881 /* duplicated tx_seq */
3882 if (tx_seq_offset < expected_tx_seq_offset)
3883 goto drop;
3884
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003885 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003886
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003887 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003888
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003889 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003890 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003891
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003892 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003893 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003894
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003895 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003896
Szymon Jancaef89f22011-11-16 09:32:18 +01003897 err = l2cap_send_srejframe(chan, tx_seq);
3898 if (err < 0) {
3899 l2cap_send_disconn_req(chan->conn, chan, -err);
3900 return err;
3901 }
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003902
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003903 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003904 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003905 return 0;
3906
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003907expected:
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003908 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003909
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003910 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003911 bt_cb(skb)->tx_seq = tx_seq;
3912 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003913 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003914 return 0;
3915 }
3916
Mat Martineau84084a32011-07-22 14:54:00 -07003917 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003918 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
3919
Mat Martineaue3281402011-07-07 09:39:02 -07003920 if (err < 0) {
3921 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3922 return err;
3923 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003924
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003925 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003926 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003927 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003928 }
3929
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003930
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003931 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3932 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003933 l2cap_send_ack(chan);
Gustavo F. Padovan4d611e42011-06-23 19:30:48 -03003934 else
3935 __set_ack_timer(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003936
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003937 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003938
3939drop:
3940 kfree_skb(skb);
3941 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003942}
3943
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003944static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003945{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003946 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003947 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003948
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003949 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003950 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003951
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003952 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003953 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3954 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3955 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003956 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003957 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003958
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003959 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003960 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003961 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003962 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003963 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003964
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003965 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003966 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003967
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003968 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003969 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003970
3971 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003972 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003973 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003974 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003975
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003976 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3977 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003978 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003979 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003980 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003981 }
3982}
3983
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003984static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003985{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003986 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003987
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003988 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003989
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003990 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003991
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003992 chan->expected_ack_seq = tx_seq;
3993 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003994
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003995 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003996 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003997 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003998 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003999 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004000
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004001 if (test_bit(CONN_WAIT_F, &chan->conn_state))
4002 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004003 }
4004}
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004005static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004006{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004007 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004008
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004009 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004010
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004011 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004012
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004013 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004014 chan->expected_ack_seq = tx_seq;
4015 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004016
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004017 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004018 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004019
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004020 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004021
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004022 if (test_bit(CONN_WAIT_F, &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 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004025 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004026 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004027 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004028 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004029 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004030 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004031 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004032 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004033 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004034 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004035 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004036 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004037 }
4038 }
4039}
4040
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004041static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004042{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004043 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004044
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004045 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004046
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004047 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004048 chan->expected_ack_seq = tx_seq;
4049 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004050
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004051 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004052 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004053
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004054 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004055 __clear_retrans_timer(chan);
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_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004058 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004059 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004060
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004061 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004062 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004063 } else {
4064 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4065 l2cap_send_sframe(chan, rx_control);
4066 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004067}
4068
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004069static 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 -03004070{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004071 BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004072
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004073 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004074 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004075 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004076 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004077 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004078 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004079 }
4080
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004081 switch (__get_ctrl_super(chan, rx_control)) {
4082 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004083 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004084 break;
4085
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004086 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004087 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004088 break;
4089
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004090 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004091 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004092 break;
4093
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004094 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004095 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004096 break;
4097 }
4098
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004099 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004100 return 0;
4101}
4102
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004103static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
4104{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004105 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004106 u32 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004107 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004108 int len, next_tx_seq_offset, req_seq_offset;
4109
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004110 control = __get_control(chan, skb->data);
4111 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004112 len = skb->len;
4113
4114 /*
4115 * We can just drop the corrupted I-frame here.
4116 * Receiver will miss it and start proper recovery
4117 * procedures and ask retransmission.
4118 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004119 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004120 goto drop;
4121
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004122 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004123 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004124
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004125 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004126 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004127
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004128 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004129 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004130 goto drop;
4131 }
4132
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004133 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004134
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004135 req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4136
4137 next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4138 chan->expected_ack_seq);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004139
4140 /* check for invalid req-seq */
4141 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004142 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004143 goto drop;
4144 }
4145
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004146 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004147 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004148 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004149 goto drop;
4150 }
4151
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004152 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004153 } else {
4154 if (len != 0) {
4155 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004156 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004157 goto drop;
4158 }
4159
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004160 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004161 }
4162
4163 return 0;
4164
4165drop:
4166 kfree_skb(skb);
4167 return 0;
4168}
4169
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4171{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004172 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07004173 struct sock *sk = NULL;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004174 u32 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004175 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004176 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004178 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004179 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004180 BT_DBG("unknown cid 0x%4.4x", cid);
4181 goto drop;
4182 }
4183
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004184 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004185
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004186 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004187
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004188 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189 goto drop;
4190
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004191 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004192 case L2CAP_MODE_BASIC:
4193 /* If socket recv buffers overflows we drop data here
4194 * which is *bad* because L2CAP has to be reliable.
4195 * But we don't have any other choice. L2CAP doesn't
4196 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004197
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004198 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004199 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004200
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004201 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004202 goto done;
4203 break;
4204
4205 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004206 if (!sock_owned_by_user(sk)) {
4207 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004208 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004209 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004210 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004211 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004212
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004213 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004214
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004215 case L2CAP_MODE_STREAMING:
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004216 control = __get_control(chan, skb->data);
4217 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004218 len = skb->len;
4219
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004220 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004221 goto drop;
4222
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004223 if (__is_sar_start(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004224 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004225
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004226 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004227 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004228
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004229 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004230 goto drop;
4231
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004232 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004233
Mat Martineau84084a32011-07-22 14:54:00 -07004234 if (chan->expected_tx_seq != tx_seq) {
4235 /* Frame(s) missing - must discard partial SDU */
4236 kfree_skb(chan->sdu);
4237 chan->sdu = NULL;
4238 chan->sdu_last_frag = NULL;
4239 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004240
Mat Martineau84084a32011-07-22 14:54:00 -07004241 /* TODO: Notify userland of missing data */
4242 }
4243
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004244 chan->expected_tx_seq = __next_seq(chan, tx_seq);
Mat Martineau84084a32011-07-22 14:54:00 -07004245
4246 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
4247 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004248
4249 goto done;
4250
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004251 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004252 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004253 break;
4254 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004255
4256drop:
4257 kfree_skb(skb);
4258
4259done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004260 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004261 release_sock(sk);
Marcel Holtmann01394182006-07-03 10:02:46 +02004262
Linus Torvalds1da177e2005-04-16 15:20:36 -07004263 return 0;
4264}
4265
Al Viro8e036fc2007-07-29 00:16:36 -07004266static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004268 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004269 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004270
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004271 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
4272 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273 goto drop;
4274
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004275 sk = chan->sk;
4276
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004277 lock_sock(sk);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00004278
Linus Torvalds1da177e2005-04-16 15:20:36 -07004279 BT_DBG("sk %p, len %d", sk, skb->len);
4280
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004281 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282 goto drop;
4283
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004284 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004285 goto drop;
4286
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004287 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288 goto done;
4289
4290drop:
4291 kfree_skb(skb);
4292
4293done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004294 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004295 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004296 return 0;
4297}
4298
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004299static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
4300{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004301 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004302 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004303
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004304 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
4305 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004306 goto drop;
4307
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004308 sk = chan->sk;
4309
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004310 lock_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004311
4312 BT_DBG("sk %p, len %d", sk, skb->len);
4313
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004314 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004315 goto drop;
4316
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004317 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004318 goto drop;
4319
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004320 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004321 goto done;
4322
4323drop:
4324 kfree_skb(skb);
4325
4326done:
4327 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004328 release_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004329 return 0;
4330}
4331
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4333{
4334 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004335 u16 cid, len;
4336 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337
4338 skb_pull(skb, L2CAP_HDR_SIZE);
4339 cid = __le16_to_cpu(lh->cid);
4340 len = __le16_to_cpu(lh->len);
4341
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004342 if (len != skb->len) {
4343 kfree_skb(skb);
4344 return;
4345 }
4346
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4348
4349 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004350 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004351 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352 l2cap_sig_channel(conn, skb);
4353 break;
4354
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004355 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004356 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357 skb_pull(skb, 2);
4358 l2cap_conless_channel(conn, psm, skb);
4359 break;
4360
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004361 case L2CAP_CID_LE_DATA:
4362 l2cap_att_channel(conn, cid, skb);
4363 break;
4364
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004365 case L2CAP_CID_SMP:
4366 if (smp_sig_channel(conn, skb))
4367 l2cap_conn_del(conn->hcon, EACCES);
4368 break;
4369
Linus Torvalds1da177e2005-04-16 15:20:36 -07004370 default:
4371 l2cap_data_channel(conn, cid, skb);
4372 break;
4373 }
4374}
4375
4376/* ---- L2CAP interface with lower layer (HCI) ---- */
4377
4378static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4379{
4380 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004381 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382
4383 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004384 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385
4386 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4387
4388 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004389 read_lock(&chan_list_lock);
4390 list_for_each_entry(c, &chan_list, global_l) {
4391 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004392
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004393 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394 continue;
4395
4396 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004397 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004398 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004399 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004400 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004401 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4402 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004403 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004404 lm2 |= HCI_LM_MASTER;
4405 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004407 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004408
4409 return exact ? lm1 : lm2;
4410}
4411
4412static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4413{
Marcel Holtmann01394182006-07-03 10:02:46 +02004414 struct l2cap_conn *conn;
4415
Linus Torvalds1da177e2005-04-16 15:20:36 -07004416 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4417
Ville Tervoacd7d372011-02-10 22:38:49 -03004418 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004419 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420
4421 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422 conn = l2cap_conn_add(hcon, status);
4423 if (conn)
4424 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004425 } else
Joe Perchese1750722011-06-29 18:18:29 -07004426 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427
4428 return 0;
4429}
4430
Marcel Holtmann2950f212009-02-12 14:02:50 +01004431static int l2cap_disconn_ind(struct hci_conn *hcon)
4432{
4433 struct l2cap_conn *conn = hcon->l2cap_data;
4434
4435 BT_DBG("hcon %p", hcon);
4436
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03004437 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02004438 return HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01004439
4440 return conn->disc_reason;
4441}
4442
4443static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444{
4445 BT_DBG("hcon %p reason %d", hcon, reason);
4446
Ville Tervoacd7d372011-02-10 22:38:49 -03004447 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004448 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004449
Joe Perchese1750722011-06-29 18:18:29 -07004450 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004451
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452 return 0;
4453}
4454
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004455static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004456{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004457 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004458 return;
4459
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004460 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004461 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004462 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02004463 __set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004464 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004465 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004466 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004467 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004468 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004469 }
4470}
4471
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004472static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004473{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004474 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004475 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004476
Marcel Holtmann01394182006-07-03 10:02:46 +02004477 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004478 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004479
Linus Torvalds1da177e2005-04-16 15:20:36 -07004480 BT_DBG("conn %p", conn);
4481
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004482 if (hcon->type == LE_LINK) {
4483 smp_distribute_keys(conn, 0);
4484 del_timer(&conn->security_timer);
4485 }
4486
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004487 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004488
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004489 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004490 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004491
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492 bh_lock_sock(sk);
4493
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004494 BT_DBG("chan->scid %d", chan->scid);
4495
4496 if (chan->scid == L2CAP_CID_LE_DATA) {
4497 if (!status && encrypt) {
4498 chan->sec_level = hcon->sec_level;
4499 l2cap_chan_ready(sk);
4500 }
4501
4502 bh_unlock_sock(sk);
4503 continue;
4504 }
4505
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004506 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004507 bh_unlock_sock(sk);
4508 continue;
4509 }
4510
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004511 if (!status && (chan->state == BT_CONNECTED ||
4512 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004513 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004514 bh_unlock_sock(sk);
4515 continue;
4516 }
4517
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004518 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004519 if (!status) {
4520 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004521 req.scid = cpu_to_le16(chan->scid);
4522 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004523
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004524 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004525 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004526
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004527 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004528 L2CAP_CONN_REQ, sizeof(req), &req);
4529 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004530 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02004531 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004532 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004533 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004534 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004535 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004536
4537 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004538 if (bt_sk(sk)->defer_setup) {
4539 struct sock *parent = bt_sk(sk)->parent;
4540 res = L2CAP_CR_PEND;
4541 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004542 if (parent)
4543 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004544 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004545 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004546 res = L2CAP_CR_SUCCESS;
4547 stat = L2CAP_CS_NO_INFO;
4548 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004549 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004550 l2cap_state_change(chan, BT_DISCONN);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02004551 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004552 res = L2CAP_CR_SEC_BLOCK;
4553 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004554 }
4555
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004556 rsp.scid = cpu_to_le16(chan->dcid);
4557 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004558 rsp.result = cpu_to_le16(res);
4559 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004560 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4561 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004562 }
4563
Linus Torvalds1da177e2005-04-16 15:20:36 -07004564 bh_unlock_sock(sk);
4565 }
4566
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004567 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004568
Linus Torvalds1da177e2005-04-16 15:20:36 -07004569 return 0;
4570}
4571
4572static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4573{
4574 struct l2cap_conn *conn = hcon->l2cap_data;
4575
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004576 if (!conn)
4577 conn = l2cap_conn_add(hcon, 0);
4578
4579 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004580 goto drop;
4581
4582 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4583
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004584 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004585 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004586 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004587 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004588 int len;
4589
4590 if (conn->rx_len) {
4591 BT_ERR("Unexpected start frame (len %d)", skb->len);
4592 kfree_skb(conn->rx_skb);
4593 conn->rx_skb = NULL;
4594 conn->rx_len = 0;
4595 l2cap_conn_unreliable(conn, ECOMM);
4596 }
4597
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004598 /* Start fragment always begin with Basic L2CAP header */
4599 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004600 BT_ERR("Frame is too short (len %d)", skb->len);
4601 l2cap_conn_unreliable(conn, ECOMM);
4602 goto drop;
4603 }
4604
4605 hdr = (struct l2cap_hdr *) skb->data;
4606 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004607 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004608
4609 if (len == skb->len) {
4610 /* Complete frame received */
4611 l2cap_recv_frame(conn, skb);
4612 return 0;
4613 }
4614
4615 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4616
4617 if (skb->len > len) {
4618 BT_ERR("Frame is too long (len %d, expected len %d)",
4619 skb->len, len);
4620 l2cap_conn_unreliable(conn, ECOMM);
4621 goto drop;
4622 }
4623
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004624 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004625
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004626 if (chan && chan->sk) {
4627 struct sock *sk = chan->sk;
4628
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004629 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004630 BT_ERR("Frame exceeding recv MTU (len %d, "
4631 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004632 chan->imtu);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004633 release_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004634 l2cap_conn_unreliable(conn, ECOMM);
4635 goto drop;
4636 }
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004637 release_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004638 }
4639
Linus Torvalds1da177e2005-04-16 15:20:36 -07004640 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004641 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4642 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004643 goto drop;
4644
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004645 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004646 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004647 conn->rx_len = len - skb->len;
4648 } else {
4649 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4650
4651 if (!conn->rx_len) {
4652 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4653 l2cap_conn_unreliable(conn, ECOMM);
4654 goto drop;
4655 }
4656
4657 if (skb->len > conn->rx_len) {
4658 BT_ERR("Fragment is too long (len %d, expected %d)",
4659 skb->len, conn->rx_len);
4660 kfree_skb(conn->rx_skb);
4661 conn->rx_skb = NULL;
4662 conn->rx_len = 0;
4663 l2cap_conn_unreliable(conn, ECOMM);
4664 goto drop;
4665 }
4666
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004667 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004668 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004669 conn->rx_len -= skb->len;
4670
4671 if (!conn->rx_len) {
4672 /* Complete frame received */
4673 l2cap_recv_frame(conn, conn->rx_skb);
4674 conn->rx_skb = NULL;
4675 }
4676 }
4677
4678drop:
4679 kfree_skb(skb);
4680 return 0;
4681}
4682
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004683static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004684{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004685 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004686
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004687 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004688
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004689 list_for_each_entry(c, &chan_list, global_l) {
4690 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004691
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004692 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 +01004693 batostr(&bt_sk(sk)->src),
4694 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004695 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004696 c->scid, c->dcid, c->imtu, c->omtu,
4697 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004698}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004699
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004700 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004701
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004702 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004703}
4704
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004705static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4706{
4707 return single_open(file, l2cap_debugfs_show, inode->i_private);
4708}
4709
4710static const struct file_operations l2cap_debugfs_fops = {
4711 .open = l2cap_debugfs_open,
4712 .read = seq_read,
4713 .llseek = seq_lseek,
4714 .release = single_release,
4715};
4716
4717static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004718
Linus Torvalds1da177e2005-04-16 15:20:36 -07004719static struct hci_proto l2cap_hci_proto = {
4720 .name = "L2CAP",
4721 .id = HCI_PROTO_L2CAP,
4722 .connect_ind = l2cap_connect_ind,
4723 .connect_cfm = l2cap_connect_cfm,
4724 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004725 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004726 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004727 .recv_acldata = l2cap_recv_acldata
4728};
4729
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004730int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004731{
4732 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004733
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004734 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004735 if (err < 0)
4736 return err;
4737
Linus Torvalds1da177e2005-04-16 15:20:36 -07004738 err = hci_register_proto(&l2cap_hci_proto);
4739 if (err < 0) {
4740 BT_ERR("L2CAP protocol registration failed");
4741 bt_sock_unregister(BTPROTO_L2CAP);
4742 goto error;
4743 }
4744
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004745 if (bt_debugfs) {
4746 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4747 bt_debugfs, NULL, &l2cap_debugfs_fops);
4748 if (!l2cap_debugfs)
4749 BT_ERR("Failed to create L2CAP debug file");
4750 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004751
Linus Torvalds1da177e2005-04-16 15:20:36 -07004752 return 0;
4753
4754error:
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004755 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004756 return err;
4757}
4758
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004759void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004760{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004761 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004762
Linus Torvalds1da177e2005-04-16 15:20:36 -07004763 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4764 BT_ERR("L2CAP protocol unregistration failed");
4765
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004766 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004767}
4768
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004769module_param(disable_ertm, bool, 0644);
4770MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");