blob: 276817a90f596ffbdb3c79bd22b8122850a5b70c [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;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +030060int enable_hs;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020061
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070062static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Mat Martineau50a147c2011-11-02 16:18:34 -070063static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Johannes Bergb5ad8b72011-06-01 08:54:45 +020065static LIST_HEAD(chan_list);
66static DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Linus Torvalds1da177e2005-04-16 15:20:36 -070068static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
69 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030070static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
71 void *data);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -030072static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030073static void l2cap_send_disconn_req(struct l2cap_conn *conn,
74 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030076static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
77
Marcel Holtmann01394182006-07-03 10:02:46 +020078/* ---- L2CAP channels ---- */
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -030079
80static inline void chan_hold(struct l2cap_chan *c)
81{
82 atomic_inc(&c->refcnt);
83}
84
85static inline void chan_put(struct l2cap_chan *c)
86{
87 if (atomic_dec_and_test(&c->refcnt))
88 kfree(c);
89}
90
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030091static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020092{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030093 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030094
95 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030096 if (c->dcid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030097 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020098 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030099 return NULL;
100
Marcel Holtmann01394182006-07-03 10:02:46 +0200101}
102
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300103static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200104{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300105 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300106
107 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300108 if (c->scid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300109 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200110 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300111 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200112}
113
114/* Find channel with given SCID.
115 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300116static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200117{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300118 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300119
120 read_lock(&conn->chan_lock);
121 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300122 if (c)
123 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300124 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300125 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200126}
127
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300128static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200129{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300130 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300131
132 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300133 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300134 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200135 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300136 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200137}
138
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300139static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200140{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300141 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300142
143 read_lock(&conn->chan_lock);
144 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300145 if (c)
146 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300147 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300148 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200149}
150
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300151static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300152{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300153 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300154
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300155 list_for_each_entry(c, &chan_list, global_l) {
156 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300157 goto found;
158 }
159
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300160 c = NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300161found:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300162 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300163}
164
165int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
166{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300167 int err;
168
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300169 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300170
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300171 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300172 err = -EADDRINUSE;
173 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300174 }
175
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300176 if (psm) {
177 chan->psm = psm;
178 chan->sport = psm;
179 err = 0;
180 } else {
181 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300182
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300183 err = -EINVAL;
184 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300185 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300186 chan->psm = cpu_to_le16(p);
187 chan->sport = cpu_to_le16(p);
188 err = 0;
189 break;
190 }
191 }
192
193done:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300194 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300195 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300196}
197
198int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
199{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300200 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300201
202 chan->scid = scid;
203
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300204 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300205
206 return 0;
207}
208
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300209static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200210{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300211 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200212
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300213 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300214 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200215 return cid;
216 }
217
218 return 0;
219}
220
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300221static void l2cap_set_timer(struct l2cap_chan *chan, struct timer_list *timer, long timeout)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300222{
Andrei Emeltchenko457f4852011-10-31 16:17:21 +0200223 BT_DBG("chan %p state %d timeout %ld", chan, chan->state, timeout);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300224
Mat Martineau942ecc92011-06-29 14:35:21 -0700225 if (!mod_timer(timer, jiffies + msecs_to_jiffies(timeout)))
Mat Martineau774e5652011-06-29 14:35:20 -0700226 chan_hold(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300227}
228
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300229static void l2cap_clear_timer(struct l2cap_chan *chan, struct timer_list *timer)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300230{
Mat Martineau774e5652011-06-29 14:35:20 -0700231 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300232
Mat Martineau774e5652011-06-29 14:35:20 -0700233 if (timer_pending(timer) && del_timer(timer))
234 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300235}
236
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300237static void l2cap_state_change(struct l2cap_chan *chan, int state)
238{
239 chan->state = state;
240 chan->ops->state_change(chan->data, state);
241}
242
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300243static void l2cap_chan_timeout(unsigned long arg)
244{
245 struct l2cap_chan *chan = (struct l2cap_chan *) arg;
246 struct sock *sk = chan->sk;
247 int reason;
248
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300249 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300250
251 bh_lock_sock(sk);
252
253 if (sock_owned_by_user(sk)) {
254 /* sk is owned by user. Try again later */
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -0200255 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300256 bh_unlock_sock(sk);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300257 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300258 return;
259 }
260
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300261 if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300262 reason = ECONNREFUSED;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300263 else if (chan->state == BT_CONNECT &&
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300264 chan->sec_level != BT_SECURITY_SDP)
265 reason = ECONNREFUSED;
266 else
267 reason = ETIMEDOUT;
268
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300269 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300270
271 bh_unlock_sock(sk);
272
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300273 chan->ops->close(chan->data);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300274 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300275}
276
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300277struct l2cap_chan *l2cap_chan_create(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200278{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300279 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200280
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300281 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
282 if (!chan)
283 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200284
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300285 chan->sk = sk;
286
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300287 write_lock_bh(&chan_list_lock);
288 list_add(&chan->global_l, &chan_list);
289 write_unlock_bh(&chan_list_lock);
290
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300291 setup_timer(&chan->chan_timer, l2cap_chan_timeout, (unsigned long) chan);
292
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300293 chan->state = BT_OPEN;
294
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300295 atomic_set(&chan->refcnt, 1);
296
Szymon Jancabc545b2011-11-03 16:05:44 +0100297 BT_DBG("sk %p chan %p", sk, chan);
298
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300299 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200300}
301
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300302void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300303{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300304 write_lock_bh(&chan_list_lock);
305 list_del(&chan->global_l);
306 write_unlock_bh(&chan_list_lock);
307
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300308 chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300309}
310
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300311static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200312{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300313 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300314 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200315
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +0200316 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +0100317
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300318 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200319
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300320 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
Ville Tervob62f3282011-02-10 22:38:50 -0300321 if (conn->hcon->type == LE_LINK) {
322 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300323 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300324 chan->scid = L2CAP_CID_LE_DATA;
325 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300326 } else {
327 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300328 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300329 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300330 }
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300331 } else if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200332 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300333 chan->scid = L2CAP_CID_CONN_LESS;
334 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300335 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200336 } else {
337 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300338 chan->scid = L2CAP_CID_SIGNALING;
339 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300340 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200341 }
342
Andrei Emeltchenko8f7975b2011-10-13 16:18:54 +0300343 chan->local_id = L2CAP_BESTEFFORT_ID;
344 chan->local_stype = L2CAP_SERV_BESTEFFORT;
345 chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
346 chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
347 chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
348 chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
349
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300350 chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300351
352 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200353}
354
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900355/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200356 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300357static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200358{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300359 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300360 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200361 struct sock *parent = bt_sk(sk)->parent;
362
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300363 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200364
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300365 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200366
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900367 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300368 /* Delete from channel list */
369 write_lock_bh(&conn->chan_lock);
370 list_del(&chan->list);
371 write_unlock_bh(&conn->chan_lock);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300372 chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300373
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300374 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200375 hci_conn_put(conn->hcon);
376 }
377
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300378 l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200379 sock_set_flag(sk, SOCK_ZAPPED);
380
381 if (err)
382 sk->sk_err = err;
383
384 if (parent) {
385 bt_accept_unlink(sk);
386 parent->sk_data_ready(parent, 0);
387 } else
388 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300389
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300390 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
391 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300392 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300393
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300394 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300395
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300396 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300397 struct srej_list *l, *tmp;
398
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300399 __clear_retrans_timer(chan);
400 __clear_monitor_timer(chan);
401 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300402
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300403 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300404
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300405 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300406 list_del(&l->list);
407 kfree(l);
408 }
409 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200410}
411
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300412static void l2cap_chan_cleanup_listen(struct sock *parent)
413{
414 struct sock *sk;
415
416 BT_DBG("parent %p", parent);
417
418 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300419 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300420 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300421 __clear_chan_timer(chan);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300422 lock_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300423 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300424 release_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300425 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300426 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300427}
428
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300429void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300430{
431 struct l2cap_conn *conn = chan->conn;
432 struct sock *sk = chan->sk;
433
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300434 BT_DBG("chan %p state %d socket %p", chan, chan->state, sk->sk_socket);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300435
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300436 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300437 case BT_LISTEN:
438 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300439
440 l2cap_state_change(chan, BT_CLOSED);
441 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300442 break;
443
444 case BT_CONNECTED:
445 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300446 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300447 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300448 __clear_chan_timer(chan);
449 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300450 l2cap_send_disconn_req(conn, chan, reason);
451 } else
452 l2cap_chan_del(chan, reason);
453 break;
454
455 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300456 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300457 conn->hcon->type == ACL_LINK) {
458 struct l2cap_conn_rsp rsp;
459 __u16 result;
460
461 if (bt_sk(sk)->defer_setup)
462 result = L2CAP_CR_SEC_BLOCK;
463 else
464 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300465 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300466
467 rsp.scid = cpu_to_le16(chan->dcid);
468 rsp.dcid = cpu_to_le16(chan->scid);
469 rsp.result = cpu_to_le16(result);
470 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
471 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
472 sizeof(rsp), &rsp);
473 }
474
475 l2cap_chan_del(chan, reason);
476 break;
477
478 case BT_CONNECT:
479 case BT_DISCONN:
480 l2cap_chan_del(chan, reason);
481 break;
482
483 default:
484 sock_set_flag(sk, SOCK_ZAPPED);
485 break;
486 }
487}
488
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300489static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530490{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300491 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300492 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530493 case BT_SECURITY_HIGH:
494 return HCI_AT_DEDICATED_BONDING_MITM;
495 case BT_SECURITY_MEDIUM:
496 return HCI_AT_DEDICATED_BONDING;
497 default:
498 return HCI_AT_NO_BONDING;
499 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300500 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300501 if (chan->sec_level == BT_SECURITY_LOW)
502 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530503
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300504 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530505 return HCI_AT_NO_BONDING_MITM;
506 else
507 return HCI_AT_NO_BONDING;
508 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300509 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530510 case BT_SECURITY_HIGH:
511 return HCI_AT_GENERAL_BONDING_MITM;
512 case BT_SECURITY_MEDIUM:
513 return HCI_AT_GENERAL_BONDING;
514 default:
515 return HCI_AT_NO_BONDING;
516 }
517 }
518}
519
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200520/* Service level security */
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200521int l2cap_chan_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200522{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300523 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100524 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200525
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300526 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100527
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300528 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200529}
530
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200531static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200532{
533 u8 id;
534
535 /* Get next available identificator.
536 * 1 - 128 are used by kernel.
537 * 129 - 199 are reserved.
538 * 200 - 254 are used by utilities like l2ping, etc.
539 */
540
541 spin_lock_bh(&conn->lock);
542
543 if (++conn->tx_ident > 128)
544 conn->tx_ident = 1;
545
546 id = conn->tx_ident;
547
548 spin_unlock_bh(&conn->lock);
549
550 return id;
551}
552
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300553static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200554{
555 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200556 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200557
558 BT_DBG("code 0x%2.2x", code);
559
560 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300561 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200562
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200563 if (lmp_no_flush_capable(conn->hcon->hdev))
564 flags = ACL_START_NO_FLUSH;
565 else
566 flags = ACL_START;
567
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700568 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +0200569 skb->priority = HCI_PRIO_MAX;
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700570
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200571 hci_send_acl(conn->hchan, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200572}
573
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200574static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
575{
576 struct hci_conn *hcon = chan->conn->hcon;
577 u16 flags;
578
579 BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
580 skb->priority);
581
582 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
583 lmp_no_flush_capable(hcon->hdev))
584 flags = ACL_START_NO_FLUSH;
585 else
586 flags = ACL_START;
587
588 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
589 hci_send_acl(chan->conn->hchan, skb, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590}
591
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300592static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300593{
594 struct sk_buff *skb;
595 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300596 struct l2cap_conn *conn = chan->conn;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300597 int count, hlen;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300598
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300599 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300600 return;
601
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300602 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
603 hlen = L2CAP_EXT_HDR_SIZE;
604 else
605 hlen = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300606
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300607 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300608 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300609
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300610 BT_DBG("chan %p, control 0x%8.8x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300611
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300612 count = min_t(unsigned int, conn->mtu, hlen);
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +0300613
614 control |= __set_sframe(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300615
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300616 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +0300617 control |= __set_ctrl_final(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300618
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300619 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +0300620 control |= __set_ctrl_poll(chan);
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300621
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300622 skb = bt_skb_alloc(count, GFP_ATOMIC);
623 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300624 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300625
626 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300627 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300628 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300629
630 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300631
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300632 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300633 u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
634 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300635 }
636
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200637 skb->priority = HCI_PRIO_MAX;
638 l2cap_do_send(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300639}
640
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300641static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300642{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300643 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300644 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300645 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300646 } else
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300647 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300648
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300649 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300650
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300651 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300652}
653
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300654static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300655{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300656 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300657}
658
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300659static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200660{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300661 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200662
663 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100664 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
665 return;
666
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200667 if (l2cap_chan_check_security(chan) &&
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300668 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200669 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300670 req.scid = cpu_to_le16(chan->scid);
671 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200672
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300673 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300674 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200675
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300676 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
677 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200678 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200679 } else {
680 struct l2cap_info_req req;
681 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
682
683 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
684 conn->info_ident = l2cap_get_ident(conn);
685
686 mod_timer(&conn->info_timer, jiffies +
687 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
688
689 l2cap_send_cmd(conn, conn->info_ident,
690 L2CAP_INFO_REQ, sizeof(req), &req);
691 }
692}
693
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300694static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
695{
696 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300697 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300698 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
699
700 switch (mode) {
701 case L2CAP_MODE_ERTM:
702 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
703 case L2CAP_MODE_STREAMING:
704 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
705 default:
706 return 0x00;
707 }
708}
709
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300710static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300711{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300712 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300713 struct l2cap_disconn_req req;
714
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300715 if (!conn)
716 return;
717
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300718 sk = chan->sk;
719
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300720 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300721 __clear_retrans_timer(chan);
722 __clear_monitor_timer(chan);
723 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300724 }
725
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300726 req.dcid = cpu_to_le16(chan->dcid);
727 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300728 l2cap_send_cmd(conn, l2cap_get_ident(conn),
729 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300730
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300731 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300732 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300733}
734
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200736static void l2cap_conn_start(struct l2cap_conn *conn)
737{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300738 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200739
740 BT_DBG("conn %p", conn);
741
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300742 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200743
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300744 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300745 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300746
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200747 bh_lock_sock(sk);
748
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300749 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200750 bh_unlock_sock(sk);
751 continue;
752 }
753
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300754 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300755 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300756
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200757 if (!l2cap_chan_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300758 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300759 bh_unlock_sock(sk);
760 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200761 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300762
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300763 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
764 && test_bit(CONF_STATE2_DEVICE,
765 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300766 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300767 * so release the lock */
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300768 read_unlock(&conn->chan_lock);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300769 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300770 read_lock(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300771 bh_unlock_sock(sk);
772 continue;
773 }
774
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300775 req.scid = cpu_to_le16(chan->scid);
776 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300777
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300778 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300779 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300780
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300781 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
782 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300783
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300784 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200785 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300786 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300787 rsp.scid = cpu_to_le16(chan->dcid);
788 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200789
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200790 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100791 if (bt_sk(sk)->defer_setup) {
792 struct sock *parent = bt_sk(sk)->parent;
793 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
794 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +0000795 if (parent)
796 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100797
798 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300799 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100800 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
801 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
802 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200803 } else {
804 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
805 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
806 }
807
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300808 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
809 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300810
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300811 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300812 rsp.result != L2CAP_CR_SUCCESS) {
813 bh_unlock_sock(sk);
814 continue;
815 }
816
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300817 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300818 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300819 l2cap_build_conf_req(chan, buf), buf);
820 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200821 }
822
823 bh_unlock_sock(sk);
824 }
825
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300826 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200827}
828
Ville Tervob62f3282011-02-10 22:38:50 -0300829/* Find socket with cid and source bdaddr.
830 * Returns closest match, locked.
831 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300832static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300833{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300834 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300835
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300836 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300837
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300838 list_for_each_entry(c, &chan_list, global_l) {
839 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300840
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300841 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300842 continue;
843
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300844 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300845 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300846 if (!bacmp(&bt_sk(sk)->src, src)) {
847 read_unlock(&chan_list_lock);
848 return c;
849 }
Ville Tervob62f3282011-02-10 22:38:50 -0300850
851 /* Closest match */
852 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300853 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300854 }
855 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300856
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300857 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300858
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300859 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300860}
861
862static void l2cap_le_conn_ready(struct l2cap_conn *conn)
863{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300864 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300865 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300866
867 BT_DBG("");
868
869 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300870 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300871 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300872 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300873 return;
874
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300875 parent = pchan->sk;
876
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300877 bh_lock_sock(parent);
878
Ville Tervob62f3282011-02-10 22:38:50 -0300879 /* Check for backlog size */
880 if (sk_acceptq_is_full(parent)) {
881 BT_DBG("backlog full %d", parent->sk_ack_backlog);
882 goto clean;
883 }
884
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300885 chan = pchan->ops->new_connection(pchan->data);
886 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300887 goto clean;
888
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300889 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300890
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300891 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300892
893 hci_conn_hold(conn->hcon);
894
Ville Tervob62f3282011-02-10 22:38:50 -0300895 bacpy(&bt_sk(sk)->src, conn->src);
896 bacpy(&bt_sk(sk)->dst, conn->dst);
897
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300898 bt_accept_enqueue(parent, sk);
899
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300900 __l2cap_chan_add(conn, chan);
901
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300902 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300903
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300904 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300905 parent->sk_data_ready(parent, 0);
906
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300907 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300908
909clean:
910 bh_unlock_sock(parent);
911}
912
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300913static void l2cap_chan_ready(struct sock *sk)
914{
915 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
916 struct sock *parent = bt_sk(sk)->parent;
917
918 BT_DBG("sk %p, parent %p", sk, parent);
919
920 chan->conf_state = 0;
921 __clear_chan_timer(chan);
922
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300923 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300924 sk->sk_state_change(sk);
925
926 if (parent)
927 parent->sk_data_ready(parent, 0);
928}
929
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200930static void l2cap_conn_ready(struct l2cap_conn *conn)
931{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300932 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200933
934 BT_DBG("conn %p", conn);
935
Ville Tervob62f3282011-02-10 22:38:50 -0300936 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
937 l2cap_le_conn_ready(conn);
938
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -0300939 if (conn->hcon->out && conn->hcon->type == LE_LINK)
940 smp_conn_security(conn, conn->hcon->pending_sec_level);
941
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300942 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200943
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300944 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300945 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300946
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200947 bh_lock_sock(sk);
948
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300949 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300950 if (smp_conn_security(conn, chan->sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300951 l2cap_chan_ready(sk);
Ville Tervoacd7d372011-02-10 22:38:49 -0300952
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300953 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300954 __clear_chan_timer(chan);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300955 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200956 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300957
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300958 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300959 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200960
961 bh_unlock_sock(sk);
962 }
963
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300964 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200965}
966
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200967/* Notify sockets that we cannot guaranty reliability anymore */
968static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
969{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300970 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200971
972 BT_DBG("conn %p", conn);
973
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300974 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200975
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300976 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300977 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300978
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +0300979 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200980 sk->sk_err = err;
981 }
982
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300983 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200984}
985
986static void l2cap_info_timeout(unsigned long arg)
987{
988 struct l2cap_conn *conn = (void *) arg;
989
Marcel Holtmann984947d2009-02-06 23:35:19 +0100990 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100991 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100992
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200993 l2cap_conn_start(conn);
994}
995
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300996static void l2cap_conn_del(struct hci_conn *hcon, int err)
997{
998 struct l2cap_conn *conn = hcon->l2cap_data;
999 struct l2cap_chan *chan, *l;
1000 struct sock *sk;
1001
1002 if (!conn)
1003 return;
1004
1005 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
1006
1007 kfree_skb(conn->rx_skb);
1008
1009 /* Kill channels */
1010 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
1011 sk = chan->sk;
1012 bh_lock_sock(sk);
1013 l2cap_chan_del(chan, err);
1014 bh_unlock_sock(sk);
1015 chan->ops->close(chan->data);
1016 }
1017
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001018 hci_chan_del(conn->hchan);
1019
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001020 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1021 del_timer_sync(&conn->info_timer);
1022
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001023 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) {
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001024 del_timer(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001025 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001026 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001027
1028 hcon->l2cap_data = NULL;
1029 kfree(conn);
1030}
1031
1032static void security_timeout(unsigned long arg)
1033{
1034 struct l2cap_conn *conn = (void *) arg;
1035
1036 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1037}
1038
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1040{
Marcel Holtmann01394182006-07-03 10:02:46 +02001041 struct l2cap_conn *conn = hcon->l2cap_data;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001042 struct hci_chan *hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043
Marcel Holtmann01394182006-07-03 10:02:46 +02001044 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 return conn;
1046
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001047 hchan = hci_chan_create(hcon);
1048 if (!hchan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001051 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1052 if (!conn) {
1053 hci_chan_del(hchan);
1054 return NULL;
1055 }
1056
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 hcon->l2cap_data = conn;
1058 conn->hcon = hcon;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001059 conn->hchan = hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001061 BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
Marcel Holtmann01394182006-07-03 10:02:46 +02001062
Ville Tervoacd7d372011-02-10 22:38:49 -03001063 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1064 conn->mtu = hcon->hdev->le_mtu;
1065 else
1066 conn->mtu = hcon->hdev->acl_mtu;
1067
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 conn->src = &hcon->hdev->bdaddr;
1069 conn->dst = &hcon->dst;
1070
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001071 conn->feat_mask = 0;
1072
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001074 rwlock_init(&conn->chan_lock);
1075
1076 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001078 if (hcon->type == LE_LINK)
1079 setup_timer(&conn->security_timer, security_timeout,
1080 (unsigned long) conn);
1081 else
Ville Tervob62f3282011-02-10 22:38:50 -03001082 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +00001083 (unsigned long) conn);
1084
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001085 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01001086
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 return conn;
1088}
1089
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001090static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001092 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001093 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001094 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095}
1096
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098
1099/* Find socket with psm and source bdaddr.
1100 * Returns closest match.
1101 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001102static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001104 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001106 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001107
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001108 list_for_each_entry(c, &chan_list, global_l) {
1109 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001110
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001111 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 continue;
1113
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001114 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001116 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001117 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001118 return c;
1119 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120
1121 /* Closest match */
1122 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001123 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 }
1125 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001127 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001128
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001129 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130}
1131
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001132int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001134 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 bdaddr_t *src = &bt_sk(sk)->src;
1136 bdaddr_t *dst = &bt_sk(sk)->dst;
1137 struct l2cap_conn *conn;
1138 struct hci_conn *hcon;
1139 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001140 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001141 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001143 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001144 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001146 hdev = hci_get_route(dst, src);
1147 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 return -EHOSTUNREACH;
1149
1150 hci_dev_lock_bh(hdev);
1151
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001152 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001153
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001154 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001155 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001156 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001157 else
1158 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001159 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001160
Ville Tervo30e76272011-02-22 16:10:53 -03001161 if (IS_ERR(hcon)) {
1162 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001164 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165
1166 conn = l2cap_conn_add(hcon, 0);
1167 if (!conn) {
1168 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001169 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 goto done;
1171 }
1172
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 /* Update source addr of the socket */
1174 bacpy(src, conn->src);
1175
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001176 l2cap_chan_add(conn, chan);
1177
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001178 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001179 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180
1181 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001182 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001183 __clear_chan_timer(chan);
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001184 if (l2cap_chan_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001185 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001186 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001187 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 }
1189
Ville Tervo30e76272011-02-22 16:10:53 -03001190 err = 0;
1191
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192done:
1193 hci_dev_unlock_bh(hdev);
1194 hci_dev_put(hdev);
1195 return err;
1196}
1197
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001198int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001199{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001200 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001201 DECLARE_WAITQUEUE(wait, current);
1202 int err = 0;
1203 int timeo = HZ/5;
1204
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001205 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001206 set_current_state(TASK_INTERRUPTIBLE);
1207 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001208 if (!timeo)
1209 timeo = HZ/5;
1210
1211 if (signal_pending(current)) {
1212 err = sock_intr_errno(timeo);
1213 break;
1214 }
1215
1216 release_sock(sk);
1217 timeo = schedule_timeout(timeo);
1218 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001219 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001220
1221 err = sock_error(sk);
1222 if (err)
1223 break;
1224 }
1225 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001226 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001227 return err;
1228}
1229
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001230static void l2cap_monitor_timeout(unsigned long arg)
1231{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001232 struct l2cap_chan *chan = (void *) arg;
1233 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001234
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001235 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001236
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001237 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001238 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001239 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001240 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001241 return;
1242 }
1243
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001244 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001245 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001246
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001247 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001248 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001249}
1250
1251static void l2cap_retrans_timeout(unsigned long arg)
1252{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001253 struct l2cap_chan *chan = (void *) arg;
1254 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001255
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001256 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001257
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001258 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001259 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001260 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001261
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001262 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001263
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001264 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001265 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001266}
1267
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001268static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001269{
1270 struct sk_buff *skb;
1271
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001272 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001273 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001274 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001275 break;
1276
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001277 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001278 kfree_skb(skb);
1279
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001280 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001281 }
1282
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001283 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001284 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001285}
1286
Szymon Janc67c9e842011-07-28 16:24:33 +02001287static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001288{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001289 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001290 u32 control;
1291 u16 fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001292
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001293 while ((skb = skb_dequeue(&chan->tx_q))) {
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001294 control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001295 control |= __set_txseq(chan, chan->next_tx_seq);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001296 __put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001297
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001298 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001299 fcs = crc16(0, (u8 *)skb->data,
1300 skb->len - L2CAP_FCS_SIZE);
1301 put_unaligned_le16(fcs,
1302 skb->data + skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001303 }
1304
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001305 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001306
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001307 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001308 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001309}
1310
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001311static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001312{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001313 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001314 u16 fcs;
1315 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001316
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001317 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001318 if (!skb)
1319 return;
1320
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001321 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001322 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001323 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001324
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001325 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001326 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001327
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001328 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001329
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001330 if (chan->remote_max_tx &&
1331 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001332 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001333 return;
1334 }
1335
1336 tx_skb = skb_clone(skb, GFP_ATOMIC);
1337 bt_cb(skb)->retries++;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001338
1339 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001340 control &= __get_sar_mask(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001341
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001342 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001343 control |= __set_ctrl_final(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001344
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001345 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001346 control |= __set_txseq(chan, tx_seq);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001347
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001348 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001349
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001350 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001351 fcs = crc16(0, (u8 *)tx_skb->data,
1352 tx_skb->len - L2CAP_FCS_SIZE);
1353 put_unaligned_le16(fcs,
1354 tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001355 }
1356
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001357 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001358}
1359
Szymon Janc67c9e842011-07-28 16:24:33 +02001360static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001361{
1362 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001363 u16 fcs;
1364 u32 control;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001365 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001366
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001367 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001368 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001369
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001370 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001371
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001372 if (chan->remote_max_tx &&
1373 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001374 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001375 break;
1376 }
1377
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001378 tx_skb = skb_clone(skb, GFP_ATOMIC);
1379
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001380 bt_cb(skb)->retries++;
1381
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001382 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001383 control &= __get_sar_mask(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001384
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001385 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001386 control |= __set_ctrl_final(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001387
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001388 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001389 control |= __set_txseq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001390
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001391 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001392
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001393 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001394 fcs = crc16(0, (u8 *)skb->data,
1395 tx_skb->len - L2CAP_FCS_SIZE);
1396 put_unaligned_le16(fcs, skb->data +
1397 tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001398 }
1399
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001400 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001401
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001402 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001403
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001404 bt_cb(skb)->tx_seq = chan->next_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001405
1406 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001407
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301408 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001409 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301410
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001411 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001412
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001413 if (skb_queue_is_last(&chan->tx_q, skb))
1414 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001415 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001416 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001417
1418 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001419 }
1420
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001421 return nsent;
1422}
1423
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001424static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001425{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001426 int ret;
1427
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001428 if (!skb_queue_empty(&chan->tx_q))
1429 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001430
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001431 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001432 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001433 return ret;
1434}
1435
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001436static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001437{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001438 u32 control = 0;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001439
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001440 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001441
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001442 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001443 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001444 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001445 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001446 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001447 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001448
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001449 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001450 return;
1451
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001452 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001453 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001454}
1455
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001456static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001457{
1458 struct srej_list *tail;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001459 u32 control;
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001460
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001461 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001462 control |= __set_ctrl_final(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001463
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001464 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001465 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001466
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001467 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001468}
1469
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001470static 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 -07001471{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001472 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001473 struct sk_buff **frag;
1474 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001476 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001477 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478
1479 sent += count;
1480 len -= count;
1481
1482 /* Continuation fragments (no L2CAP header) */
1483 frag = &skb_shinfo(skb)->frag_list;
1484 while (len) {
1485 count = min_t(unsigned int, conn->mtu, len);
1486
1487 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1488 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001489 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001490 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1491 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001493 (*frag)->priority = skb->priority;
1494
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 sent += count;
1496 len -= count;
1497
1498 frag = &(*frag)->next;
1499 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500
1501 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001502}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001504static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
1505 struct msghdr *msg, size_t len,
1506 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001507{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001508 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001509 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001510 struct sk_buff *skb;
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001511 int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001512 struct l2cap_hdr *lh;
1513
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001514 BT_DBG("sk %p len %d priority %u", sk, (int)len, priority);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001515
1516 count = min_t(unsigned int, (conn->mtu - hlen), len);
1517 skb = bt_skb_send_alloc(sk, count + hlen,
1518 msg->msg_flags & MSG_DONTWAIT, &err);
1519 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001520 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001521
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001522 skb->priority = priority;
1523
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001524 /* Create L2CAP header */
1525 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001526 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001527 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001528 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001529
1530 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1531 if (unlikely(err < 0)) {
1532 kfree_skb(skb);
1533 return ERR_PTR(err);
1534 }
1535 return skb;
1536}
1537
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001538static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
1539 struct msghdr *msg, size_t len,
1540 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001541{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001542 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001543 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001544 struct sk_buff *skb;
1545 int err, count, hlen = L2CAP_HDR_SIZE;
1546 struct l2cap_hdr *lh;
1547
1548 BT_DBG("sk %p len %d", sk, (int)len);
1549
1550 count = min_t(unsigned int, (conn->mtu - hlen), len);
1551 skb = bt_skb_send_alloc(sk, count + hlen,
1552 msg->msg_flags & MSG_DONTWAIT, &err);
1553 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001554 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001555
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001556 skb->priority = priority;
1557
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001558 /* Create L2CAP header */
1559 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001560 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001561 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1562
1563 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1564 if (unlikely(err < 0)) {
1565 kfree_skb(skb);
1566 return ERR_PTR(err);
1567 }
1568 return skb;
1569}
1570
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001571static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1572 struct msghdr *msg, size_t len,
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001573 u32 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001574{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001575 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001576 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001577 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001578 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001579 struct l2cap_hdr *lh;
1580
1581 BT_DBG("sk %p len %d", sk, (int)len);
1582
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001583 if (!conn)
1584 return ERR_PTR(-ENOTCONN);
1585
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001586 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1587 hlen = L2CAP_EXT_HDR_SIZE;
1588 else
1589 hlen = L2CAP_ENH_HDR_SIZE;
1590
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001591 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001592 hlen += L2CAP_SDULEN_SIZE;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001593
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001594 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001595 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001596
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001597 count = min_t(unsigned int, (conn->mtu - hlen), len);
1598 skb = bt_skb_send_alloc(sk, count + hlen,
1599 msg->msg_flags & MSG_DONTWAIT, &err);
1600 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001601 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001602
1603 /* Create L2CAP header */
1604 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001605 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001606 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001607
1608 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
1609
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001610 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001611 put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001612
1613 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1614 if (unlikely(err < 0)) {
1615 kfree_skb(skb);
1616 return ERR_PTR(err);
1617 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001618
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001619 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001620 put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001621
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001622 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001623 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624}
1625
Szymon Janc67c9e842011-07-28 16:24:33 +02001626static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001627{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001628 struct sk_buff *skb;
1629 struct sk_buff_head sar_queue;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001630 u32 control;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001631 size_t size = 0;
1632
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001633 skb_queue_head_init(&sar_queue);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001634 control = __set_ctrl_sar(chan, L2CAP_SAR_START);
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001635 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001636 if (IS_ERR(skb))
1637 return PTR_ERR(skb);
1638
1639 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001640 len -= chan->remote_mps;
1641 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001642
1643 while (len > 0) {
1644 size_t buflen;
1645
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001646 if (len > chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001647 control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001648 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001649 } else {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001650 control = __set_ctrl_sar(chan, L2CAP_SAR_END);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001651 buflen = len;
1652 }
1653
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001654 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001655 if (IS_ERR(skb)) {
1656 skb_queue_purge(&sar_queue);
1657 return PTR_ERR(skb);
1658 }
1659
1660 __skb_queue_tail(&sar_queue, skb);
1661 len -= buflen;
1662 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001663 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001664 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1665 if (chan->tx_send_head == NULL)
1666 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001667
1668 return size;
1669}
1670
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001671int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
1672 u32 priority)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001673{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001674 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001675 u32 control;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001676 int err;
1677
1678 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001679 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001680 skb = l2cap_create_connless_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001681 if (IS_ERR(skb))
1682 return PTR_ERR(skb);
1683
1684 l2cap_do_send(chan, skb);
1685 return len;
1686 }
1687
1688 switch (chan->mode) {
1689 case L2CAP_MODE_BASIC:
1690 /* Check outgoing MTU */
1691 if (len > chan->omtu)
1692 return -EMSGSIZE;
1693
1694 /* Create a basic PDU */
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001695 skb = l2cap_create_basic_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 err = len;
1701 break;
1702
1703 case L2CAP_MODE_ERTM:
1704 case L2CAP_MODE_STREAMING:
1705 /* Entire SDU fits into one PDU */
1706 if (len <= chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001707 control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001708 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1709 0);
1710 if (IS_ERR(skb))
1711 return PTR_ERR(skb);
1712
1713 __skb_queue_tail(&chan->tx_q, skb);
1714
1715 if (chan->tx_send_head == NULL)
1716 chan->tx_send_head = skb;
1717
1718 } else {
1719 /* Segment SDU into multiples PDUs */
1720 err = l2cap_sar_segment_sdu(chan, msg, len);
1721 if (err < 0)
1722 return err;
1723 }
1724
1725 if (chan->mode == L2CAP_MODE_STREAMING) {
1726 l2cap_streaming_send(chan);
1727 err = len;
1728 break;
1729 }
1730
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001731 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1732 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001733 err = len;
1734 break;
1735 }
1736
1737 err = l2cap_ertm_send(chan);
1738 if (err >= 0)
1739 err = len;
1740
1741 break;
1742
1743 default:
1744 BT_DBG("bad state %1.1x", chan->mode);
1745 err = -EBADFD;
1746 }
1747
1748 return err;
1749}
1750
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751/* Copy frame to all raw sockets on that connection */
1752static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1753{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001755 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756
1757 BT_DBG("conn %p", conn);
1758
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001759 read_lock(&conn->chan_lock);
1760 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001761 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001762 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 continue;
1764
1765 /* Don't send frame to the socket it came from */
1766 if (skb->sk == sk)
1767 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001768 nskb = skb_clone(skb, GFP_ATOMIC);
1769 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770 continue;
1771
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001772 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773 kfree_skb(nskb);
1774 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001775 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776}
1777
1778/* ---- L2CAP signalling commands ---- */
1779static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1780 u8 code, u8 ident, u16 dlen, void *data)
1781{
1782 struct sk_buff *skb, **frag;
1783 struct l2cap_cmd_hdr *cmd;
1784 struct l2cap_hdr *lh;
1785 int len, count;
1786
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001787 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1788 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789
1790 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1791 count = min_t(unsigned int, conn->mtu, len);
1792
1793 skb = bt_skb_alloc(count, GFP_ATOMIC);
1794 if (!skb)
1795 return NULL;
1796
1797 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001798 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001799
1800 if (conn->hcon->type == LE_LINK)
1801 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1802 else
1803 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804
1805 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1806 cmd->code = code;
1807 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001808 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809
1810 if (dlen) {
1811 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1812 memcpy(skb_put(skb, count), data, count);
1813 data += count;
1814 }
1815
1816 len -= skb->len;
1817
1818 /* Continuation fragments (no L2CAP header) */
1819 frag = &skb_shinfo(skb)->frag_list;
1820 while (len) {
1821 count = min_t(unsigned int, conn->mtu, len);
1822
1823 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1824 if (!*frag)
1825 goto fail;
1826
1827 memcpy(skb_put(*frag, count), data, count);
1828
1829 len -= count;
1830 data += count;
1831
1832 frag = &(*frag)->next;
1833 }
1834
1835 return skb;
1836
1837fail:
1838 kfree_skb(skb);
1839 return NULL;
1840}
1841
1842static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1843{
1844 struct l2cap_conf_opt *opt = *ptr;
1845 int len;
1846
1847 len = L2CAP_CONF_OPT_SIZE + opt->len;
1848 *ptr += len;
1849
1850 *type = opt->type;
1851 *olen = opt->len;
1852
1853 switch (opt->len) {
1854 case 1:
1855 *val = *((u8 *) opt->val);
1856 break;
1857
1858 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001859 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860 break;
1861
1862 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001863 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 break;
1865
1866 default:
1867 *val = (unsigned long) opt->val;
1868 break;
1869 }
1870
1871 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1872 return len;
1873}
1874
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1876{
1877 struct l2cap_conf_opt *opt = *ptr;
1878
1879 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1880
1881 opt->type = type;
1882 opt->len = len;
1883
1884 switch (len) {
1885 case 1:
1886 *((u8 *) opt->val) = val;
1887 break;
1888
1889 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001890 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 break;
1892
1893 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001894 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 break;
1896
1897 default:
1898 memcpy(opt->val, (void *) val, len);
1899 break;
1900 }
1901
1902 *ptr += L2CAP_CONF_OPT_SIZE + len;
1903}
1904
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001905static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
1906{
1907 struct l2cap_conf_efs efs;
1908
1909 switch(chan->mode) {
1910 case L2CAP_MODE_ERTM:
1911 efs.id = chan->local_id;
1912 efs.stype = chan->local_stype;
1913 efs.msdu = cpu_to_le16(chan->local_msdu);
1914 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1915 efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
1916 efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
1917 break;
1918
1919 case L2CAP_MODE_STREAMING:
1920 efs.id = 1;
1921 efs.stype = L2CAP_SERV_BESTEFFORT;
1922 efs.msdu = cpu_to_le16(chan->local_msdu);
1923 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1924 efs.acc_lat = 0;
1925 efs.flush_to = 0;
1926 break;
1927
1928 default:
1929 return;
1930 }
1931
1932 l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
1933 (unsigned long) &efs);
1934}
1935
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001936static void l2cap_ack_timeout(unsigned long arg)
1937{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001938 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001939
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001940 bh_lock_sock(chan->sk);
1941 l2cap_send_ack(chan);
1942 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001943}
1944
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001945static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001946{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001947 struct sock *sk = chan->sk;
1948
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001949 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001950 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001951 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001952 chan->num_acked = 0;
1953 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001954
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001955 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1956 (unsigned long) chan);
1957 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1958 (unsigned long) chan);
1959 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001960
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001961 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001962
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001963 INIT_LIST_HEAD(&chan->srej_l);
1964
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001965
1966 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001967}
1968
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001969static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1970{
1971 switch (mode) {
1972 case L2CAP_MODE_STREAMING:
1973 case L2CAP_MODE_ERTM:
1974 if (l2cap_mode_supported(mode, remote_feat_mask))
1975 return mode;
1976 /* fall through */
1977 default:
1978 return L2CAP_MODE_BASIC;
1979 }
1980}
1981
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001982static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
1983{
1984 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
1985}
1986
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001987static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
1988{
1989 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
1990}
1991
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001992static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
1993{
1994 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001995 __l2cap_ews_supported(chan)) {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001996 /* use extended control field */
1997 set_bit(FLAG_EXT_CTRL, &chan->flags);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001998 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
1999 } else {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002000 chan->tx_win = min_t(u16, chan->tx_win,
2001 L2CAP_DEFAULT_TX_WINDOW);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002002 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2003 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002004}
2005
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002006static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002009 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010 void *ptr = req->data;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002011 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002013 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002015 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002016 goto done;
2017
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002018 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002019 case L2CAP_MODE_STREAMING:
2020 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002021 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002022 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002023
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002024 if (__l2cap_efs_supported(chan))
2025 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2026
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002027 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002028 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002029 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002030 break;
2031 }
2032
2033done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002034 if (chan->imtu != L2CAP_DEFAULT_MTU)
2035 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002036
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002037 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002038 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002039 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2040 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002041 break;
2042
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002043 rfc.mode = L2CAP_MODE_BASIC;
2044 rfc.txwin_size = 0;
2045 rfc.max_transmit = 0;
2046 rfc.retrans_timeout = 0;
2047 rfc.monitor_timeout = 0;
2048 rfc.max_pdu_size = 0;
2049
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002050 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2051 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002052 break;
2053
2054 case L2CAP_MODE_ERTM:
2055 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002056 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002057 rfc.retrans_timeout = 0;
2058 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002059
2060 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2061 L2CAP_EXT_HDR_SIZE -
2062 L2CAP_SDULEN_SIZE -
2063 L2CAP_FCS_SIZE);
2064 rfc.max_pdu_size = cpu_to_le16(size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002065
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002066 l2cap_txwin_setup(chan);
2067
2068 rfc.txwin_size = min_t(u16, chan->tx_win,
2069 L2CAP_DEFAULT_TX_WINDOW);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002070
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002071 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2072 (unsigned long) &rfc);
2073
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002074 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2075 l2cap_add_opt_efs(&ptr, chan);
2076
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002077 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002078 break;
2079
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002080 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002081 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002082 chan->fcs = L2CAP_FCS_NONE;
2083 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002084 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002085
2086 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2087 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2088 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002089 break;
2090
2091 case L2CAP_MODE_STREAMING:
2092 rfc.mode = L2CAP_MODE_STREAMING;
2093 rfc.txwin_size = 0;
2094 rfc.max_transmit = 0;
2095 rfc.retrans_timeout = 0;
2096 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002097
2098 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2099 L2CAP_EXT_HDR_SIZE -
2100 L2CAP_SDULEN_SIZE -
2101 L2CAP_FCS_SIZE);
2102 rfc.max_pdu_size = cpu_to_le16(size);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002103
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002104 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2105 (unsigned long) &rfc);
2106
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002107 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2108 l2cap_add_opt_efs(&ptr, chan);
2109
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002110 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002111 break;
2112
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002113 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002114 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002115 chan->fcs = L2CAP_FCS_NONE;
2116 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002117 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002118 break;
2119 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002121 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002122 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123
2124 return ptr - data;
2125}
2126
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002127static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002129 struct l2cap_conf_rsp *rsp = data;
2130 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002131 void *req = chan->conf_req;
2132 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002133 int type, hint, olen;
2134 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002135 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002136 struct l2cap_conf_efs efs;
2137 u8 remote_efs = 0;
Marcel Holtmann861d6882007-10-20 13:37:06 +02002138 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002139 u16 result = L2CAP_CONF_SUCCESS;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002140 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002142 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002143
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002144 while (len >= L2CAP_CONF_OPT_SIZE) {
2145 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002147 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002148 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002149
2150 switch (type) {
2151 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002152 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002153 break;
2154
2155 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002156 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002157 break;
2158
2159 case L2CAP_CONF_QOS:
2160 break;
2161
Marcel Holtmann6464f352007-10-20 13:39:51 +02002162 case L2CAP_CONF_RFC:
2163 if (olen == sizeof(rfc))
2164 memcpy(&rfc, (void *) val, olen);
2165 break;
2166
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002167 case L2CAP_CONF_FCS:
2168 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002169 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002170 break;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002171
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002172 case L2CAP_CONF_EFS:
2173 remote_efs = 1;
2174 if (olen == sizeof(efs))
2175 memcpy(&efs, (void *) val, olen);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002176 break;
2177
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002178 case L2CAP_CONF_EWS:
2179 if (!enable_hs)
2180 return -ECONNREFUSED;
2181
2182 set_bit(FLAG_EXT_CTRL, &chan->flags);
2183 set_bit(CONF_EWS_RECV, &chan->conf_state);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002184 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002185 chan->remote_tx_win = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002186 break;
2187
2188 default:
2189 if (hint)
2190 break;
2191
2192 result = L2CAP_CONF_UNKNOWN;
2193 *((u8 *) ptr++) = type;
2194 break;
2195 }
2196 }
2197
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002198 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002199 goto done;
2200
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002201 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002202 case L2CAP_MODE_STREAMING:
2203 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002204 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002205 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002206 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002207 break;
2208 }
2209
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002210 if (remote_efs) {
2211 if (__l2cap_efs_supported(chan))
2212 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2213 else
2214 return -ECONNREFUSED;
2215 }
2216
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002217 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002218 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002219
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002220 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002221 }
2222
2223done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002224 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002225 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002226 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002227
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002228 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002229 return -ECONNREFUSED;
2230
2231 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2232 sizeof(rfc), (unsigned long) &rfc);
2233 }
2234
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002235 if (result == L2CAP_CONF_SUCCESS) {
2236 /* Configure output options and let the other side know
2237 * which ones we don't like. */
2238
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002239 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2240 result = L2CAP_CONF_UNACCEPT;
2241 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002242 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002243 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002244 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002245 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002246
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002247 if (remote_efs) {
2248 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2249 efs.stype != L2CAP_SERV_NOTRAFIC &&
2250 efs.stype != chan->local_stype) {
2251
2252 result = L2CAP_CONF_UNACCEPT;
2253
2254 if (chan->num_conf_req >= 1)
2255 return -ECONNREFUSED;
2256
2257 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002258 sizeof(efs),
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002259 (unsigned long) &efs);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002260 } else {
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002261 /* Send PENDING Conf Rsp */
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002262 result = L2CAP_CONF_PENDING;
2263 set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002264 }
2265 }
2266
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002267 switch (rfc.mode) {
2268 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002269 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002270 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002271 break;
2272
2273 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002274 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2275 chan->remote_tx_win = rfc.txwin_size;
2276 else
2277 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2278
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002279 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002280
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002281 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2282 chan->conn->mtu -
2283 L2CAP_EXT_HDR_SIZE -
2284 L2CAP_SDULEN_SIZE -
2285 L2CAP_FCS_SIZE);
2286 rfc.max_pdu_size = cpu_to_le16(size);
2287 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002288
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002289 rfc.retrans_timeout =
2290 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2291 rfc.monitor_timeout =
2292 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002293
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002294 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002295
2296 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2297 sizeof(rfc), (unsigned long) &rfc);
2298
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002299 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2300 chan->remote_id = efs.id;
2301 chan->remote_stype = efs.stype;
2302 chan->remote_msdu = le16_to_cpu(efs.msdu);
2303 chan->remote_flush_to =
2304 le32_to_cpu(efs.flush_to);
2305 chan->remote_acc_lat =
2306 le32_to_cpu(efs.acc_lat);
2307 chan->remote_sdu_itime =
2308 le32_to_cpu(efs.sdu_itime);
2309 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2310 sizeof(efs), (unsigned long) &efs);
2311 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002312 break;
2313
2314 case L2CAP_MODE_STREAMING:
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002315 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2316 chan->conn->mtu -
2317 L2CAP_EXT_HDR_SIZE -
2318 L2CAP_SDULEN_SIZE -
2319 L2CAP_FCS_SIZE);
2320 rfc.max_pdu_size = cpu_to_le16(size);
2321 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002322
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002323 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002324
2325 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2326 sizeof(rfc), (unsigned long) &rfc);
2327
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002328 break;
2329
2330 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002331 result = L2CAP_CONF_UNACCEPT;
2332
2333 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002334 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002335 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002336
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002337 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002338 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002339 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002340 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002341 rsp->result = cpu_to_le16(result);
2342 rsp->flags = cpu_to_le16(0x0000);
2343
2344 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345}
2346
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002347static 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 -03002348{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002349 struct l2cap_conf_req *req = data;
2350 void *ptr = req->data;
2351 int type, olen;
2352 unsigned long val;
2353 struct l2cap_conf_rfc rfc;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002354 struct l2cap_conf_efs efs;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002355
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002356 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002357
2358 while (len >= L2CAP_CONF_OPT_SIZE) {
2359 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2360
2361 switch (type) {
2362 case L2CAP_CONF_MTU:
2363 if (val < L2CAP_DEFAULT_MIN_MTU) {
2364 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002365 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002366 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002367 chan->imtu = val;
2368 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002369 break;
2370
2371 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002372 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002373 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002374 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002375 break;
2376
2377 case L2CAP_CONF_RFC:
2378 if (olen == sizeof(rfc))
2379 memcpy(&rfc, (void *)val, olen);
2380
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002381 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002382 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002383 return -ECONNREFUSED;
2384
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002385 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002386
2387 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2388 sizeof(rfc), (unsigned long) &rfc);
2389 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002390
2391 case L2CAP_CONF_EWS:
2392 chan->tx_win = min_t(u16, val,
2393 L2CAP_DEFAULT_EXT_WINDOW);
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002394 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2395 chan->tx_win);
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002396 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002397
2398 case L2CAP_CONF_EFS:
2399 if (olen == sizeof(efs))
2400 memcpy(&efs, (void *)val, olen);
2401
2402 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2403 efs.stype != L2CAP_SERV_NOTRAFIC &&
2404 efs.stype != chan->local_stype)
2405 return -ECONNREFUSED;
2406
2407 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2408 sizeof(efs), (unsigned long) &efs);
2409 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002410 }
2411 }
2412
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002413 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002414 return -ECONNREFUSED;
2415
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002416 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002417
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002418 if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002419 switch (rfc.mode) {
2420 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002421 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2422 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2423 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002424
2425 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2426 chan->local_msdu = le16_to_cpu(efs.msdu);
2427 chan->local_sdu_itime =
2428 le32_to_cpu(efs.sdu_itime);
2429 chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
2430 chan->local_flush_to =
2431 le32_to_cpu(efs.flush_to);
2432 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002433 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002434
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002435 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002436 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002437 }
2438 }
2439
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002440 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002441 req->flags = cpu_to_le16(0x0000);
2442
2443 return ptr - data;
2444}
2445
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002446static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447{
2448 struct l2cap_conf_rsp *rsp = data;
2449 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002451 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002453 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002454 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002455 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456
2457 return ptr - data;
2458}
2459
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002460void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002461{
2462 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002463 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002464 u8 buf[128];
2465
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002466 rsp.scid = cpu_to_le16(chan->dcid);
2467 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002468 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2469 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2470 l2cap_send_cmd(conn, chan->ident,
2471 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2472
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002473 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002474 return;
2475
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002476 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2477 l2cap_build_conf_req(chan, buf), buf);
2478 chan->num_conf_req++;
2479}
2480
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002481static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002482{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002483 int type, olen;
2484 unsigned long val;
2485 struct l2cap_conf_rfc rfc;
2486
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002487 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002488
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002489 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002490 return;
2491
2492 while (len >= L2CAP_CONF_OPT_SIZE) {
2493 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2494
2495 switch (type) {
2496 case L2CAP_CONF_RFC:
2497 if (olen == sizeof(rfc))
2498 memcpy(&rfc, (void *)val, olen);
2499 goto done;
2500 }
2501 }
2502
2503done:
2504 switch (rfc.mode) {
2505 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002506 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2507 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2508 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002509 break;
2510 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002511 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002512 }
2513}
2514
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002515static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2516{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002517 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002518
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002519 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002520 return 0;
2521
2522 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2523 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002524 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002525
2526 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002527 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002528
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002529 l2cap_conn_start(conn);
2530 }
2531
2532 return 0;
2533}
2534
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2536{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2538 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002539 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002540 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002541 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002542
2543 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002544 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545
2546 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2547
2548 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002549 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2550 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551 result = L2CAP_CR_BAD_PSM;
2552 goto sendresp;
2553 }
2554
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002555 parent = pchan->sk;
2556
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002557 bh_lock_sock(parent);
2558
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002559 /* Check if the ACL is secure enough (if not SDP) */
2560 if (psm != cpu_to_le16(0x0001) &&
2561 !hci_conn_check_link_mode(conn->hcon)) {
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002562 conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002563 result = L2CAP_CR_SEC_BLOCK;
2564 goto response;
2565 }
2566
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 result = L2CAP_CR_NO_MEM;
2568
2569 /* Check for backlog size */
2570 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002571 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572 goto response;
2573 }
2574
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002575 chan = pchan->ops->new_connection(pchan->data);
2576 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577 goto response;
2578
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002579 sk = chan->sk;
2580
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002581 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582
2583 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002584 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2585 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002587 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588 goto response;
2589 }
2590
2591 hci_conn_hold(conn->hcon);
2592
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593 bacpy(&bt_sk(sk)->src, conn->src);
2594 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002595 chan->psm = psm;
2596 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002598 bt_accept_enqueue(parent, sk);
2599
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002600 __l2cap_chan_add(conn, chan);
2601
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002602 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002604 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002606 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607
Marcel Holtmann984947d2009-02-06 23:35:19 +01002608 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02002609 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002610 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002611 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002612 result = L2CAP_CR_PEND;
2613 status = L2CAP_CS_AUTHOR_PEND;
2614 parent->sk_data_ready(parent, 0);
2615 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002616 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002617 result = L2CAP_CR_SUCCESS;
2618 status = L2CAP_CS_NO_INFO;
2619 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002620 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002621 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002622 result = L2CAP_CR_PEND;
2623 status = L2CAP_CS_AUTHEN_PEND;
2624 }
2625 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002626 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002627 result = L2CAP_CR_PEND;
2628 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629 }
2630
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002631 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632
2633response:
2634 bh_unlock_sock(parent);
2635
2636sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002637 rsp.scid = cpu_to_le16(scid);
2638 rsp.dcid = cpu_to_le16(dcid);
2639 rsp.result = cpu_to_le16(result);
2640 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002642
2643 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2644 struct l2cap_info_req info;
2645 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2646
2647 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2648 conn->info_ident = l2cap_get_ident(conn);
2649
2650 mod_timer(&conn->info_timer, jiffies +
2651 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2652
2653 l2cap_send_cmd(conn, conn->info_ident,
2654 L2CAP_INFO_REQ, sizeof(info), &info);
2655 }
2656
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002657 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002658 result == L2CAP_CR_SUCCESS) {
2659 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002660 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002661 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002662 l2cap_build_conf_req(chan, buf), buf);
2663 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002664 }
2665
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666 return 0;
2667}
2668
2669static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2670{
2671 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2672 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002673 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674 struct sock *sk;
2675 u8 req[128];
2676
2677 scid = __le16_to_cpu(rsp->scid);
2678 dcid = __le16_to_cpu(rsp->dcid);
2679 result = __le16_to_cpu(rsp->result);
2680 status = __le16_to_cpu(rsp->status);
2681
2682 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2683
2684 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002685 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002686 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002687 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002689 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002690 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002691 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692 }
2693
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002694 sk = chan->sk;
2695
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696 switch (result) {
2697 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002698 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002699 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002700 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002701 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002702
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002703 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002704 break;
2705
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002707 l2cap_build_conf_req(chan, req), req);
2708 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 break;
2710
2711 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002712 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713 break;
2714
2715 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002716 /* don't delete l2cap channel if sk is owned by user */
2717 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002718 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002719 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02002720 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002721 break;
2722 }
2723
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002724 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725 break;
2726 }
2727
2728 bh_unlock_sock(sk);
2729 return 0;
2730}
2731
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002732static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002733{
2734 /* FCS is enabled only in ERTM or streaming mode, if one or both
2735 * sides request it.
2736 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002737 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002738 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002739 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002740 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002741}
2742
Al Viro88219a02007-07-29 00:17:25 -07002743static 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 -07002744{
2745 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2746 u16 dcid, flags;
2747 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002748 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002750 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751
2752 dcid = __le16_to_cpu(req->dcid);
2753 flags = __le16_to_cpu(req->flags);
2754
2755 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2756
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002757 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002758 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 return -ENOENT;
2760
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002761 sk = chan->sk;
2762
David S. Miller033b1142011-07-21 13:38:42 -07002763 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002764 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002765
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002766 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2767 rej.scid = cpu_to_le16(chan->scid);
2768 rej.dcid = cpu_to_le16(chan->dcid);
2769
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002770 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2771 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002772 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002773 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002774
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002775 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002776 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002777 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002778 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002779 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002780 L2CAP_CONF_REJECT, flags), rsp);
2781 goto unlock;
2782 }
2783
2784 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002785 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2786 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787
2788 if (flags & 0x0001) {
2789 /* Incomplete config. Send empty response. */
2790 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002791 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002792 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793 goto unlock;
2794 }
2795
2796 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002797 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002798 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002799 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002801 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002803 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002804 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002805
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002806 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002807 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002808
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002809 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002810 goto unlock;
2811
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002812 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002813 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002814
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002815 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002816
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002817 chan->next_tx_seq = 0;
2818 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002819 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002820 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002821 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002822
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002824 goto unlock;
2825 }
2826
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002827 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002828 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002830 l2cap_build_conf_req(chan, buf), buf);
2831 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832 }
2833
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002834 /* Got Conf Rsp PENDING from remote side and asume we sent
2835 Conf Rsp PENDING in the code above */
2836 if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
2837 test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2838
2839 /* check compatibility */
2840
2841 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2842 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2843
2844 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002845 l2cap_build_conf_rsp(chan, rsp,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002846 L2CAP_CONF_SUCCESS, 0x0000), rsp);
2847 }
2848
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849unlock:
2850 bh_unlock_sock(sk);
2851 return 0;
2852}
2853
2854static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2855{
2856 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2857 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002858 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002860 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861
2862 scid = __le16_to_cpu(rsp->scid);
2863 flags = __le16_to_cpu(rsp->flags);
2864 result = __le16_to_cpu(rsp->result);
2865
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002866 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2867 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002869 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002870 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871 return 0;
2872
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002873 sk = chan->sk;
2874
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875 switch (result) {
2876 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002877 l2cap_conf_rfc_get(chan, rsp->data, len);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002878 clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879 break;
2880
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002881 case L2CAP_CONF_PENDING:
2882 set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
2883
2884 if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2885 char buf[64];
2886
2887 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2888 buf, &result);
2889 if (len < 0) {
2890 l2cap_send_disconn_req(conn, chan, ECONNRESET);
2891 goto done;
2892 }
2893
2894 /* check compatibility */
2895
2896 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2897 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2898
2899 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002900 l2cap_build_conf_rsp(chan, buf,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002901 L2CAP_CONF_SUCCESS, 0x0000), buf);
2902 }
2903 goto done;
2904
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002906 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002907 char req[64];
2908
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002909 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002910 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002911 goto done;
2912 }
2913
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002914 /* throw out any old stored conf requests */
2915 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002916 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2917 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002918 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002919 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002920 goto done;
2921 }
2922
2923 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2924 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002925 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002926 if (result != L2CAP_CONF_SUCCESS)
2927 goto done;
2928 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929 }
2930
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002931 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002932 sk->sk_err = ECONNRESET;
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02002933 __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002934 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935 goto done;
2936 }
2937
2938 if (flags & 0x01)
2939 goto done;
2940
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002941 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002942
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002943 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002944 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002945
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002946 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002947 chan->next_tx_seq = 0;
2948 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002949 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002950 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002951 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002952
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 l2cap_chan_ready(sk);
2954 }
2955
2956done:
2957 bh_unlock_sock(sk);
2958 return 0;
2959}
2960
2961static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2962{
2963 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2964 struct l2cap_disconn_rsp rsp;
2965 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002966 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002967 struct sock *sk;
2968
2969 scid = __le16_to_cpu(req->scid);
2970 dcid = __le16_to_cpu(req->dcid);
2971
2972 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2973
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002974 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002975 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976 return 0;
2977
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002978 sk = chan->sk;
2979
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002980 rsp.dcid = cpu_to_le16(chan->scid);
2981 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002982 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2983
2984 sk->sk_shutdown = SHUTDOWN_MASK;
2985
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002986 /* don't delete l2cap channel if sk is owned by user */
2987 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002988 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002989 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02002990 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002991 bh_unlock_sock(sk);
2992 return 0;
2993 }
2994
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002995 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996 bh_unlock_sock(sk);
2997
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002998 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999 return 0;
3000}
3001
3002static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3003{
3004 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3005 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003006 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 struct sock *sk;
3008
3009 scid = __le16_to_cpu(rsp->scid);
3010 dcid = __le16_to_cpu(rsp->dcid);
3011
3012 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3013
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003014 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003015 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016 return 0;
3017
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003018 sk = chan->sk;
3019
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02003020 /* don't delete l2cap channel if sk is owned by user */
3021 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003022 l2cap_state_change(chan,BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03003023 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02003024 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02003025 bh_unlock_sock(sk);
3026 return 0;
3027 }
3028
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003029 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030 bh_unlock_sock(sk);
3031
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003032 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033 return 0;
3034}
3035
3036static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3037{
3038 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039 u16 type;
3040
3041 type = __le16_to_cpu(req->type);
3042
3043 BT_DBG("type 0x%4.4x", type);
3044
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003045 if (type == L2CAP_IT_FEAT_MASK) {
3046 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003047 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003048 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3049 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3050 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003051 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003052 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3053 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003054 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003055 feat_mask |= L2CAP_FEAT_EXT_FLOW
3056 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003057
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003058 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003059 l2cap_send_cmd(conn, cmd->ident,
3060 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003061 } else if (type == L2CAP_IT_FIXED_CHAN) {
3062 u8 buf[12];
3063 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
Mat Martineau50a147c2011-11-02 16:18:34 -07003064
3065 if (enable_hs)
3066 l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
3067 else
3068 l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
3069
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003070 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3071 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003072 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003073 l2cap_send_cmd(conn, cmd->ident,
3074 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003075 } else {
3076 struct l2cap_info_rsp rsp;
3077 rsp.type = cpu_to_le16(type);
3078 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3079 l2cap_send_cmd(conn, cmd->ident,
3080 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3081 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082
3083 return 0;
3084}
3085
3086static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3087{
3088 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3089 u16 type, result;
3090
3091 type = __le16_to_cpu(rsp->type);
3092 result = __le16_to_cpu(rsp->result);
3093
3094 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3095
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003096 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3097 if (cmd->ident != conn->info_ident ||
3098 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3099 return 0;
3100
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003101 del_timer(&conn->info_timer);
3102
Ville Tervoadb08ed2010-08-04 09:43:33 +03003103 if (result != L2CAP_IR_SUCCESS) {
3104 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3105 conn->info_ident = 0;
3106
3107 l2cap_conn_start(conn);
3108
3109 return 0;
3110 }
3111
Marcel Holtmann984947d2009-02-06 23:35:19 +01003112 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003113 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003114
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003115 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003116 struct l2cap_info_req req;
3117 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3118
3119 conn->info_ident = l2cap_get_ident(conn);
3120
3121 l2cap_send_cmd(conn, conn->info_ident,
3122 L2CAP_INFO_REQ, sizeof(req), &req);
3123 } else {
3124 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3125 conn->info_ident = 0;
3126
3127 l2cap_conn_start(conn);
3128 }
3129 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003130 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003131 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003132
3133 l2cap_conn_start(conn);
3134 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003135
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136 return 0;
3137}
3138
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003139static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3140 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3141 void *data)
3142{
3143 struct l2cap_create_chan_req *req = data;
3144 struct l2cap_create_chan_rsp rsp;
3145 u16 psm, scid;
3146
3147 if (cmd_len != sizeof(*req))
3148 return -EPROTO;
3149
3150 if (!enable_hs)
3151 return -EINVAL;
3152
3153 psm = le16_to_cpu(req->psm);
3154 scid = le16_to_cpu(req->scid);
3155
3156 BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3157
3158 /* Placeholder: Always reject */
3159 rsp.dcid = 0;
3160 rsp.scid = cpu_to_le16(scid);
3161 rsp.result = L2CAP_CR_NO_MEM;
3162 rsp.status = L2CAP_CS_NO_INFO;
3163
3164 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3165 sizeof(rsp), &rsp);
3166
3167 return 0;
3168}
3169
3170static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3171 struct l2cap_cmd_hdr *cmd, void *data)
3172{
3173 BT_DBG("conn %p", conn);
3174
3175 return l2cap_connect_rsp(conn, cmd, data);
3176}
3177
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003178static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
3179 u16 icid, u16 result)
3180{
3181 struct l2cap_move_chan_rsp rsp;
3182
3183 BT_DBG("icid %d, result %d", icid, result);
3184
3185 rsp.icid = cpu_to_le16(icid);
3186 rsp.result = cpu_to_le16(result);
3187
3188 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
3189}
3190
3191static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
3192 struct l2cap_chan *chan, u16 icid, u16 result)
3193{
3194 struct l2cap_move_chan_cfm cfm;
3195 u8 ident;
3196
3197 BT_DBG("icid %d, result %d", icid, result);
3198
3199 ident = l2cap_get_ident(conn);
3200 if (chan)
3201 chan->ident = ident;
3202
3203 cfm.icid = cpu_to_le16(icid);
3204 cfm.result = cpu_to_le16(result);
3205
3206 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
3207}
3208
3209static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
3210 u16 icid)
3211{
3212 struct l2cap_move_chan_cfm_rsp rsp;
3213
3214 BT_DBG("icid %d", icid);
3215
3216 rsp.icid = cpu_to_le16(icid);
3217 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
3218}
3219
3220static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
3221 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3222{
3223 struct l2cap_move_chan_req *req = data;
3224 u16 icid = 0;
3225 u16 result = L2CAP_MR_NOT_ALLOWED;
3226
3227 if (cmd_len != sizeof(*req))
3228 return -EPROTO;
3229
3230 icid = le16_to_cpu(req->icid);
3231
3232 BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
3233
3234 if (!enable_hs)
3235 return -EINVAL;
3236
3237 /* Placeholder: Always refuse */
3238 l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
3239
3240 return 0;
3241}
3242
3243static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
3244 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3245{
3246 struct l2cap_move_chan_rsp *rsp = data;
3247 u16 icid, result;
3248
3249 if (cmd_len != sizeof(*rsp))
3250 return -EPROTO;
3251
3252 icid = le16_to_cpu(rsp->icid);
3253 result = le16_to_cpu(rsp->result);
3254
3255 BT_DBG("icid %d, result %d", icid, result);
3256
3257 /* Placeholder: Always unconfirmed */
3258 l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
3259
3260 return 0;
3261}
3262
3263static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
3264 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3265{
3266 struct l2cap_move_chan_cfm *cfm = data;
3267 u16 icid, result;
3268
3269 if (cmd_len != sizeof(*cfm))
3270 return -EPROTO;
3271
3272 icid = le16_to_cpu(cfm->icid);
3273 result = le16_to_cpu(cfm->result);
3274
3275 BT_DBG("icid %d, result %d", icid, result);
3276
3277 l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
3278
3279 return 0;
3280}
3281
3282static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
3283 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3284{
3285 struct l2cap_move_chan_cfm_rsp *rsp = data;
3286 u16 icid;
3287
3288 if (cmd_len != sizeof(*rsp))
3289 return -EPROTO;
3290
3291 icid = le16_to_cpu(rsp->icid);
3292
3293 BT_DBG("icid %d", icid);
3294
3295 return 0;
3296}
3297
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003298static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02003299 u16 to_multiplier)
3300{
3301 u16 max_latency;
3302
3303 if (min > max || min < 6 || max > 3200)
3304 return -EINVAL;
3305
3306 if (to_multiplier < 10 || to_multiplier > 3200)
3307 return -EINVAL;
3308
3309 if (max >= to_multiplier * 8)
3310 return -EINVAL;
3311
3312 max_latency = (to_multiplier * 8 / max) - 1;
3313 if (latency > 499 || latency > max_latency)
3314 return -EINVAL;
3315
3316 return 0;
3317}
3318
3319static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3320 struct l2cap_cmd_hdr *cmd, u8 *data)
3321{
3322 struct hci_conn *hcon = conn->hcon;
3323 struct l2cap_conn_param_update_req *req;
3324 struct l2cap_conn_param_update_rsp rsp;
3325 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003326 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02003327
3328 if (!(hcon->link_mode & HCI_LM_MASTER))
3329 return -EINVAL;
3330
3331 cmd_len = __le16_to_cpu(cmd->len);
3332 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3333 return -EPROTO;
3334
3335 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003336 min = __le16_to_cpu(req->min);
3337 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02003338 latency = __le16_to_cpu(req->latency);
3339 to_multiplier = __le16_to_cpu(req->to_multiplier);
3340
3341 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3342 min, max, latency, to_multiplier);
3343
3344 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003345
3346 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
3347 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02003348 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3349 else
3350 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3351
3352 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3353 sizeof(rsp), &rsp);
3354
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003355 if (!err)
3356 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
3357
Claudio Takahaside731152011-02-11 19:28:55 -02003358 return 0;
3359}
3360
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003361static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
3362 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
3363{
3364 int err = 0;
3365
3366 switch (cmd->code) {
3367 case L2CAP_COMMAND_REJ:
3368 l2cap_command_rej(conn, cmd, data);
3369 break;
3370
3371 case L2CAP_CONN_REQ:
3372 err = l2cap_connect_req(conn, cmd, data);
3373 break;
3374
3375 case L2CAP_CONN_RSP:
3376 err = l2cap_connect_rsp(conn, cmd, data);
3377 break;
3378
3379 case L2CAP_CONF_REQ:
3380 err = l2cap_config_req(conn, cmd, cmd_len, data);
3381 break;
3382
3383 case L2CAP_CONF_RSP:
3384 err = l2cap_config_rsp(conn, cmd, data);
3385 break;
3386
3387 case L2CAP_DISCONN_REQ:
3388 err = l2cap_disconnect_req(conn, cmd, data);
3389 break;
3390
3391 case L2CAP_DISCONN_RSP:
3392 err = l2cap_disconnect_rsp(conn, cmd, data);
3393 break;
3394
3395 case L2CAP_ECHO_REQ:
3396 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3397 break;
3398
3399 case L2CAP_ECHO_RSP:
3400 break;
3401
3402 case L2CAP_INFO_REQ:
3403 err = l2cap_information_req(conn, cmd, data);
3404 break;
3405
3406 case L2CAP_INFO_RSP:
3407 err = l2cap_information_rsp(conn, cmd, data);
3408 break;
3409
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003410 case L2CAP_CREATE_CHAN_REQ:
3411 err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3412 break;
3413
3414 case L2CAP_CREATE_CHAN_RSP:
3415 err = l2cap_create_channel_rsp(conn, cmd, data);
3416 break;
3417
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003418 case L2CAP_MOVE_CHAN_REQ:
3419 err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
3420 break;
3421
3422 case L2CAP_MOVE_CHAN_RSP:
3423 err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
3424 break;
3425
3426 case L2CAP_MOVE_CHAN_CFM:
3427 err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
3428 break;
3429
3430 case L2CAP_MOVE_CHAN_CFM_RSP:
3431 err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
3432 break;
3433
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003434 default:
3435 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3436 err = -EINVAL;
3437 break;
3438 }
3439
3440 return err;
3441}
3442
3443static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3444 struct l2cap_cmd_hdr *cmd, u8 *data)
3445{
3446 switch (cmd->code) {
3447 case L2CAP_COMMAND_REJ:
3448 return 0;
3449
3450 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003451 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003452
3453 case L2CAP_CONN_PARAM_UPDATE_RSP:
3454 return 0;
3455
3456 default:
3457 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3458 return -EINVAL;
3459 }
3460}
3461
3462static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3463 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003464{
3465 u8 *data = skb->data;
3466 int len = skb->len;
3467 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003468 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469
3470 l2cap_raw_recv(conn, skb);
3471
3472 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003473 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003474 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3475 data += L2CAP_CMD_HDR_SIZE;
3476 len -= L2CAP_CMD_HDR_SIZE;
3477
Al Viro88219a02007-07-29 00:17:25 -07003478 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479
Al Viro88219a02007-07-29 00:17:25 -07003480 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 -07003481
Al Viro88219a02007-07-29 00:17:25 -07003482 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483 BT_DBG("corrupted command");
3484 break;
3485 }
3486
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003487 if (conn->hcon->type == LE_LINK)
3488 err = l2cap_le_sig_cmd(conn, &cmd, data);
3489 else
3490 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003491
3492 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003493 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003494
3495 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496
3497 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003498 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003499 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3500 }
3501
Al Viro88219a02007-07-29 00:17:25 -07003502 data += cmd_len;
3503 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003504 }
3505
3506 kfree_skb(skb);
3507}
3508
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003509static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003510{
3511 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003512 int hdr_size;
3513
3514 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3515 hdr_size = L2CAP_EXT_HDR_SIZE;
3516 else
3517 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003518
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003519 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003520 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003521 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3522 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3523
3524 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003525 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003526 }
3527 return 0;
3528}
3529
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003530static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003531{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003532 u32 control = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003533
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003534 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003535
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003536 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003537
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003538 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003539 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003540 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003541 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003542 }
3543
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003544 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003545 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003546
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003547 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003548
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003549 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003550 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003551 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003552 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003553 }
3554}
3555
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003556static 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 -03003557{
3558 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003559 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003560
3561 bt_cb(skb)->tx_seq = tx_seq;
3562 bt_cb(skb)->sar = sar;
3563
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003564 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003565 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003566 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003567 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003568 }
3569
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003570 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003571
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003572 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003573 if (bt_cb(next_skb)->tx_seq == tx_seq)
3574 return -EINVAL;
3575
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003576 next_tx_seq_offset = __seq_offset(chan,
3577 bt_cb(next_skb)->tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003578
3579 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003580 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003581 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003582 }
3583
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003584 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003585 break;
3586
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003587 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003588
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003589 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003590
3591 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003592}
3593
Mat Martineau84084a32011-07-22 14:54:00 -07003594static void append_skb_frag(struct sk_buff *skb,
3595 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003596{
Mat Martineau84084a32011-07-22 14:54:00 -07003597 /* skb->len reflects data in skb as well as all fragments
3598 * skb->data_len reflects only data in fragments
3599 */
3600 if (!skb_has_frag_list(skb))
3601 skb_shinfo(skb)->frag_list = new_frag;
3602
3603 new_frag->next = NULL;
3604
3605 (*last_frag)->next = new_frag;
3606 *last_frag = new_frag;
3607
3608 skb->len += new_frag->len;
3609 skb->data_len += new_frag->len;
3610 skb->truesize += new_frag->truesize;
3611}
3612
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003613static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
Mat Martineau84084a32011-07-22 14:54:00 -07003614{
3615 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003616
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003617 switch (__get_ctrl_sar(chan, control)) {
3618 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003619 if (chan->sdu)
3620 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003621
Mat Martineau84084a32011-07-22 14:54:00 -07003622 err = chan->ops->recv(chan->data, skb);
3623 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003624
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003625 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003626 if (chan->sdu)
3627 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003628
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003629 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003630 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003631
Mat Martineau84084a32011-07-22 14:54:00 -07003632 if (chan->sdu_len > chan->imtu) {
3633 err = -EMSGSIZE;
3634 break;
3635 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003636
Mat Martineau84084a32011-07-22 14:54:00 -07003637 if (skb->len >= chan->sdu_len)
3638 break;
3639
3640 chan->sdu = skb;
3641 chan->sdu_last_frag = skb;
3642
3643 skb = NULL;
3644 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003645 break;
3646
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003647 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003648 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003649 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003650
Mat Martineau84084a32011-07-22 14:54:00 -07003651 append_skb_frag(chan->sdu, skb,
3652 &chan->sdu_last_frag);
3653 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003654
Mat Martineau84084a32011-07-22 14:54:00 -07003655 if (chan->sdu->len >= chan->sdu_len)
3656 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003657
Mat Martineau84084a32011-07-22 14:54:00 -07003658 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003659 break;
3660
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003661 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003662 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003663 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003664
Mat Martineau84084a32011-07-22 14:54:00 -07003665 append_skb_frag(chan->sdu, skb,
3666 &chan->sdu_last_frag);
3667 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003668
Mat Martineau84084a32011-07-22 14:54:00 -07003669 if (chan->sdu->len != chan->sdu_len)
3670 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003671
Mat Martineau84084a32011-07-22 14:54:00 -07003672 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003673
Mat Martineau84084a32011-07-22 14:54:00 -07003674 if (!err) {
3675 /* Reassembly complete */
3676 chan->sdu = NULL;
3677 chan->sdu_last_frag = NULL;
3678 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003679 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003680 break;
3681 }
3682
Mat Martineau84084a32011-07-22 14:54:00 -07003683 if (err) {
3684 kfree_skb(skb);
3685 kfree_skb(chan->sdu);
3686 chan->sdu = NULL;
3687 chan->sdu_last_frag = NULL;
3688 chan->sdu_len = 0;
3689 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003690
Mat Martineau84084a32011-07-22 14:54:00 -07003691 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003692}
3693
Mat Martineau26f880d2011-07-07 09:39:01 -07003694static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003695{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003696 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003697
Mat Martineau26f880d2011-07-07 09:39:01 -07003698 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003699
Mat Martineau26f880d2011-07-07 09:39:01 -07003700 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3701
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003702 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003703 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Mat Martineau26f880d2011-07-07 09:39:01 -07003704 l2cap_send_sframe(chan, control);
3705
3706 set_bit(CONN_RNR_SENT, &chan->conn_state);
3707
3708 __clear_ack_timer(chan);
3709}
3710
3711static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3712{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003713 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003714
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003715 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003716 goto done;
3717
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003718 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003719 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003720 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003721 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003722 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003723
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003724 __clear_retrans_timer(chan);
3725 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003726
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003727 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003728
3729done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003730 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3731 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003732
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003733 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003734}
3735
Mat Martineaue3281402011-07-07 09:39:02 -07003736void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003737{
Mat Martineaue3281402011-07-07 09:39:02 -07003738 if (chan->mode == L2CAP_MODE_ERTM) {
3739 if (busy)
3740 l2cap_ertm_enter_local_busy(chan);
3741 else
3742 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003743 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003744}
3745
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003746static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003747{
3748 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003749 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003750
Mat Martineaue3281402011-07-07 09:39:02 -07003751 while ((skb = skb_peek(&chan->srej_q)) &&
3752 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3753 int err;
3754
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003755 if (bt_cb(skb)->tx_seq != tx_seq)
3756 break;
3757
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003758 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003759 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003760 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003761
3762 if (err < 0) {
3763 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3764 break;
3765 }
3766
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003767 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
3768 tx_seq = __next_seq(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003769 }
3770}
3771
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003772static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003773{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003774 struct srej_list *l, *tmp;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003775 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003776
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003777 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003778 if (l->tx_seq == tx_seq) {
3779 list_del(&l->list);
3780 kfree(l);
3781 return;
3782 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003783 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003784 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003785 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003786 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003787 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003788 }
3789}
3790
Szymon Jancaef89f22011-11-16 09:32:18 +01003791static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003792{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003793 struct srej_list *new;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003794 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003795
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003796 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003797 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003798 control |= __set_reqseq(chan, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003799 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003800
3801 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Szymon Jancaef89f22011-11-16 09:32:18 +01003802 if (!new)
3803 return -ENOMEM;
3804
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003805 new->tx_seq = chan->expected_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003806
3807 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
3808
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003809 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003810 }
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003811
3812 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Szymon Jancaef89f22011-11-16 09:32:18 +01003813
3814 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003815}
3816
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003817static 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 -03003818{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003819 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003820 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003821 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003822 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003823 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003824 int err = 0;
3825
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003826 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 -03003827 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003828
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003829 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003830 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003831 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003832 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003833 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003834 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003835 }
3836
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003837 chan->expected_ack_seq = req_seq;
3838 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003839
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003840 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003841
3842 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003843 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003844 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003845 goto drop;
3846 }
3847
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003848 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003849 goto drop;
3850
Mat Martineau02f1b642011-06-29 14:35:19 -07003851 if (tx_seq == chan->expected_tx_seq)
3852 goto expected;
3853
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003854 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003855 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003856
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003857 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003858 struct srej_list, list);
3859 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003860 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003861 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003862
3863 list_del(&first->list);
3864 kfree(first);
3865
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003866 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003867 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003868 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003869 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003870 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003871 }
3872 } else {
3873 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003874
3875 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003876 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003877 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003878
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003879 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003880 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003881 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003882 return 0;
3883 }
3884 }
Szymon Jancaef89f22011-11-16 09:32:18 +01003885
3886 err = l2cap_send_srejframe(chan, tx_seq);
3887 if (err < 0) {
3888 l2cap_send_disconn_req(chan->conn, chan, -err);
3889 return err;
3890 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003891 }
3892 } else {
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003893 expected_tx_seq_offset = __seq_offset(chan,
3894 chan->expected_tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003895
3896 /* duplicated tx_seq */
3897 if (tx_seq_offset < expected_tx_seq_offset)
3898 goto drop;
3899
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003900 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003901
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003902 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003903
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003904 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003905 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003906
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003907 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003908 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003909
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003910 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003911
Szymon Jancaef89f22011-11-16 09:32:18 +01003912 err = l2cap_send_srejframe(chan, tx_seq);
3913 if (err < 0) {
3914 l2cap_send_disconn_req(chan->conn, chan, -err);
3915 return err;
3916 }
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003917
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003918 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003919 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003920 return 0;
3921
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003922expected:
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003923 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003924
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003925 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003926 bt_cb(skb)->tx_seq = tx_seq;
3927 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003928 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003929 return 0;
3930 }
3931
Mat Martineau84084a32011-07-22 14:54:00 -07003932 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003933 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
3934
Mat Martineaue3281402011-07-07 09:39:02 -07003935 if (err < 0) {
3936 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3937 return err;
3938 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003939
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003940 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003941 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003942 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003943 }
3944
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003945
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003946 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3947 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003948 l2cap_send_ack(chan);
Gustavo F. Padovan4d611e42011-06-23 19:30:48 -03003949 else
3950 __set_ack_timer(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003951
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003952 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003953
3954drop:
3955 kfree_skb(skb);
3956 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003957}
3958
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003959static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003960{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003961 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003962 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003963
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003964 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003965 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003966
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003967 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003968 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3969 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3970 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003971 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003972 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003973
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003974 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003975 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003976 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003977 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003978 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003979
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003980 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003981 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003982
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003983 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003984 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003985
3986 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003987 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003988 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003989 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003990
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003991 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3992 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003993 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003994 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003995 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003996 }
3997}
3998
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003999static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004000{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004001 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004002
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004003 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004004
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004005 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004006
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004007 chan->expected_ack_seq = tx_seq;
4008 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004009
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004010 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004011 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004012 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004013 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004014 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004015
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004016 if (test_bit(CONN_WAIT_F, &chan->conn_state))
4017 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004018 }
4019}
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004020static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004021{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004022 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004023
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004024 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004025
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004026 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004027
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004028 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004029 chan->expected_ack_seq = tx_seq;
4030 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004031
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004032 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004033 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004034
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004035 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004036
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004037 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004038 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004039 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004040 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004041 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004042 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004043 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004044 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004045 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004046 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004047 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004048 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004049 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004050 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004051 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004052 }
4053 }
4054}
4055
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004056static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004057{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004058 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004059
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004060 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004061
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004062 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004063 chan->expected_ack_seq = tx_seq;
4064 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004065
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004066 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004067 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004068
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004069 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004070 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004071 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004072 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004073 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004074 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004075
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004076 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004077 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004078 } else {
4079 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4080 l2cap_send_sframe(chan, rx_control);
4081 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004082}
4083
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004084static 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 -03004085{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004086 BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004087
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004088 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004089 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004090 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004091 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004092 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004093 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004094 }
4095
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004096 switch (__get_ctrl_super(chan, rx_control)) {
4097 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004098 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004099 break;
4100
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004101 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004102 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004103 break;
4104
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004105 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004106 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004107 break;
4108
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004109 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004110 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004111 break;
4112 }
4113
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004114 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004115 return 0;
4116}
4117
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004118static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
4119{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004120 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004121 u32 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004122 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004123 int len, next_tx_seq_offset, req_seq_offset;
4124
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004125 control = __get_control(chan, skb->data);
4126 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004127 len = skb->len;
4128
4129 /*
4130 * We can just drop the corrupted I-frame here.
4131 * Receiver will miss it and start proper recovery
4132 * procedures and ask retransmission.
4133 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004134 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004135 goto drop;
4136
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004137 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004138 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004139
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004140 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004141 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004142
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004143 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004144 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004145 goto drop;
4146 }
4147
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004148 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004149
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004150 req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4151
4152 next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4153 chan->expected_ack_seq);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004154
4155 /* check for invalid req-seq */
4156 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004157 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004158 goto drop;
4159 }
4160
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004161 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004162 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004163 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004164 goto drop;
4165 }
4166
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004167 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004168 } else {
4169 if (len != 0) {
4170 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004171 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004172 goto drop;
4173 }
4174
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004175 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004176 }
4177
4178 return 0;
4179
4180drop:
4181 kfree_skb(skb);
4182 return 0;
4183}
4184
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4186{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004187 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07004188 struct sock *sk = NULL;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004189 u32 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004190 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004191 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004193 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004194 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004195 BT_DBG("unknown cid 0x%4.4x", cid);
4196 goto drop;
4197 }
4198
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004199 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004200
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004201 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004203 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204 goto drop;
4205
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004206 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004207 case L2CAP_MODE_BASIC:
4208 /* If socket recv buffers overflows we drop data here
4209 * which is *bad* because L2CAP has to be reliable.
4210 * But we don't have any other choice. L2CAP doesn't
4211 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004212
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004213 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004214 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004215
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004216 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004217 goto done;
4218 break;
4219
4220 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004221 if (!sock_owned_by_user(sk)) {
4222 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004223 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004224 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004225 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004226 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004227
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004228 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004229
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004230 case L2CAP_MODE_STREAMING:
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004231 control = __get_control(chan, skb->data);
4232 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004233 len = skb->len;
4234
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004235 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004236 goto drop;
4237
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004238 if (__is_sar_start(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004239 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004240
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004241 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004242 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004243
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004244 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004245 goto drop;
4246
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004247 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004248
Mat Martineau84084a32011-07-22 14:54:00 -07004249 if (chan->expected_tx_seq != tx_seq) {
4250 /* Frame(s) missing - must discard partial SDU */
4251 kfree_skb(chan->sdu);
4252 chan->sdu = NULL;
4253 chan->sdu_last_frag = NULL;
4254 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004255
Mat Martineau84084a32011-07-22 14:54:00 -07004256 /* TODO: Notify userland of missing data */
4257 }
4258
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004259 chan->expected_tx_seq = __next_seq(chan, tx_seq);
Mat Martineau84084a32011-07-22 14:54:00 -07004260
4261 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
4262 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004263
4264 goto done;
4265
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004266 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004267 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004268 break;
4269 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004270
4271drop:
4272 kfree_skb(skb);
4273
4274done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004275 if (sk)
4276 bh_unlock_sock(sk);
4277
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278 return 0;
4279}
4280
Al Viro8e036fc2007-07-29 00:16:36 -07004281static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004283 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004284 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004285
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004286 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
4287 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288 goto drop;
4289
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004290 sk = chan->sk;
4291
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00004292 bh_lock_sock(sk);
4293
Linus Torvalds1da177e2005-04-16 15:20:36 -07004294 BT_DBG("sk %p, len %d", sk, skb->len);
4295
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004296 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297 goto drop;
4298
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004299 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300 goto drop;
4301
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004302 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303 goto done;
4304
4305drop:
4306 kfree_skb(skb);
4307
4308done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004309 if (sk)
4310 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311 return 0;
4312}
4313
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004314static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
4315{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004316 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004317 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004318
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004319 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
4320 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004321 goto drop;
4322
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004323 sk = chan->sk;
4324
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004325 bh_lock_sock(sk);
4326
4327 BT_DBG("sk %p, len %d", sk, skb->len);
4328
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004329 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004330 goto drop;
4331
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004332 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004333 goto drop;
4334
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004335 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004336 goto done;
4337
4338drop:
4339 kfree_skb(skb);
4340
4341done:
4342 if (sk)
4343 bh_unlock_sock(sk);
4344 return 0;
4345}
4346
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4348{
4349 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004350 u16 cid, len;
4351 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352
4353 skb_pull(skb, L2CAP_HDR_SIZE);
4354 cid = __le16_to_cpu(lh->cid);
4355 len = __le16_to_cpu(lh->len);
4356
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004357 if (len != skb->len) {
4358 kfree_skb(skb);
4359 return;
4360 }
4361
Linus Torvalds1da177e2005-04-16 15:20:36 -07004362 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4363
4364 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004365 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004366 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367 l2cap_sig_channel(conn, skb);
4368 break;
4369
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004370 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004371 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372 skb_pull(skb, 2);
4373 l2cap_conless_channel(conn, psm, skb);
4374 break;
4375
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004376 case L2CAP_CID_LE_DATA:
4377 l2cap_att_channel(conn, cid, skb);
4378 break;
4379
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004380 case L2CAP_CID_SMP:
4381 if (smp_sig_channel(conn, skb))
4382 l2cap_conn_del(conn->hcon, EACCES);
4383 break;
4384
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385 default:
4386 l2cap_data_channel(conn, cid, skb);
4387 break;
4388 }
4389}
4390
4391/* ---- L2CAP interface with lower layer (HCI) ---- */
4392
4393static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4394{
4395 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004396 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397
4398 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004399 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004400
4401 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4402
4403 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004404 read_lock(&chan_list_lock);
4405 list_for_each_entry(c, &chan_list, global_l) {
4406 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004407
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004408 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004409 continue;
4410
4411 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004412 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004413 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004414 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004416 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4417 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004418 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004419 lm2 |= HCI_LM_MASTER;
4420 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004422 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004423
4424 return exact ? lm1 : lm2;
4425}
4426
4427static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4428{
Marcel Holtmann01394182006-07-03 10:02:46 +02004429 struct l2cap_conn *conn;
4430
Linus Torvalds1da177e2005-04-16 15:20:36 -07004431 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4432
Ville Tervoacd7d372011-02-10 22:38:49 -03004433 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004434 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435
4436 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004437 conn = l2cap_conn_add(hcon, status);
4438 if (conn)
4439 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004440 } else
Joe Perchese1750722011-06-29 18:18:29 -07004441 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442
4443 return 0;
4444}
4445
Marcel Holtmann2950f212009-02-12 14:02:50 +01004446static int l2cap_disconn_ind(struct hci_conn *hcon)
4447{
4448 struct l2cap_conn *conn = hcon->l2cap_data;
4449
4450 BT_DBG("hcon %p", hcon);
4451
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03004452 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02004453 return HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01004454
4455 return conn->disc_reason;
4456}
4457
4458static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004459{
4460 BT_DBG("hcon %p reason %d", hcon, reason);
4461
Ville Tervoacd7d372011-02-10 22:38:49 -03004462 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004463 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004464
Joe Perchese1750722011-06-29 18:18:29 -07004465 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004466
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467 return 0;
4468}
4469
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004470static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004471{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004472 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004473 return;
4474
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004475 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004476 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004477 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02004478 __set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004479 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004480 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004481 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004482 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004483 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004484 }
4485}
4486
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004487static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004488{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004489 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004490 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004491
Marcel Holtmann01394182006-07-03 10:02:46 +02004492 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004494
Linus Torvalds1da177e2005-04-16 15:20:36 -07004495 BT_DBG("conn %p", conn);
4496
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004497 if (hcon->type == LE_LINK) {
4498 smp_distribute_keys(conn, 0);
4499 del_timer(&conn->security_timer);
4500 }
4501
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004502 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004503
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004504 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004505 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004506
Linus Torvalds1da177e2005-04-16 15:20:36 -07004507 bh_lock_sock(sk);
4508
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004509 BT_DBG("chan->scid %d", chan->scid);
4510
4511 if (chan->scid == L2CAP_CID_LE_DATA) {
4512 if (!status && encrypt) {
4513 chan->sec_level = hcon->sec_level;
4514 l2cap_chan_ready(sk);
4515 }
4516
4517 bh_unlock_sock(sk);
4518 continue;
4519 }
4520
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004521 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004522 bh_unlock_sock(sk);
4523 continue;
4524 }
4525
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004526 if (!status && (chan->state == BT_CONNECTED ||
4527 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004528 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004529 bh_unlock_sock(sk);
4530 continue;
4531 }
4532
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004533 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004534 if (!status) {
4535 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004536 req.scid = cpu_to_le16(chan->scid);
4537 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004538
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004539 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004540 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004541
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004542 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004543 L2CAP_CONN_REQ, sizeof(req), &req);
4544 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004545 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02004546 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004547 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004548 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004549 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004550 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004551
4552 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004553 if (bt_sk(sk)->defer_setup) {
4554 struct sock *parent = bt_sk(sk)->parent;
4555 res = L2CAP_CR_PEND;
4556 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004557 if (parent)
4558 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004559 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004560 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004561 res = L2CAP_CR_SUCCESS;
4562 stat = L2CAP_CS_NO_INFO;
4563 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004564 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004565 l2cap_state_change(chan, BT_DISCONN);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02004566 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004567 res = L2CAP_CR_SEC_BLOCK;
4568 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004569 }
4570
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004571 rsp.scid = cpu_to_le16(chan->dcid);
4572 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004573 rsp.result = cpu_to_le16(res);
4574 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004575 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4576 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004577 }
4578
Linus Torvalds1da177e2005-04-16 15:20:36 -07004579 bh_unlock_sock(sk);
4580 }
4581
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004582 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004583
Linus Torvalds1da177e2005-04-16 15:20:36 -07004584 return 0;
4585}
4586
4587static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4588{
4589 struct l2cap_conn *conn = hcon->l2cap_data;
4590
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004591 if (!conn)
4592 conn = l2cap_conn_add(hcon, 0);
4593
4594 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004595 goto drop;
4596
4597 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4598
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004599 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004600 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004601 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004602 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004603 int len;
4604
4605 if (conn->rx_len) {
4606 BT_ERR("Unexpected start frame (len %d)", skb->len);
4607 kfree_skb(conn->rx_skb);
4608 conn->rx_skb = NULL;
4609 conn->rx_len = 0;
4610 l2cap_conn_unreliable(conn, ECOMM);
4611 }
4612
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004613 /* Start fragment always begin with Basic L2CAP header */
4614 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004615 BT_ERR("Frame is too short (len %d)", skb->len);
4616 l2cap_conn_unreliable(conn, ECOMM);
4617 goto drop;
4618 }
4619
4620 hdr = (struct l2cap_hdr *) skb->data;
4621 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004622 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004623
4624 if (len == skb->len) {
4625 /* Complete frame received */
4626 l2cap_recv_frame(conn, skb);
4627 return 0;
4628 }
4629
4630 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4631
4632 if (skb->len > len) {
4633 BT_ERR("Frame is too long (len %d, expected len %d)",
4634 skb->len, len);
4635 l2cap_conn_unreliable(conn, ECOMM);
4636 goto drop;
4637 }
4638
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004639 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004640
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004641 if (chan && chan->sk) {
4642 struct sock *sk = chan->sk;
4643
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004644 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004645 BT_ERR("Frame exceeding recv MTU (len %d, "
4646 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004647 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004648 bh_unlock_sock(sk);
4649 l2cap_conn_unreliable(conn, ECOMM);
4650 goto drop;
4651 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004652 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004653 }
4654
Linus Torvalds1da177e2005-04-16 15:20:36 -07004655 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004656 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4657 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004658 goto drop;
4659
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004660 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004661 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004662 conn->rx_len = len - skb->len;
4663 } else {
4664 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4665
4666 if (!conn->rx_len) {
4667 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4668 l2cap_conn_unreliable(conn, ECOMM);
4669 goto drop;
4670 }
4671
4672 if (skb->len > conn->rx_len) {
4673 BT_ERR("Fragment is too long (len %d, expected %d)",
4674 skb->len, conn->rx_len);
4675 kfree_skb(conn->rx_skb);
4676 conn->rx_skb = NULL;
4677 conn->rx_len = 0;
4678 l2cap_conn_unreliable(conn, ECOMM);
4679 goto drop;
4680 }
4681
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004682 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004683 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004684 conn->rx_len -= skb->len;
4685
4686 if (!conn->rx_len) {
4687 /* Complete frame received */
4688 l2cap_recv_frame(conn, conn->rx_skb);
4689 conn->rx_skb = NULL;
4690 }
4691 }
4692
4693drop:
4694 kfree_skb(skb);
4695 return 0;
4696}
4697
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004698static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004699{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004700 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004701
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004702 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004703
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004704 list_for_each_entry(c, &chan_list, global_l) {
4705 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004706
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004707 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 +01004708 batostr(&bt_sk(sk)->src),
4709 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004710 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004711 c->scid, c->dcid, c->imtu, c->omtu,
4712 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004713}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004714
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004715 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004716
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004717 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004718}
4719
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004720static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4721{
4722 return single_open(file, l2cap_debugfs_show, inode->i_private);
4723}
4724
4725static const struct file_operations l2cap_debugfs_fops = {
4726 .open = l2cap_debugfs_open,
4727 .read = seq_read,
4728 .llseek = seq_lseek,
4729 .release = single_release,
4730};
4731
4732static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004733
Linus Torvalds1da177e2005-04-16 15:20:36 -07004734static struct hci_proto l2cap_hci_proto = {
4735 .name = "L2CAP",
4736 .id = HCI_PROTO_L2CAP,
4737 .connect_ind = l2cap_connect_ind,
4738 .connect_cfm = l2cap_connect_cfm,
4739 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004740 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004741 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004742 .recv_acldata = l2cap_recv_acldata
4743};
4744
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004745int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004746{
4747 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004748
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004749 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004750 if (err < 0)
4751 return err;
4752
Linus Torvalds1da177e2005-04-16 15:20:36 -07004753 err = hci_register_proto(&l2cap_hci_proto);
4754 if (err < 0) {
4755 BT_ERR("L2CAP protocol registration failed");
4756 bt_sock_unregister(BTPROTO_L2CAP);
4757 goto error;
4758 }
4759
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004760 if (bt_debugfs) {
4761 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4762 bt_debugfs, NULL, &l2cap_debugfs_fops);
4763 if (!l2cap_debugfs)
4764 BT_ERR("Failed to create L2CAP debug file");
4765 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004766
Linus Torvalds1da177e2005-04-16 15:20:36 -07004767 return 0;
4768
4769error:
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004770 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004771 return err;
4772}
4773
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004774void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004775{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004776 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004777
Linus Torvalds1da177e2005-04-16 15:20:36 -07004778 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4779 BT_ERR("L2CAP protocol unregistration failed");
4780
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004781 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004782}
4783
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004784module_param(disable_ertm, bool, 0644);
4785MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03004786
4787module_param(enable_hs, bool, 0644);
4788MODULE_PARM_DESC(enable_hs, "Enable High Speed");