blob: 9262a00bce55215c2f11cde542be2bbb53c2d521 [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;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010063static u8 l2cap_fixed_chan[8] = { 0x02, };
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{
Mat Martineau774e5652011-06-29 14:35:20 -0700223 BT_DBG("chan %p state %d timeout %ld", chan->sk, chan->state, timeout);
Gustavo F. Padovan89bc500e2011-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. Padovan89bc500e2011-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. Padovan89bc500e2011-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 */
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300255 __set_chan_timer(chan, HZ / 5);
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. Padovan89bc500e2011-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. Padovan89bc500e2011-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. Padovan89bc500e2011-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
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300297 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200298}
299
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300300void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300301{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300302 write_lock_bh(&chan_list_lock);
303 list_del(&chan->global_l);
304 write_unlock_bh(&chan_list_lock);
305
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300306 chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300307}
308
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300309static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200310{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300311 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300312 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200313
Marcel Holtmann2950f212009-02-12 14:02:50 +0100314 conn->disc_reason = 0x13;
315
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300316 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200317
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300318 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
Ville Tervob62f3282011-02-10 22:38:50 -0300319 if (conn->hcon->type == LE_LINK) {
320 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300321 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300322 chan->scid = L2CAP_CID_LE_DATA;
323 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300324 } else {
325 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300326 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300327 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300328 }
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300329 } else if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200330 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300331 chan->scid = L2CAP_CID_CONN_LESS;
332 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300333 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200334 } else {
335 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300336 chan->scid = L2CAP_CID_SIGNALING;
337 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300338 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200339 }
340
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300341 chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300342
343 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200344}
345
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900346/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200347 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300348static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200349{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300350 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300351 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200352 struct sock *parent = bt_sk(sk)->parent;
353
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300354 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200355
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300356 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200357
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900358 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300359 /* Delete from channel list */
360 write_lock_bh(&conn->chan_lock);
361 list_del(&chan->list);
362 write_unlock_bh(&conn->chan_lock);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300363 chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300364
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300365 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200366 hci_conn_put(conn->hcon);
367 }
368
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300369 l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200370 sock_set_flag(sk, SOCK_ZAPPED);
371
372 if (err)
373 sk->sk_err = err;
374
375 if (parent) {
376 bt_accept_unlink(sk);
377 parent->sk_data_ready(parent, 0);
378 } else
379 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300380
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300381 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
382 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300383 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300384
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300385 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300386
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300387 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300388 struct srej_list *l, *tmp;
389
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300390 __clear_retrans_timer(chan);
391 __clear_monitor_timer(chan);
392 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300393
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300394 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300395
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300396 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300397 list_del(&l->list);
398 kfree(l);
399 }
400 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200401}
402
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300403static void l2cap_chan_cleanup_listen(struct sock *parent)
404{
405 struct sock *sk;
406
407 BT_DBG("parent %p", parent);
408
409 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300410 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300411 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300412 __clear_chan_timer(chan);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300413 lock_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300414 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300415 release_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300416 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300417 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300418}
419
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300420void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300421{
422 struct l2cap_conn *conn = chan->conn;
423 struct sock *sk = chan->sk;
424
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300425 BT_DBG("chan %p state %d socket %p", chan, chan->state, sk->sk_socket);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300426
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300427 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300428 case BT_LISTEN:
429 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300430
431 l2cap_state_change(chan, BT_CLOSED);
432 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300433 break;
434
435 case BT_CONNECTED:
436 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300437 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300438 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300439 __clear_chan_timer(chan);
440 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300441 l2cap_send_disconn_req(conn, chan, reason);
442 } else
443 l2cap_chan_del(chan, reason);
444 break;
445
446 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300447 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300448 conn->hcon->type == ACL_LINK) {
449 struct l2cap_conn_rsp rsp;
450 __u16 result;
451
452 if (bt_sk(sk)->defer_setup)
453 result = L2CAP_CR_SEC_BLOCK;
454 else
455 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300456 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300457
458 rsp.scid = cpu_to_le16(chan->dcid);
459 rsp.dcid = cpu_to_le16(chan->scid);
460 rsp.result = cpu_to_le16(result);
461 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
462 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
463 sizeof(rsp), &rsp);
464 }
465
466 l2cap_chan_del(chan, reason);
467 break;
468
469 case BT_CONNECT:
470 case BT_DISCONN:
471 l2cap_chan_del(chan, reason);
472 break;
473
474 default:
475 sock_set_flag(sk, SOCK_ZAPPED);
476 break;
477 }
478}
479
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300480static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530481{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300482 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300483 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530484 case BT_SECURITY_HIGH:
485 return HCI_AT_DEDICATED_BONDING_MITM;
486 case BT_SECURITY_MEDIUM:
487 return HCI_AT_DEDICATED_BONDING;
488 default:
489 return HCI_AT_NO_BONDING;
490 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300491 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300492 if (chan->sec_level == BT_SECURITY_LOW)
493 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530494
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300495 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530496 return HCI_AT_NO_BONDING_MITM;
497 else
498 return HCI_AT_NO_BONDING;
499 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300500 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530501 case BT_SECURITY_HIGH:
502 return HCI_AT_GENERAL_BONDING_MITM;
503 case BT_SECURITY_MEDIUM:
504 return HCI_AT_GENERAL_BONDING;
505 default:
506 return HCI_AT_NO_BONDING;
507 }
508 }
509}
510
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200511/* Service level security */
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300512static inline int l2cap_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200513{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300514 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100515 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200516
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300517 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100518
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300519 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200520}
521
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200522static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200523{
524 u8 id;
525
526 /* Get next available identificator.
527 * 1 - 128 are used by kernel.
528 * 129 - 199 are reserved.
529 * 200 - 254 are used by utilities like l2ping, etc.
530 */
531
532 spin_lock_bh(&conn->lock);
533
534 if (++conn->tx_ident > 128)
535 conn->tx_ident = 1;
536
537 id = conn->tx_ident;
538
539 spin_unlock_bh(&conn->lock);
540
541 return id;
542}
543
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300544static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200545{
546 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200547 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200548
549 BT_DBG("code 0x%2.2x", code);
550
551 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300552 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200553
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200554 if (lmp_no_flush_capable(conn->hcon->hdev))
555 flags = ACL_START_NO_FLUSH;
556 else
557 flags = ACL_START;
558
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700559 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
560
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200561 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200562}
563
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300564static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300565{
566 struct sk_buff *skb;
567 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300568 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300569 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200570 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300571
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300572 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300573 return;
574
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300575 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300576 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300577
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300578 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300579
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300580 count = min_t(unsigned int, conn->mtu, hlen);
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +0300581
582 control |= __set_sframe(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300583
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300584 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300585 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300586
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300587 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300588 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300589
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300590 skb = bt_skb_alloc(count, GFP_ATOMIC);
591 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300592 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300593
594 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300595 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300596 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300597 put_unaligned_le16(control, skb_put(skb, 2));
598
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300599 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300600 u16 fcs = crc16(0, (u8 *)lh, count - 2);
601 put_unaligned_le16(fcs, skb_put(skb, 2));
602 }
603
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200604 if (lmp_no_flush_capable(conn->hcon->hdev))
605 flags = ACL_START_NO_FLUSH;
606 else
607 flags = ACL_START;
608
Andrei Emeltchenko15770b12011-10-11 14:04:33 +0300609 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700610
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300611 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300612}
613
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300614static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300615{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300616 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300617 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300618 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300619 } else
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300620 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300621
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300622 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300623
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300624 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300625}
626
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300627static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300628{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300629 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300630}
631
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300632static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200633{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300634 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200635
636 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100637 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
638 return;
639
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300640 if (l2cap_check_security(chan) &&
641 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200642 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300643 req.scid = cpu_to_le16(chan->scid);
644 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200645
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300646 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300647 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200648
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300649 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
650 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200651 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200652 } else {
653 struct l2cap_info_req req;
654 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
655
656 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
657 conn->info_ident = l2cap_get_ident(conn);
658
659 mod_timer(&conn->info_timer, jiffies +
660 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
661
662 l2cap_send_cmd(conn, conn->info_ident,
663 L2CAP_INFO_REQ, sizeof(req), &req);
664 }
665}
666
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300667static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
668{
669 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300670 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300671 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
672
673 switch (mode) {
674 case L2CAP_MODE_ERTM:
675 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
676 case L2CAP_MODE_STREAMING:
677 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
678 default:
679 return 0x00;
680 }
681}
682
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300683static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300684{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300685 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300686 struct l2cap_disconn_req req;
687
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300688 if (!conn)
689 return;
690
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300691 sk = chan->sk;
692
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300693 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300694 __clear_retrans_timer(chan);
695 __clear_monitor_timer(chan);
696 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300697 }
698
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300699 req.dcid = cpu_to_le16(chan->dcid);
700 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300701 l2cap_send_cmd(conn, l2cap_get_ident(conn),
702 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300703
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300704 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300705 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300706}
707
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200709static void l2cap_conn_start(struct l2cap_conn *conn)
710{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300711 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200712
713 BT_DBG("conn %p", conn);
714
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300715 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200716
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300717 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300718 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300719
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200720 bh_lock_sock(sk);
721
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300722 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200723 bh_unlock_sock(sk);
724 continue;
725 }
726
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300727 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300728 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300729
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300730 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300731 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300732 bh_unlock_sock(sk);
733 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200734 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300735
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300736 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
737 && test_bit(CONF_STATE2_DEVICE,
738 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300739 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300740 * so release the lock */
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300741 read_unlock(&conn->chan_lock);
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300742 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300743 read_lock(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300744 bh_unlock_sock(sk);
745 continue;
746 }
747
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300748 req.scid = cpu_to_le16(chan->scid);
749 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300750
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300751 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300752 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300753
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300754 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
755 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300756
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300757 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200758 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300759 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300760 rsp.scid = cpu_to_le16(chan->dcid);
761 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200762
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300763 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100764 if (bt_sk(sk)->defer_setup) {
765 struct sock *parent = bt_sk(sk)->parent;
766 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
767 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +0000768 if (parent)
769 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100770
771 } else {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300772 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100773 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
774 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
775 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200776 } else {
777 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
778 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
779 }
780
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300781 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
782 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300783
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300784 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300785 rsp.result != L2CAP_CR_SUCCESS) {
786 bh_unlock_sock(sk);
787 continue;
788 }
789
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300790 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300791 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300792 l2cap_build_conf_req(chan, buf), buf);
793 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200794 }
795
796 bh_unlock_sock(sk);
797 }
798
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300799 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200800}
801
Ville Tervob62f3282011-02-10 22:38:50 -0300802/* Find socket with cid and source bdaddr.
803 * Returns closest match, locked.
804 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300805static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300806{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300807 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300808
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300809 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300810
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300811 list_for_each_entry(c, &chan_list, global_l) {
812 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300813
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300814 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300815 continue;
816
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300817 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300818 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300819 if (!bacmp(&bt_sk(sk)->src, src)) {
820 read_unlock(&chan_list_lock);
821 return c;
822 }
Ville Tervob62f3282011-02-10 22:38:50 -0300823
824 /* Closest match */
825 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300826 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300827 }
828 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300829
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300830 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300831
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300832 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300833}
834
835static void l2cap_le_conn_ready(struct l2cap_conn *conn)
836{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300837 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300838 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300839
840 BT_DBG("");
841
842 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300843 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300844 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300845 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300846 return;
847
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300848 parent = pchan->sk;
849
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300850 bh_lock_sock(parent);
851
Ville Tervob62f3282011-02-10 22:38:50 -0300852 /* Check for backlog size */
853 if (sk_acceptq_is_full(parent)) {
854 BT_DBG("backlog full %d", parent->sk_ack_backlog);
855 goto clean;
856 }
857
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300858 chan = pchan->ops->new_connection(pchan->data);
859 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300860 goto clean;
861
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300862 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300863
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300864 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300865
866 hci_conn_hold(conn->hcon);
867
Ville Tervob62f3282011-02-10 22:38:50 -0300868 bacpy(&bt_sk(sk)->src, conn->src);
869 bacpy(&bt_sk(sk)->dst, conn->dst);
870
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300871 bt_accept_enqueue(parent, sk);
872
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300873 __l2cap_chan_add(conn, chan);
874
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300875 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300876
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300877 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300878 parent->sk_data_ready(parent, 0);
879
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300880 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300881
882clean:
883 bh_unlock_sock(parent);
884}
885
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300886static void l2cap_chan_ready(struct sock *sk)
887{
888 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
889 struct sock *parent = bt_sk(sk)->parent;
890
891 BT_DBG("sk %p, parent %p", sk, parent);
892
893 chan->conf_state = 0;
894 __clear_chan_timer(chan);
895
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300896 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300897 sk->sk_state_change(sk);
898
899 if (parent)
900 parent->sk_data_ready(parent, 0);
901}
902
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200903static void l2cap_conn_ready(struct l2cap_conn *conn)
904{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300905 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200906
907 BT_DBG("conn %p", conn);
908
Ville Tervob62f3282011-02-10 22:38:50 -0300909 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
910 l2cap_le_conn_ready(conn);
911
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -0300912 if (conn->hcon->out && conn->hcon->type == LE_LINK)
913 smp_conn_security(conn, conn->hcon->pending_sec_level);
914
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300915 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200916
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300917 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300918 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300919
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200920 bh_lock_sock(sk);
921
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300922 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300923 if (smp_conn_security(conn, chan->sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300924 l2cap_chan_ready(sk);
Ville Tervoacd7d372011-02-10 22:38:49 -0300925
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300926 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300927 __clear_chan_timer(chan);
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300928 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200929 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300930
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300931 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300932 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200933
934 bh_unlock_sock(sk);
935 }
936
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300937 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200938}
939
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200940/* Notify sockets that we cannot guaranty reliability anymore */
941static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
942{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300943 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200944
945 BT_DBG("conn %p", conn);
946
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300947 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200948
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300949 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300950 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300951
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +0300952 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200953 sk->sk_err = err;
954 }
955
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300956 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200957}
958
959static void l2cap_info_timeout(unsigned long arg)
960{
961 struct l2cap_conn *conn = (void *) arg;
962
Marcel Holtmann984947d2009-02-06 23:35:19 +0100963 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100964 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100965
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200966 l2cap_conn_start(conn);
967}
968
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300969static void l2cap_conn_del(struct hci_conn *hcon, int err)
970{
971 struct l2cap_conn *conn = hcon->l2cap_data;
972 struct l2cap_chan *chan, *l;
973 struct sock *sk;
974
975 if (!conn)
976 return;
977
978 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
979
980 kfree_skb(conn->rx_skb);
981
982 /* Kill channels */
983 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
984 sk = chan->sk;
985 bh_lock_sock(sk);
986 l2cap_chan_del(chan, err);
987 bh_unlock_sock(sk);
988 chan->ops->close(chan->data);
989 }
990
991 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
992 del_timer_sync(&conn->info_timer);
993
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300994 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) {
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300995 del_timer(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300996 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300997 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300998
999 hcon->l2cap_data = NULL;
1000 kfree(conn);
1001}
1002
1003static void security_timeout(unsigned long arg)
1004{
1005 struct l2cap_conn *conn = (void *) arg;
1006
1007 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1008}
1009
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1011{
Marcel Holtmann01394182006-07-03 10:02:46 +02001012 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013
Marcel Holtmann01394182006-07-03 10:02:46 +02001014 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 return conn;
1016
Marcel Holtmann01394182006-07-03 10:02:46 +02001017 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1018 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020
1021 hcon->l2cap_data = conn;
1022 conn->hcon = hcon;
1023
Marcel Holtmann01394182006-07-03 10:02:46 +02001024 BT_DBG("hcon %p conn %p", hcon, conn);
1025
Ville Tervoacd7d372011-02-10 22:38:49 -03001026 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1027 conn->mtu = hcon->hdev->le_mtu;
1028 else
1029 conn->mtu = hcon->hdev->acl_mtu;
1030
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 conn->src = &hcon->hdev->bdaddr;
1032 conn->dst = &hcon->dst;
1033
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001034 conn->feat_mask = 0;
1035
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001037 rwlock_init(&conn->chan_lock);
1038
1039 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001041 if (hcon->type == LE_LINK)
1042 setup_timer(&conn->security_timer, security_timeout,
1043 (unsigned long) conn);
1044 else
Ville Tervob62f3282011-02-10 22:38:50 -03001045 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +00001046 (unsigned long) conn);
1047
Marcel Holtmann2950f212009-02-12 14:02:50 +01001048 conn->disc_reason = 0x13;
1049
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 return conn;
1051}
1052
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001053static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001055 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001056 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001057 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058}
1059
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061
1062/* Find socket with psm and source bdaddr.
1063 * Returns closest match.
1064 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001065static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001067 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001069 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001070
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001071 list_for_each_entry(c, &chan_list, global_l) {
1072 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001073
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03001074 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 continue;
1076
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001077 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001079 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001080 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001081 return c;
1082 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083
1084 /* Closest match */
1085 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001086 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 }
1088 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001090 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001091
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001092 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093}
1094
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001095int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001097 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 bdaddr_t *src = &bt_sk(sk)->src;
1099 bdaddr_t *dst = &bt_sk(sk)->dst;
1100 struct l2cap_conn *conn;
1101 struct hci_conn *hcon;
1102 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001103 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001104 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001106 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001107 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001109 hdev = hci_get_route(dst, src);
1110 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 return -EHOSTUNREACH;
1112
1113 hci_dev_lock_bh(hdev);
1114
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001115 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001116
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001117 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001118 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001119 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001120 else
1121 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001122 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001123
Ville Tervo30e76272011-02-22 16:10:53 -03001124 if (IS_ERR(hcon)) {
1125 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001127 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128
1129 conn = l2cap_conn_add(hcon, 0);
1130 if (!conn) {
1131 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001132 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 goto done;
1134 }
1135
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 /* Update source addr of the socket */
1137 bacpy(src, conn->src);
1138
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001139 l2cap_chan_add(conn, chan);
1140
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03001141 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001142 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143
1144 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001145 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001146 __clear_chan_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001147 if (l2cap_check_security(chan))
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03001148 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001149 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001150 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 }
1152
Ville Tervo30e76272011-02-22 16:10:53 -03001153 err = 0;
1154
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155done:
1156 hci_dev_unlock_bh(hdev);
1157 hci_dev_put(hdev);
1158 return err;
1159}
1160
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001161int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001162{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001163 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001164 DECLARE_WAITQUEUE(wait, current);
1165 int err = 0;
1166 int timeo = HZ/5;
1167
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001168 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001169 set_current_state(TASK_INTERRUPTIBLE);
1170 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001171 if (!timeo)
1172 timeo = HZ/5;
1173
1174 if (signal_pending(current)) {
1175 err = sock_intr_errno(timeo);
1176 break;
1177 }
1178
1179 release_sock(sk);
1180 timeo = schedule_timeout(timeo);
1181 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001182 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001183
1184 err = sock_error(sk);
1185 if (err)
1186 break;
1187 }
1188 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001189 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001190 return err;
1191}
1192
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001193static void l2cap_monitor_timeout(unsigned long arg)
1194{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001195 struct l2cap_chan *chan = (void *) arg;
1196 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001197
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001198 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001199
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001200 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001201 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001202 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001203 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001204 return;
1205 }
1206
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001207 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001208 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001209
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001210 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001211 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001212}
1213
1214static void l2cap_retrans_timeout(unsigned long arg)
1215{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001216 struct l2cap_chan *chan = (void *) arg;
1217 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001218
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001219 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001220
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001221 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001222 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001223 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001224
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001225 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001226
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001227 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001228 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001229}
1230
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001231static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001232{
1233 struct sk_buff *skb;
1234
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001235 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001236 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001237 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001238 break;
1239
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001240 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001241 kfree_skb(skb);
1242
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001243 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001244 }
1245
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001246 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001247 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001248}
1249
Szymon Janc67c9e842011-07-28 16:24:33 +02001250static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001251{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001252 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001253 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001254
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001255 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001256
Andrei Emeltchenkod57b0e82011-10-11 14:04:31 +03001257 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
1258 lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001259 flags = ACL_START_NO_FLUSH;
1260 else
1261 flags = ACL_START;
1262
Andrei Emeltchenko15770b12011-10-11 14:04:33 +03001263 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001264 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001265}
1266
Szymon Janc67c9e842011-07-28 16:24:33 +02001267static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001268{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001269 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001270 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001271
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001272 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001273 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001274 control |= __set_txseq(chan, chan->next_tx_seq);
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001275 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001276
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001277 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001278 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1279 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001280 }
1281
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001282 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001283
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001284 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001285 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001286}
1287
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001288static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001289{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001290 struct sk_buff *skb, *tx_skb;
1291 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001292
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001293 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001294 if (!skb)
1295 return;
1296
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001297 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001298 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001299 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001300
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001301 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001302 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001303
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001304 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001305
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001306 if (chan->remote_max_tx &&
1307 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001308 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001309 return;
1310 }
1311
1312 tx_skb = skb_clone(skb, GFP_ATOMIC);
1313 bt_cb(skb)->retries++;
1314 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001315 control &= __get_sar_mask(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001316
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001317 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001318 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001319
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001320 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001321 control |= __set_txseq(chan, tx_seq);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001322
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001323 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1324
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001325 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001326 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1327 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1328 }
1329
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001330 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001331}
1332
Szymon Janc67c9e842011-07-28 16:24:33 +02001333static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001334{
1335 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001336 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001337 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001338
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03001339 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001340 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001341
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001342 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001343
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001344 if (chan->remote_max_tx &&
1345 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001346 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001347 break;
1348 }
1349
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001350 tx_skb = skb_clone(skb, GFP_ATOMIC);
1351
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001352 bt_cb(skb)->retries++;
1353
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001354 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001355 control &= __get_sar_mask(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001356
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001357 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001358 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001359
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001360 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001361 control |= __set_txseq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001362 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1363
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001364
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001365 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001366 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1367 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1368 }
1369
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001370 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001371
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001372 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001373
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001374 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1375 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001376
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301377 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001378 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301379
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001380 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001381
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001382 if (skb_queue_is_last(&chan->tx_q, skb))
1383 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001384 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001385 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001386
1387 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001388 }
1389
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001390 return nsent;
1391}
1392
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001393static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001394{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001395 int ret;
1396
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001397 if (!skb_queue_empty(&chan->tx_q))
1398 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001399
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001400 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001401 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001402 return ret;
1403}
1404
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001405static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001406{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001407 u16 control = 0;
1408
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001409 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001410
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001411 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001412 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001413 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001414 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001415 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001416 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001417
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001418 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001419 return;
1420
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001421 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001422 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001423}
1424
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001425static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001426{
1427 struct srej_list *tail;
1428 u16 control;
1429
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001430 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001431 control |= L2CAP_CTRL_FINAL;
1432
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001433 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001434 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001435
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001436 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001437}
1438
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001439static 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 -07001440{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001441 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001442 struct sk_buff **frag;
1443 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001445 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001446 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447
1448 sent += count;
1449 len -= count;
1450
1451 /* Continuation fragments (no L2CAP header) */
1452 frag = &skb_shinfo(skb)->frag_list;
1453 while (len) {
1454 count = min_t(unsigned int, conn->mtu, len);
1455
1456 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1457 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001458 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001459 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1460 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461
1462 sent += count;
1463 len -= count;
1464
1465 frag = &(*frag)->next;
1466 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
1468 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001469}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
Szymon Janc67c9e842011-07-28 16:24:33 +02001471static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001472{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001473 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001474 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001475 struct sk_buff *skb;
1476 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1477 struct l2cap_hdr *lh;
1478
1479 BT_DBG("sk %p len %d", sk, (int)len);
1480
1481 count = min_t(unsigned int, (conn->mtu - hlen), len);
1482 skb = bt_skb_send_alloc(sk, count + hlen,
1483 msg->msg_flags & MSG_DONTWAIT, &err);
1484 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001485 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001486
1487 /* Create L2CAP header */
1488 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001489 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001490 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001491 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001492
1493 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1494 if (unlikely(err < 0)) {
1495 kfree_skb(skb);
1496 return ERR_PTR(err);
1497 }
1498 return skb;
1499}
1500
Szymon Janc67c9e842011-07-28 16:24:33 +02001501static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001502{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001503 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001504 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001505 struct sk_buff *skb;
1506 int err, count, hlen = L2CAP_HDR_SIZE;
1507 struct l2cap_hdr *lh;
1508
1509 BT_DBG("sk %p len %d", sk, (int)len);
1510
1511 count = min_t(unsigned int, (conn->mtu - hlen), len);
1512 skb = bt_skb_send_alloc(sk, count + hlen,
1513 msg->msg_flags & MSG_DONTWAIT, &err);
1514 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001515 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001516
1517 /* Create L2CAP header */
1518 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001519 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001520 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1521
1522 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1523 if (unlikely(err < 0)) {
1524 kfree_skb(skb);
1525 return ERR_PTR(err);
1526 }
1527 return skb;
1528}
1529
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001530static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1531 struct msghdr *msg, size_t len,
1532 u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001533{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001534 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001535 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001536 struct sk_buff *skb;
1537 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1538 struct l2cap_hdr *lh;
1539
1540 BT_DBG("sk %p len %d", sk, (int)len);
1541
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001542 if (!conn)
1543 return ERR_PTR(-ENOTCONN);
1544
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001545 if (sdulen)
1546 hlen += 2;
1547
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001548 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001549 hlen += 2;
1550
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001551 count = min_t(unsigned int, (conn->mtu - hlen), len);
1552 skb = bt_skb_send_alloc(sk, count + hlen,
1553 msg->msg_flags & MSG_DONTWAIT, &err);
1554 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001555 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001556
1557 /* Create L2CAP header */
1558 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001559 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001560 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1561 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001562 if (sdulen)
1563 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001564
1565 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1566 if (unlikely(err < 0)) {
1567 kfree_skb(skb);
1568 return ERR_PTR(err);
1569 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001570
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001571 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001572 put_unaligned_le16(0, skb_put(skb, 2));
1573
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001574 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001575 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576}
1577
Szymon Janc67c9e842011-07-28 16:24:33 +02001578static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001579{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001580 struct sk_buff *skb;
1581 struct sk_buff_head sar_queue;
1582 u16 control;
1583 size_t size = 0;
1584
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001585 skb_queue_head_init(&sar_queue);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001586 control = __set_ctrl_sar(chan, L2CAP_SAR_START);
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001587 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001588 if (IS_ERR(skb))
1589 return PTR_ERR(skb);
1590
1591 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001592 len -= chan->remote_mps;
1593 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001594
1595 while (len > 0) {
1596 size_t buflen;
1597
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001598 if (len > chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001599 control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001600 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001601 } else {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001602 control = __set_ctrl_sar(chan, L2CAP_SAR_END);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001603 buflen = len;
1604 }
1605
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001606 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001607 if (IS_ERR(skb)) {
1608 skb_queue_purge(&sar_queue);
1609 return PTR_ERR(skb);
1610 }
1611
1612 __skb_queue_tail(&sar_queue, skb);
1613 len -= buflen;
1614 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001615 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001616 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1617 if (chan->tx_send_head == NULL)
1618 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001619
1620 return size;
1621}
1622
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001623int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1624{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001625 struct sk_buff *skb;
1626 u16 control;
1627 int err;
1628
1629 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001630 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001631 skb = l2cap_create_connless_pdu(chan, msg, len);
1632 if (IS_ERR(skb))
1633 return PTR_ERR(skb);
1634
1635 l2cap_do_send(chan, skb);
1636 return len;
1637 }
1638
1639 switch (chan->mode) {
1640 case L2CAP_MODE_BASIC:
1641 /* Check outgoing MTU */
1642 if (len > chan->omtu)
1643 return -EMSGSIZE;
1644
1645 /* Create a basic PDU */
1646 skb = l2cap_create_basic_pdu(chan, msg, len);
1647 if (IS_ERR(skb))
1648 return PTR_ERR(skb);
1649
1650 l2cap_do_send(chan, skb);
1651 err = len;
1652 break;
1653
1654 case L2CAP_MODE_ERTM:
1655 case L2CAP_MODE_STREAMING:
1656 /* Entire SDU fits into one PDU */
1657 if (len <= chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001658 control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001659 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1660 0);
1661 if (IS_ERR(skb))
1662 return PTR_ERR(skb);
1663
1664 __skb_queue_tail(&chan->tx_q, skb);
1665
1666 if (chan->tx_send_head == NULL)
1667 chan->tx_send_head = skb;
1668
1669 } else {
1670 /* Segment SDU into multiples PDUs */
1671 err = l2cap_sar_segment_sdu(chan, msg, len);
1672 if (err < 0)
1673 return err;
1674 }
1675
1676 if (chan->mode == L2CAP_MODE_STREAMING) {
1677 l2cap_streaming_send(chan);
1678 err = len;
1679 break;
1680 }
1681
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001682 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1683 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001684 err = len;
1685 break;
1686 }
1687
1688 err = l2cap_ertm_send(chan);
1689 if (err >= 0)
1690 err = len;
1691
1692 break;
1693
1694 default:
1695 BT_DBG("bad state %1.1x", chan->mode);
1696 err = -EBADFD;
1697 }
1698
1699 return err;
1700}
1701
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702/* Copy frame to all raw sockets on that connection */
1703static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1704{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001706 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707
1708 BT_DBG("conn %p", conn);
1709
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001710 read_lock(&conn->chan_lock);
1711 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001712 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001713 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714 continue;
1715
1716 /* Don't send frame to the socket it came from */
1717 if (skb->sk == sk)
1718 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001719 nskb = skb_clone(skb, GFP_ATOMIC);
1720 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 continue;
1722
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001723 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724 kfree_skb(nskb);
1725 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001726 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727}
1728
1729/* ---- L2CAP signalling commands ---- */
1730static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1731 u8 code, u8 ident, u16 dlen, void *data)
1732{
1733 struct sk_buff *skb, **frag;
1734 struct l2cap_cmd_hdr *cmd;
1735 struct l2cap_hdr *lh;
1736 int len, count;
1737
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001738 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1739 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740
1741 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1742 count = min_t(unsigned int, conn->mtu, len);
1743
1744 skb = bt_skb_alloc(count, GFP_ATOMIC);
1745 if (!skb)
1746 return NULL;
1747
1748 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001749 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001750
1751 if (conn->hcon->type == LE_LINK)
1752 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1753 else
1754 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755
1756 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1757 cmd->code = code;
1758 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001759 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760
1761 if (dlen) {
1762 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1763 memcpy(skb_put(skb, count), data, count);
1764 data += count;
1765 }
1766
1767 len -= skb->len;
1768
1769 /* Continuation fragments (no L2CAP header) */
1770 frag = &skb_shinfo(skb)->frag_list;
1771 while (len) {
1772 count = min_t(unsigned int, conn->mtu, len);
1773
1774 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1775 if (!*frag)
1776 goto fail;
1777
1778 memcpy(skb_put(*frag, count), data, count);
1779
1780 len -= count;
1781 data += count;
1782
1783 frag = &(*frag)->next;
1784 }
1785
1786 return skb;
1787
1788fail:
1789 kfree_skb(skb);
1790 return NULL;
1791}
1792
1793static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1794{
1795 struct l2cap_conf_opt *opt = *ptr;
1796 int len;
1797
1798 len = L2CAP_CONF_OPT_SIZE + opt->len;
1799 *ptr += len;
1800
1801 *type = opt->type;
1802 *olen = opt->len;
1803
1804 switch (opt->len) {
1805 case 1:
1806 *val = *((u8 *) opt->val);
1807 break;
1808
1809 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001810 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 break;
1812
1813 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001814 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 break;
1816
1817 default:
1818 *val = (unsigned long) opt->val;
1819 break;
1820 }
1821
1822 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1823 return len;
1824}
1825
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1827{
1828 struct l2cap_conf_opt *opt = *ptr;
1829
1830 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1831
1832 opt->type = type;
1833 opt->len = len;
1834
1835 switch (len) {
1836 case 1:
1837 *((u8 *) opt->val) = val;
1838 break;
1839
1840 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001841 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 break;
1843
1844 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001845 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 break;
1847
1848 default:
1849 memcpy(opt->val, (void *) val, len);
1850 break;
1851 }
1852
1853 *ptr += L2CAP_CONF_OPT_SIZE + len;
1854}
1855
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001856static void l2cap_ack_timeout(unsigned long arg)
1857{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001858 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001859
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001860 bh_lock_sock(chan->sk);
1861 l2cap_send_ack(chan);
1862 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001863}
1864
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001865static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001866{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001867 struct sock *sk = chan->sk;
1868
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001869 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001870 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001871 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001872 chan->num_acked = 0;
1873 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001874
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001875 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1876 (unsigned long) chan);
1877 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1878 (unsigned long) chan);
1879 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001880
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001881 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001882
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001883 INIT_LIST_HEAD(&chan->srej_l);
1884
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001885
1886 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001887}
1888
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001889static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1890{
1891 switch (mode) {
1892 case L2CAP_MODE_STREAMING:
1893 case L2CAP_MODE_ERTM:
1894 if (l2cap_mode_supported(mode, remote_feat_mask))
1895 return mode;
1896 /* fall through */
1897 default:
1898 return L2CAP_MODE_BASIC;
1899 }
1900}
1901
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001902static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
1903{
1904 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
1905}
1906
1907static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
1908{
1909 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
1910 __l2cap_ews_supported(chan))
1911 /* use extended control field */
1912 set_bit(FLAG_EXT_CTRL, &chan->flags);
1913 else
1914 chan->tx_win = min_t(u16, chan->tx_win,
1915 L2CAP_DEFAULT_TX_WINDOW);
1916}
1917
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001918static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001921 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922 void *ptr = req->data;
1923
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001924 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001926 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001927 goto done;
1928
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001929 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001930 case L2CAP_MODE_STREAMING:
1931 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001932 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001933 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001934
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001935 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001936 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001937 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001938 break;
1939 }
1940
1941done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001942 if (chan->imtu != L2CAP_DEFAULT_MTU)
1943 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001944
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001945 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001946 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001947 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1948 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001949 break;
1950
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001951 rfc.mode = L2CAP_MODE_BASIC;
1952 rfc.txwin_size = 0;
1953 rfc.max_transmit = 0;
1954 rfc.retrans_timeout = 0;
1955 rfc.monitor_timeout = 0;
1956 rfc.max_pdu_size = 0;
1957
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001958 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1959 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001960 break;
1961
1962 case L2CAP_MODE_ERTM:
1963 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001964 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001965 rfc.retrans_timeout = 0;
1966 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001967 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001968 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1969 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001970
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001971 l2cap_txwin_setup(chan);
1972
1973 rfc.txwin_size = min_t(u16, chan->tx_win,
1974 L2CAP_DEFAULT_TX_WINDOW);
1975
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001976 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1977 (unsigned long) &rfc);
1978
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001979 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001980 break;
1981
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001982 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001983 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001984 chan->fcs = L2CAP_FCS_NONE;
1985 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001986 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001987
1988 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1989 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
1990 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001991 break;
1992
1993 case L2CAP_MODE_STREAMING:
1994 rfc.mode = L2CAP_MODE_STREAMING;
1995 rfc.txwin_size = 0;
1996 rfc.max_transmit = 0;
1997 rfc.retrans_timeout = 0;
1998 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001999 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002000 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
2001 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002002
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002003 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2004 (unsigned long) &rfc);
2005
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002006 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002007 break;
2008
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002009 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002010 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002011 chan->fcs = L2CAP_FCS_NONE;
2012 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002013 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002014 break;
2015 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002017 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002018 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019
2020 return ptr - data;
2021}
2022
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002023static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002025 struct l2cap_conf_rsp *rsp = data;
2026 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002027 void *req = chan->conf_req;
2028 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002029 int type, hint, olen;
2030 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002031 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002032 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002033 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002035 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002036
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002037 while (len >= L2CAP_CONF_OPT_SIZE) {
2038 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002040 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002041 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002042
2043 switch (type) {
2044 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002045 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002046 break;
2047
2048 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002049 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002050 break;
2051
2052 case L2CAP_CONF_QOS:
2053 break;
2054
Marcel Holtmann6464f352007-10-20 13:39:51 +02002055 case L2CAP_CONF_RFC:
2056 if (olen == sizeof(rfc))
2057 memcpy(&rfc, (void *) val, olen);
2058 break;
2059
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002060 case L2CAP_CONF_FCS:
2061 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002062 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002063
2064 break;
2065
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002066 case L2CAP_CONF_EWS:
2067 if (!enable_hs)
2068 return -ECONNREFUSED;
2069
2070 set_bit(FLAG_EXT_CTRL, &chan->flags);
2071 set_bit(CONF_EWS_RECV, &chan->conf_state);
2072 chan->remote_tx_win = val;
2073 break;
2074
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002075 default:
2076 if (hint)
2077 break;
2078
2079 result = L2CAP_CONF_UNKNOWN;
2080 *((u8 *) ptr++) = type;
2081 break;
2082 }
2083 }
2084
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002085 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002086 goto done;
2087
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002088 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002089 case L2CAP_MODE_STREAMING:
2090 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002091 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002092 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002093 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002094 break;
2095 }
2096
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002097 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002098 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002099
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002100 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002101 }
2102
2103done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002104 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002105 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002106 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002107
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002108 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002109 return -ECONNREFUSED;
2110
2111 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2112 sizeof(rfc), (unsigned long) &rfc);
2113 }
2114
2115
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002116 if (result == L2CAP_CONF_SUCCESS) {
2117 /* Configure output options and let the other side know
2118 * which ones we don't like. */
2119
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002120 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2121 result = L2CAP_CONF_UNACCEPT;
2122 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002123 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002124 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002125 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002126 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002127
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002128 switch (rfc.mode) {
2129 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002130 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002131 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002132 break;
2133
2134 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002135 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2136 chan->remote_tx_win = rfc.txwin_size;
2137 else
2138 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2139
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002140 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002141
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002142 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2143 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002144
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002145 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002146
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002147 rfc.retrans_timeout =
2148 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2149 rfc.monitor_timeout =
2150 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002151
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002152 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002153
2154 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2155 sizeof(rfc), (unsigned long) &rfc);
2156
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002157 break;
2158
2159 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002160 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2161 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002162
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002163 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002164
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002165 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002166
2167 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2168 sizeof(rfc), (unsigned long) &rfc);
2169
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002170 break;
2171
2172 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002173 result = L2CAP_CONF_UNACCEPT;
2174
2175 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002176 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002177 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002178
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002179 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002180 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002181 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002182 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002183 rsp->result = cpu_to_le16(result);
2184 rsp->flags = cpu_to_le16(0x0000);
2185
2186 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187}
2188
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002189static 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 -03002190{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002191 struct l2cap_conf_req *req = data;
2192 void *ptr = req->data;
2193 int type, olen;
2194 unsigned long val;
2195 struct l2cap_conf_rfc rfc;
2196
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002197 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002198
2199 while (len >= L2CAP_CONF_OPT_SIZE) {
2200 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2201
2202 switch (type) {
2203 case L2CAP_CONF_MTU:
2204 if (val < L2CAP_DEFAULT_MIN_MTU) {
2205 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002206 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002207 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002208 chan->imtu = val;
2209 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002210 break;
2211
2212 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002213 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002214 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002215 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002216 break;
2217
2218 case L2CAP_CONF_RFC:
2219 if (olen == sizeof(rfc))
2220 memcpy(&rfc, (void *)val, olen);
2221
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002222 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002223 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002224 return -ECONNREFUSED;
2225
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002226 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002227
2228 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2229 sizeof(rfc), (unsigned long) &rfc);
2230 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002231
2232 case L2CAP_CONF_EWS:
2233 chan->tx_win = min_t(u16, val,
2234 L2CAP_DEFAULT_EXT_WINDOW);
2235 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS,
2236 2, chan->tx_win);
2237 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002238 }
2239 }
2240
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002241 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002242 return -ECONNREFUSED;
2243
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002244 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002245
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002246 if (*result == L2CAP_CONF_SUCCESS) {
2247 switch (rfc.mode) {
2248 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002249 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2250 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2251 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002252 break;
2253 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002254 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002255 }
2256 }
2257
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002258 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002259 req->flags = cpu_to_le16(0x0000);
2260
2261 return ptr - data;
2262}
2263
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002264static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265{
2266 struct l2cap_conf_rsp *rsp = data;
2267 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002269 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002271 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002272 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002273 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274
2275 return ptr - data;
2276}
2277
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002278void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002279{
2280 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002281 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002282 u8 buf[128];
2283
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002284 rsp.scid = cpu_to_le16(chan->dcid);
2285 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002286 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2287 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2288 l2cap_send_cmd(conn, chan->ident,
2289 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2290
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002291 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002292 return;
2293
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002294 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2295 l2cap_build_conf_req(chan, buf), buf);
2296 chan->num_conf_req++;
2297}
2298
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002299static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002300{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002301 int type, olen;
2302 unsigned long val;
2303 struct l2cap_conf_rfc rfc;
2304
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002305 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002306
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002307 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002308 return;
2309
2310 while (len >= L2CAP_CONF_OPT_SIZE) {
2311 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2312
2313 switch (type) {
2314 case L2CAP_CONF_RFC:
2315 if (olen == sizeof(rfc))
2316 memcpy(&rfc, (void *)val, olen);
2317 goto done;
2318 }
2319 }
2320
2321done:
2322 switch (rfc.mode) {
2323 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002324 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2325 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2326 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002327 break;
2328 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002329 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002330 }
2331}
2332
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002333static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2334{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002335 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002336
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002337 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002338 return 0;
2339
2340 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2341 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002342 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002343
2344 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002345 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002346
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002347 l2cap_conn_start(conn);
2348 }
2349
2350 return 0;
2351}
2352
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2354{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2356 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002357 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002358 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002359 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360
2361 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002362 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363
2364 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2365
2366 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002367 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2368 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 result = L2CAP_CR_BAD_PSM;
2370 goto sendresp;
2371 }
2372
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002373 parent = pchan->sk;
2374
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002375 bh_lock_sock(parent);
2376
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002377 /* Check if the ACL is secure enough (if not SDP) */
2378 if (psm != cpu_to_le16(0x0001) &&
2379 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002380 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002381 result = L2CAP_CR_SEC_BLOCK;
2382 goto response;
2383 }
2384
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385 result = L2CAP_CR_NO_MEM;
2386
2387 /* Check for backlog size */
2388 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002389 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390 goto response;
2391 }
2392
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002393 chan = pchan->ops->new_connection(pchan->data);
2394 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 goto response;
2396
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002397 sk = chan->sk;
2398
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002399 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400
2401 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002402 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2403 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002405 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406 goto response;
2407 }
2408
2409 hci_conn_hold(conn->hcon);
2410
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 bacpy(&bt_sk(sk)->src, conn->src);
2412 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002413 chan->psm = psm;
2414 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002416 bt_accept_enqueue(parent, sk);
2417
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002418 __l2cap_chan_add(conn, chan);
2419
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002420 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002422 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002424 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425
Marcel Holtmann984947d2009-02-06 23:35:19 +01002426 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002427 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002428 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002429 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002430 result = L2CAP_CR_PEND;
2431 status = L2CAP_CS_AUTHOR_PEND;
2432 parent->sk_data_ready(parent, 0);
2433 } else {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002434 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002435 result = L2CAP_CR_SUCCESS;
2436 status = L2CAP_CS_NO_INFO;
2437 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002438 } else {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002439 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002440 result = L2CAP_CR_PEND;
2441 status = L2CAP_CS_AUTHEN_PEND;
2442 }
2443 } else {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002444 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002445 result = L2CAP_CR_PEND;
2446 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 }
2448
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002449 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450
2451response:
2452 bh_unlock_sock(parent);
2453
2454sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002455 rsp.scid = cpu_to_le16(scid);
2456 rsp.dcid = cpu_to_le16(dcid);
2457 rsp.result = cpu_to_le16(result);
2458 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002460
2461 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2462 struct l2cap_info_req info;
2463 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2464
2465 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2466 conn->info_ident = l2cap_get_ident(conn);
2467
2468 mod_timer(&conn->info_timer, jiffies +
2469 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2470
2471 l2cap_send_cmd(conn, conn->info_ident,
2472 L2CAP_INFO_REQ, sizeof(info), &info);
2473 }
2474
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002475 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002476 result == L2CAP_CR_SUCCESS) {
2477 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002478 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002479 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002480 l2cap_build_conf_req(chan, buf), buf);
2481 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002482 }
2483
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484 return 0;
2485}
2486
2487static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2488{
2489 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2490 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002491 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492 struct sock *sk;
2493 u8 req[128];
2494
2495 scid = __le16_to_cpu(rsp->scid);
2496 dcid = __le16_to_cpu(rsp->dcid);
2497 result = __le16_to_cpu(rsp->result);
2498 status = __le16_to_cpu(rsp->status);
2499
2500 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2501
2502 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002503 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002504 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002505 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002507 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002508 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002509 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510 }
2511
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002512 sk = chan->sk;
2513
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514 switch (result) {
2515 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002516 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002517 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002518 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002519 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002520
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002521 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002522 break;
2523
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002525 l2cap_build_conf_req(chan, req), req);
2526 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527 break;
2528
2529 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002530 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531 break;
2532
2533 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002534 /* don't delete l2cap channel if sk is owned by user */
2535 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002536 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002537 __clear_chan_timer(chan);
2538 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002539 break;
2540 }
2541
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002542 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543 break;
2544 }
2545
2546 bh_unlock_sock(sk);
2547 return 0;
2548}
2549
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002550static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002551{
2552 /* FCS is enabled only in ERTM or streaming mode, if one or both
2553 * sides request it.
2554 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002555 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002556 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002557 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002558 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002559}
2560
Al Viro88219a02007-07-29 00:17:25 -07002561static 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 -07002562{
2563 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2564 u16 dcid, flags;
2565 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002566 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002568 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002569
2570 dcid = __le16_to_cpu(req->dcid);
2571 flags = __le16_to_cpu(req->flags);
2572
2573 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2574
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002575 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002576 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577 return -ENOENT;
2578
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002579 sk = chan->sk;
2580
David S. Miller033b1142011-07-21 13:38:42 -07002581 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002582 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002583
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002584 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2585 rej.scid = cpu_to_le16(chan->scid);
2586 rej.dcid = cpu_to_le16(chan->dcid);
2587
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002588 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2589 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002590 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002591 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002592
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002593 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002594 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002595 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002596 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002597 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002598 L2CAP_CONF_REJECT, flags), rsp);
2599 goto unlock;
2600 }
2601
2602 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002603 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2604 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605
2606 if (flags & 0x0001) {
2607 /* Incomplete config. Send empty response. */
2608 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002609 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002610 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611 goto unlock;
2612 }
2613
2614 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002615 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002616 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002617 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002619 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002621 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002622 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002623
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002624 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002625 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002626
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002627 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002628 goto unlock;
2629
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002630 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002631 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002632
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002633 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002634
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002635 chan->next_tx_seq = 0;
2636 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002637 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002638 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002639 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002640
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002642 goto unlock;
2643 }
2644
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002645 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002646 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002648 l2cap_build_conf_req(chan, buf), buf);
2649 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650 }
2651
2652unlock:
2653 bh_unlock_sock(sk);
2654 return 0;
2655}
2656
2657static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2658{
2659 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2660 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002661 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002663 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664
2665 scid = __le16_to_cpu(rsp->scid);
2666 flags = __le16_to_cpu(rsp->flags);
2667 result = __le16_to_cpu(rsp->result);
2668
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002669 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2670 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002672 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002673 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674 return 0;
2675
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002676 sk = chan->sk;
2677
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678 switch (result) {
2679 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002680 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681 break;
2682
2683 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002684 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002685 char req[64];
2686
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002687 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002688 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002689 goto done;
2690 }
2691
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002692 /* throw out any old stored conf requests */
2693 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002694 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2695 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002696 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002697 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002698 goto done;
2699 }
2700
2701 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2702 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002703 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002704 if (result != L2CAP_CONF_SUCCESS)
2705 goto done;
2706 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707 }
2708
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002709 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002710 sk->sk_err = ECONNRESET;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002711 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002712 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713 goto done;
2714 }
2715
2716 if (flags & 0x01)
2717 goto done;
2718
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002719 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002721 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002722 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002723
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002724 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002725 chan->next_tx_seq = 0;
2726 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002727 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002728 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002729 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002730
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731 l2cap_chan_ready(sk);
2732 }
2733
2734done:
2735 bh_unlock_sock(sk);
2736 return 0;
2737}
2738
2739static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2740{
2741 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2742 struct l2cap_disconn_rsp rsp;
2743 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002744 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 struct sock *sk;
2746
2747 scid = __le16_to_cpu(req->scid);
2748 dcid = __le16_to_cpu(req->dcid);
2749
2750 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2751
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002752 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002753 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754 return 0;
2755
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002756 sk = chan->sk;
2757
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002758 rsp.dcid = cpu_to_le16(chan->scid);
2759 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2761
2762 sk->sk_shutdown = SHUTDOWN_MASK;
2763
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002764 /* don't delete l2cap channel if sk is owned by user */
2765 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002766 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002767 __clear_chan_timer(chan);
2768 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002769 bh_unlock_sock(sk);
2770 return 0;
2771 }
2772
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002773 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774 bh_unlock_sock(sk);
2775
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002776 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777 return 0;
2778}
2779
2780static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2781{
2782 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2783 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002784 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 struct sock *sk;
2786
2787 scid = __le16_to_cpu(rsp->scid);
2788 dcid = __le16_to_cpu(rsp->dcid);
2789
2790 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2791
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002792 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002793 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794 return 0;
2795
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002796 sk = chan->sk;
2797
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002798 /* don't delete l2cap channel if sk is owned by user */
2799 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002800 l2cap_state_change(chan,BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002801 __clear_chan_timer(chan);
2802 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002803 bh_unlock_sock(sk);
2804 return 0;
2805 }
2806
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002807 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808 bh_unlock_sock(sk);
2809
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002810 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811 return 0;
2812}
2813
2814static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2815{
2816 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817 u16 type;
2818
2819 type = __le16_to_cpu(req->type);
2820
2821 BT_DBG("type 0x%4.4x", type);
2822
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002823 if (type == L2CAP_IT_FEAT_MASK) {
2824 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002825 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002826 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2827 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2828 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002829 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002830 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2831 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03002832 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002833 feat_mask |= L2CAP_FEAT_EXT_FLOW
2834 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03002835
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002836 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002837 l2cap_send_cmd(conn, cmd->ident,
2838 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002839 } else if (type == L2CAP_IT_FIXED_CHAN) {
2840 u8 buf[12];
2841 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2842 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2843 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2844 memcpy(buf + 4, l2cap_fixed_chan, 8);
2845 l2cap_send_cmd(conn, cmd->ident,
2846 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002847 } else {
2848 struct l2cap_info_rsp rsp;
2849 rsp.type = cpu_to_le16(type);
2850 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2851 l2cap_send_cmd(conn, cmd->ident,
2852 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2853 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854
2855 return 0;
2856}
2857
2858static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2859{
2860 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2861 u16 type, result;
2862
2863 type = __le16_to_cpu(rsp->type);
2864 result = __le16_to_cpu(rsp->result);
2865
2866 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2867
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002868 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2869 if (cmd->ident != conn->info_ident ||
2870 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2871 return 0;
2872
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002873 del_timer(&conn->info_timer);
2874
Ville Tervoadb08ed2010-08-04 09:43:33 +03002875 if (result != L2CAP_IR_SUCCESS) {
2876 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2877 conn->info_ident = 0;
2878
2879 l2cap_conn_start(conn);
2880
2881 return 0;
2882 }
2883
Marcel Holtmann984947d2009-02-06 23:35:19 +01002884 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002885 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002886
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002887 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002888 struct l2cap_info_req req;
2889 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2890
2891 conn->info_ident = l2cap_get_ident(conn);
2892
2893 l2cap_send_cmd(conn, conn->info_ident,
2894 L2CAP_INFO_REQ, sizeof(req), &req);
2895 } else {
2896 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2897 conn->info_ident = 0;
2898
2899 l2cap_conn_start(conn);
2900 }
2901 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002902 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002903 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002904
2905 l2cap_conn_start(conn);
2906 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002907
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908 return 0;
2909}
2910
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002911static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002912 u16 to_multiplier)
2913{
2914 u16 max_latency;
2915
2916 if (min > max || min < 6 || max > 3200)
2917 return -EINVAL;
2918
2919 if (to_multiplier < 10 || to_multiplier > 3200)
2920 return -EINVAL;
2921
2922 if (max >= to_multiplier * 8)
2923 return -EINVAL;
2924
2925 max_latency = (to_multiplier * 8 / max) - 1;
2926 if (latency > 499 || latency > max_latency)
2927 return -EINVAL;
2928
2929 return 0;
2930}
2931
2932static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2933 struct l2cap_cmd_hdr *cmd, u8 *data)
2934{
2935 struct hci_conn *hcon = conn->hcon;
2936 struct l2cap_conn_param_update_req *req;
2937 struct l2cap_conn_param_update_rsp rsp;
2938 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002939 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002940
2941 if (!(hcon->link_mode & HCI_LM_MASTER))
2942 return -EINVAL;
2943
2944 cmd_len = __le16_to_cpu(cmd->len);
2945 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2946 return -EPROTO;
2947
2948 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002949 min = __le16_to_cpu(req->min);
2950 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002951 latency = __le16_to_cpu(req->latency);
2952 to_multiplier = __le16_to_cpu(req->to_multiplier);
2953
2954 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2955 min, max, latency, to_multiplier);
2956
2957 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002958
2959 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2960 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002961 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2962 else
2963 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2964
2965 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2966 sizeof(rsp), &rsp);
2967
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002968 if (!err)
2969 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2970
Claudio Takahaside731152011-02-11 19:28:55 -02002971 return 0;
2972}
2973
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002974static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2975 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2976{
2977 int err = 0;
2978
2979 switch (cmd->code) {
2980 case L2CAP_COMMAND_REJ:
2981 l2cap_command_rej(conn, cmd, data);
2982 break;
2983
2984 case L2CAP_CONN_REQ:
2985 err = l2cap_connect_req(conn, cmd, data);
2986 break;
2987
2988 case L2CAP_CONN_RSP:
2989 err = l2cap_connect_rsp(conn, cmd, data);
2990 break;
2991
2992 case L2CAP_CONF_REQ:
2993 err = l2cap_config_req(conn, cmd, cmd_len, data);
2994 break;
2995
2996 case L2CAP_CONF_RSP:
2997 err = l2cap_config_rsp(conn, cmd, data);
2998 break;
2999
3000 case L2CAP_DISCONN_REQ:
3001 err = l2cap_disconnect_req(conn, cmd, data);
3002 break;
3003
3004 case L2CAP_DISCONN_RSP:
3005 err = l2cap_disconnect_rsp(conn, cmd, data);
3006 break;
3007
3008 case L2CAP_ECHO_REQ:
3009 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3010 break;
3011
3012 case L2CAP_ECHO_RSP:
3013 break;
3014
3015 case L2CAP_INFO_REQ:
3016 err = l2cap_information_req(conn, cmd, data);
3017 break;
3018
3019 case L2CAP_INFO_RSP:
3020 err = l2cap_information_rsp(conn, cmd, data);
3021 break;
3022
3023 default:
3024 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3025 err = -EINVAL;
3026 break;
3027 }
3028
3029 return err;
3030}
3031
3032static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3033 struct l2cap_cmd_hdr *cmd, u8 *data)
3034{
3035 switch (cmd->code) {
3036 case L2CAP_COMMAND_REJ:
3037 return 0;
3038
3039 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003040 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003041
3042 case L2CAP_CONN_PARAM_UPDATE_RSP:
3043 return 0;
3044
3045 default:
3046 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3047 return -EINVAL;
3048 }
3049}
3050
3051static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3052 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053{
3054 u8 *data = skb->data;
3055 int len = skb->len;
3056 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003057 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058
3059 l2cap_raw_recv(conn, skb);
3060
3061 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003062 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3064 data += L2CAP_CMD_HDR_SIZE;
3065 len -= L2CAP_CMD_HDR_SIZE;
3066
Al Viro88219a02007-07-29 00:17:25 -07003067 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003068
Al Viro88219a02007-07-29 00:17:25 -07003069 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 -07003070
Al Viro88219a02007-07-29 00:17:25 -07003071 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072 BT_DBG("corrupted command");
3073 break;
3074 }
3075
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003076 if (conn->hcon->type == LE_LINK)
3077 err = l2cap_le_sig_cmd(conn, &cmd, data);
3078 else
3079 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080
3081 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003082 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003083
3084 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085
3086 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003087 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3089 }
3090
Al Viro88219a02007-07-29 00:17:25 -07003091 data += cmd_len;
3092 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003093 }
3094
3095 kfree_skb(skb);
3096}
3097
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003098static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003099{
3100 u16 our_fcs, rcv_fcs;
3101 int hdr_size = L2CAP_HDR_SIZE + 2;
3102
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003103 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003104 skb_trim(skb, skb->len - 2);
3105 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3106 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3107
3108 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003109 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003110 }
3111 return 0;
3112}
3113
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003114static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003115{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003116 u16 control = 0;
3117
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003118 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003119
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003120 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003121
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003122 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003123 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003124 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003125 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003126 }
3127
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003128 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003129 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003130
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003131 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003132
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003133 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003134 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003135 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003136 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003137 }
3138}
3139
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003140static 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 -03003141{
3142 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003143 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003144
3145 bt_cb(skb)->tx_seq = tx_seq;
3146 bt_cb(skb)->sar = sar;
3147
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003148 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003149 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003150 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003151 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003152 }
3153
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003154 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003155 if (tx_seq_offset < 0)
3156 tx_seq_offset += 64;
3157
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003158 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003159 if (bt_cb(next_skb)->tx_seq == tx_seq)
3160 return -EINVAL;
3161
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003162 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003163 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003164 if (next_tx_seq_offset < 0)
3165 next_tx_seq_offset += 64;
3166
3167 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003168 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003169 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003170 }
3171
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003172 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003173 break;
3174
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003175 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003176
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003177 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003178
3179 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003180}
3181
Mat Martineau84084a32011-07-22 14:54:00 -07003182static void append_skb_frag(struct sk_buff *skb,
3183 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003184{
Mat Martineau84084a32011-07-22 14:54:00 -07003185 /* skb->len reflects data in skb as well as all fragments
3186 * skb->data_len reflects only data in fragments
3187 */
3188 if (!skb_has_frag_list(skb))
3189 skb_shinfo(skb)->frag_list = new_frag;
3190
3191 new_frag->next = NULL;
3192
3193 (*last_frag)->next = new_frag;
3194 *last_frag = new_frag;
3195
3196 skb->len += new_frag->len;
3197 skb->data_len += new_frag->len;
3198 skb->truesize += new_frag->truesize;
3199}
3200
3201static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
3202{
3203 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003204
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003205 switch (__get_ctrl_sar(chan, control)) {
3206 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003207 if (chan->sdu)
3208 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003209
Mat Martineau84084a32011-07-22 14:54:00 -07003210 err = chan->ops->recv(chan->data, skb);
3211 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003212
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003213 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003214 if (chan->sdu)
3215 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003216
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003217 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003218 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003219
Mat Martineau84084a32011-07-22 14:54:00 -07003220 if (chan->sdu_len > chan->imtu) {
3221 err = -EMSGSIZE;
3222 break;
3223 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003224
Mat Martineau84084a32011-07-22 14:54:00 -07003225 if (skb->len >= chan->sdu_len)
3226 break;
3227
3228 chan->sdu = skb;
3229 chan->sdu_last_frag = skb;
3230
3231 skb = NULL;
3232 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003233 break;
3234
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003235 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003236 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003237 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003238
Mat Martineau84084a32011-07-22 14:54:00 -07003239 append_skb_frag(chan->sdu, skb,
3240 &chan->sdu_last_frag);
3241 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003242
Mat Martineau84084a32011-07-22 14:54:00 -07003243 if (chan->sdu->len >= chan->sdu_len)
3244 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003245
Mat Martineau84084a32011-07-22 14:54:00 -07003246 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003247 break;
3248
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003249 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003250 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003251 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003252
Mat Martineau84084a32011-07-22 14:54:00 -07003253 append_skb_frag(chan->sdu, skb,
3254 &chan->sdu_last_frag);
3255 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003256
Mat Martineau84084a32011-07-22 14:54:00 -07003257 if (chan->sdu->len != chan->sdu_len)
3258 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003259
Mat Martineau84084a32011-07-22 14:54:00 -07003260 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003261
Mat Martineau84084a32011-07-22 14:54:00 -07003262 if (!err) {
3263 /* Reassembly complete */
3264 chan->sdu = NULL;
3265 chan->sdu_last_frag = NULL;
3266 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003267 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003268 break;
3269 }
3270
Mat Martineau84084a32011-07-22 14:54:00 -07003271 if (err) {
3272 kfree_skb(skb);
3273 kfree_skb(chan->sdu);
3274 chan->sdu = NULL;
3275 chan->sdu_last_frag = NULL;
3276 chan->sdu_len = 0;
3277 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003278
Mat Martineau84084a32011-07-22 14:54:00 -07003279 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003280}
3281
Mat Martineau26f880d2011-07-07 09:39:01 -07003282static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003283{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003284 u16 control;
3285
Mat Martineau26f880d2011-07-07 09:39:01 -07003286 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003287
Mat Martineau26f880d2011-07-07 09:39:01 -07003288 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3289
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003290 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003291 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Mat Martineau26f880d2011-07-07 09:39:01 -07003292 l2cap_send_sframe(chan, control);
3293
3294 set_bit(CONN_RNR_SENT, &chan->conn_state);
3295
3296 __clear_ack_timer(chan);
3297}
3298
3299static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3300{
3301 u16 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003302
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003303 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003304 goto done;
3305
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003306 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003307 control |= L2CAP_CTRL_POLL;
3308 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003309 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003310 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003311
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003312 __clear_retrans_timer(chan);
3313 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003314
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003315 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003316
3317done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003318 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3319 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003320
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003321 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003322}
3323
Mat Martineaue3281402011-07-07 09:39:02 -07003324void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003325{
Mat Martineaue3281402011-07-07 09:39:02 -07003326 if (chan->mode == L2CAP_MODE_ERTM) {
3327 if (busy)
3328 l2cap_ertm_enter_local_busy(chan);
3329 else
3330 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003331 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003332}
3333
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003334static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003335{
3336 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003337 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003338
Mat Martineaue3281402011-07-07 09:39:02 -07003339 while ((skb = skb_peek(&chan->srej_q)) &&
3340 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3341 int err;
3342
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003343 if (bt_cb(skb)->tx_seq != tx_seq)
3344 break;
3345
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003346 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003347 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003348 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003349
3350 if (err < 0) {
3351 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3352 break;
3353 }
3354
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003355 chan->buffer_seq_srej =
3356 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003357 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003358 }
3359}
3360
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003361static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003362{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003363 struct srej_list *l, *tmp;
3364 u16 control;
3365
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003366 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003367 if (l->tx_seq == tx_seq) {
3368 list_del(&l->list);
3369 kfree(l);
3370 return;
3371 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003372 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003373 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003374 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003375 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003376 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003377 }
3378}
3379
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003380static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003381{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003382 struct srej_list *new;
3383 u16 control;
3384
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003385 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003386 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003387 control |= __set_reqseq(chan, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003388 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003389
3390 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003391 new->tx_seq = chan->expected_tx_seq;
3392 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003393 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003394 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003395 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003396}
3397
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003398static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003399{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003400 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003401 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003402 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003403 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003404 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003405 int err = 0;
3406
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003407 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3408 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003409
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003410 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003411 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003412 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003413 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003414 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003415 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003416 }
3417
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003418 chan->expected_ack_seq = req_seq;
3419 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003420
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003421 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003422 if (tx_seq_offset < 0)
3423 tx_seq_offset += 64;
3424
3425 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003426 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003427 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003428 goto drop;
3429 }
3430
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003431 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003432 goto drop;
3433
Mat Martineau02f1b642011-06-29 14:35:19 -07003434 if (tx_seq == chan->expected_tx_seq)
3435 goto expected;
3436
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003437 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003438 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003439
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003440 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003441 struct srej_list, list);
3442 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003443 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003444 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003445
3446 list_del(&first->list);
3447 kfree(first);
3448
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003449 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003450 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003451 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003452 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003453 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003454 }
3455 } else {
3456 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003457
3458 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003459 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003460 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003461
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003462 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003463 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003464 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003465 return 0;
3466 }
3467 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003468 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003469 }
3470 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003471 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003472 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003473 if (expected_tx_seq_offset < 0)
3474 expected_tx_seq_offset += 64;
3475
3476 /* duplicated tx_seq */
3477 if (tx_seq_offset < expected_tx_seq_offset)
3478 goto drop;
3479
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003480 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003481
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003482 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003483
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003484 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003485 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003486
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003487 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003488 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003489
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003490 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003491
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003492 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003493
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003494 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003495 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003496 return 0;
3497
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003498expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003499 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003500
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003501 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003502 bt_cb(skb)->tx_seq = tx_seq;
3503 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003504 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003505 return 0;
3506 }
3507
Mat Martineau84084a32011-07-22 14:54:00 -07003508 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Mat Martineaufadd1922011-07-07 09:39:03 -07003509 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Mat Martineaue3281402011-07-07 09:39:02 -07003510 if (err < 0) {
3511 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3512 return err;
3513 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003514
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003515 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003516 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003517 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003518 }
3519
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003520 __set_ack_timer(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003521
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003522 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3523 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003524 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003525
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003526 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003527
3528drop:
3529 kfree_skb(skb);
3530 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003531}
3532
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003533static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003534{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003535 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan,
3536 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003537
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003538 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003539 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003540
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003541 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003542 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3543 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3544 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003545 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003546 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003547
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003548 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003549 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003550 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003551 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003552 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003553
3554 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003555 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003556
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003557 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003558 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003559
3560 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003561 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003562 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003563 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003564
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003565 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3566 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003567 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003568 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003569 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003570 }
3571}
3572
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003573static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003574{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003575 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003576
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003577 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003578
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003579 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003580
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003581 chan->expected_ack_seq = tx_seq;
3582 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003583
3584 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003585 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003586 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003587 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003588 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003589
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003590 if (test_bit(CONN_WAIT_F, &chan->conn_state))
3591 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003592 }
3593}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003594static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003595{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003596 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003597
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003598 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003599
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003600 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003601
3602 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003603 chan->expected_ack_seq = tx_seq;
3604 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003605
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003606 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003607 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003608
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003609 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003610
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003611 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003612 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003613 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003614 }
3615 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003616 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003617 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003618 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003619 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003620 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003621 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003622 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003623 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003624 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003625 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003626 }
3627 }
3628}
3629
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003630static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003631{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003632 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003633
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003634 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003635
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003636 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003637 chan->expected_ack_seq = tx_seq;
3638 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003639
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003640 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003641 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003642
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003643 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003644 __clear_retrans_timer(chan);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003645 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003646 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003647 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003648 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003649
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003650 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003651 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003652 } else {
3653 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
3654 l2cap_send_sframe(chan, rx_control);
3655 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003656}
3657
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003658static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003659{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003660 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003661
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003662 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003663 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003664 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003665 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003666 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003667 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003668 }
3669
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003670 switch (__get_ctrl_super(chan, rx_control)) {
3671 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003672 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003673 break;
3674
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003675 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003676 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003677 break;
3678
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003679 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003680 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003681 break;
3682
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003683 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003684 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003685 break;
3686 }
3687
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003688 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003689 return 0;
3690}
3691
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003692static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3693{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003694 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003695 u16 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003696 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003697 int len, next_tx_seq_offset, req_seq_offset;
3698
3699 control = get_unaligned_le16(skb->data);
3700 skb_pull(skb, 2);
3701 len = skb->len;
3702
3703 /*
3704 * We can just drop the corrupted I-frame here.
3705 * Receiver will miss it and start proper recovery
3706 * procedures and ask retransmission.
3707 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003708 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003709 goto drop;
3710
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03003711 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003712 len -= 2;
3713
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003714 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003715 len -= 2;
3716
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003717 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003718 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003719 goto drop;
3720 }
3721
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003722 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003723 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003724 if (req_seq_offset < 0)
3725 req_seq_offset += 64;
3726
3727 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003728 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003729 if (next_tx_seq_offset < 0)
3730 next_tx_seq_offset += 64;
3731
3732 /* check for invalid req-seq */
3733 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003734 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003735 goto drop;
3736 }
3737
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03003738 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003739 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003740 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003741 goto drop;
3742 }
3743
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003744 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003745 } else {
3746 if (len != 0) {
3747 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003748 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003749 goto drop;
3750 }
3751
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003752 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003753 }
3754
3755 return 0;
3756
3757drop:
3758 kfree_skb(skb);
3759 return 0;
3760}
3761
Linus Torvalds1da177e2005-04-16 15:20:36 -07003762static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3763{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003764 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003765 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003766 u16 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003767 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003768 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003770 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003771 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772 BT_DBG("unknown cid 0x%4.4x", cid);
3773 goto drop;
3774 }
3775
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003776 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003777
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003778 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03003780 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781 goto drop;
3782
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003783 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003784 case L2CAP_MODE_BASIC:
3785 /* If socket recv buffers overflows we drop data here
3786 * which is *bad* because L2CAP has to be reliable.
3787 * But we don't have any other choice. L2CAP doesn't
3788 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003789
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003790 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003791 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003792
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003793 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003794 goto done;
3795 break;
3796
3797 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003798 if (!sock_owned_by_user(sk)) {
3799 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003800 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003801 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003802 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003803 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003804
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003805 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003806
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003807 case L2CAP_MODE_STREAMING:
3808 control = get_unaligned_le16(skb->data);
3809 skb_pull(skb, 2);
3810 len = skb->len;
3811
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003812 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003813 goto drop;
3814
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003815 if (__is_sar_start(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003816 len -= 2;
3817
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003818 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003819 len -= 2;
3820
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03003821 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003822 goto drop;
3823
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003824 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003825
Mat Martineau84084a32011-07-22 14:54:00 -07003826 if (chan->expected_tx_seq != tx_seq) {
3827 /* Frame(s) missing - must discard partial SDU */
3828 kfree_skb(chan->sdu);
3829 chan->sdu = NULL;
3830 chan->sdu_last_frag = NULL;
3831 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003832
Mat Martineau84084a32011-07-22 14:54:00 -07003833 /* TODO: Notify userland of missing data */
3834 }
3835
3836 chan->expected_tx_seq = (tx_seq + 1) % 64;
3837
3838 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
3839 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003840
3841 goto done;
3842
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003843 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003844 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003845 break;
3846 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003847
3848drop:
3849 kfree_skb(skb);
3850
3851done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003852 if (sk)
3853 bh_unlock_sock(sk);
3854
Linus Torvalds1da177e2005-04-16 15:20:36 -07003855 return 0;
3856}
3857
Al Viro8e036fc2007-07-29 00:16:36 -07003858static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003860 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003861 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003863 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3864 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865 goto drop;
3866
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003867 sk = chan->sk;
3868
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003869 bh_lock_sock(sk);
3870
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871 BT_DBG("sk %p, len %d", sk, skb->len);
3872
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03003873 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874 goto drop;
3875
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003876 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877 goto drop;
3878
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003879 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880 goto done;
3881
3882drop:
3883 kfree_skb(skb);
3884
3885done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003886 if (sk)
3887 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888 return 0;
3889}
3890
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003891static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3892{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003893 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003894 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003895
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003896 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3897 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003898 goto drop;
3899
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003900 sk = chan->sk;
3901
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003902 bh_lock_sock(sk);
3903
3904 BT_DBG("sk %p, len %d", sk, skb->len);
3905
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03003906 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003907 goto drop;
3908
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003909 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003910 goto drop;
3911
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003912 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003913 goto done;
3914
3915drop:
3916 kfree_skb(skb);
3917
3918done:
3919 if (sk)
3920 bh_unlock_sock(sk);
3921 return 0;
3922}
3923
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3925{
3926 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003927 u16 cid, len;
3928 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929
3930 skb_pull(skb, L2CAP_HDR_SIZE);
3931 cid = __le16_to_cpu(lh->cid);
3932 len = __le16_to_cpu(lh->len);
3933
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003934 if (len != skb->len) {
3935 kfree_skb(skb);
3936 return;
3937 }
3938
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3940
3941 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003942 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003943 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944 l2cap_sig_channel(conn, skb);
3945 break;
3946
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003947 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003948 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949 skb_pull(skb, 2);
3950 l2cap_conless_channel(conn, psm, skb);
3951 break;
3952
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003953 case L2CAP_CID_LE_DATA:
3954 l2cap_att_channel(conn, cid, skb);
3955 break;
3956
Anderson Brigliab501d6a2011-06-07 18:46:31 -03003957 case L2CAP_CID_SMP:
3958 if (smp_sig_channel(conn, skb))
3959 l2cap_conn_del(conn->hcon, EACCES);
3960 break;
3961
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962 default:
3963 l2cap_data_channel(conn, cid, skb);
3964 break;
3965 }
3966}
3967
3968/* ---- L2CAP interface with lower layer (HCI) ---- */
3969
3970static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3971{
3972 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003973 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974
3975 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003976 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977
3978 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3979
3980 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003981 read_lock(&chan_list_lock);
3982 list_for_each_entry(c, &chan_list, global_l) {
3983 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003984
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03003985 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986 continue;
3987
3988 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003989 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03003990 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003991 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003993 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3994 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03003995 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003996 lm2 |= HCI_LM_MASTER;
3997 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003999 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004000
4001 return exact ? lm1 : lm2;
4002}
4003
4004static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4005{
Marcel Holtmann01394182006-07-03 10:02:46 +02004006 struct l2cap_conn *conn;
4007
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4009
Ville Tervoacd7d372011-02-10 22:38:49 -03004010 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004011 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004012
4013 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014 conn = l2cap_conn_add(hcon, status);
4015 if (conn)
4016 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004017 } else
Joe Perchese1750722011-06-29 18:18:29 -07004018 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019
4020 return 0;
4021}
4022
Marcel Holtmann2950f212009-02-12 14:02:50 +01004023static int l2cap_disconn_ind(struct hci_conn *hcon)
4024{
4025 struct l2cap_conn *conn = hcon->l2cap_data;
4026
4027 BT_DBG("hcon %p", hcon);
4028
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03004029 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004030 return 0x13;
4031
4032 return conn->disc_reason;
4033}
4034
4035static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036{
4037 BT_DBG("hcon %p reason %d", hcon, reason);
4038
Ville Tervoacd7d372011-02-10 22:38:49 -03004039 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004040 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041
Joe Perchese1750722011-06-29 18:18:29 -07004042 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004043
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044 return 0;
4045}
4046
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004047static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004048{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004049 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004050 return;
4051
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004052 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004053 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004054 __clear_chan_timer(chan);
4055 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004056 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004057 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004058 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004059 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004060 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004061 }
4062}
4063
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004064static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004066 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004067 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068
Marcel Holtmann01394182006-07-03 10:02:46 +02004069 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004070 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004071
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072 BT_DBG("conn %p", conn);
4073
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004074 if (hcon->type == LE_LINK) {
4075 smp_distribute_keys(conn, 0);
4076 del_timer(&conn->security_timer);
4077 }
4078
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004079 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004081 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004082 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004083
Linus Torvalds1da177e2005-04-16 15:20:36 -07004084 bh_lock_sock(sk);
4085
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004086 BT_DBG("chan->scid %d", chan->scid);
4087
4088 if (chan->scid == L2CAP_CID_LE_DATA) {
4089 if (!status && encrypt) {
4090 chan->sec_level = hcon->sec_level;
4091 l2cap_chan_ready(sk);
4092 }
4093
4094 bh_unlock_sock(sk);
4095 continue;
4096 }
4097
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004098 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004099 bh_unlock_sock(sk);
4100 continue;
4101 }
4102
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004103 if (!status && (chan->state == BT_CONNECTED ||
4104 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004105 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004106 bh_unlock_sock(sk);
4107 continue;
4108 }
4109
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004110 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004111 if (!status) {
4112 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004113 req.scid = cpu_to_le16(chan->scid);
4114 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004115
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004116 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004117 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004118
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004119 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004120 L2CAP_CONN_REQ, sizeof(req), &req);
4121 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004122 __clear_chan_timer(chan);
4123 __set_chan_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004124 }
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004125 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004126 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004127 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004128
4129 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004130 if (bt_sk(sk)->defer_setup) {
4131 struct sock *parent = bt_sk(sk)->parent;
4132 res = L2CAP_CR_PEND;
4133 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004134 if (parent)
4135 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004136 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004137 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004138 res = L2CAP_CR_SUCCESS;
4139 stat = L2CAP_CS_NO_INFO;
4140 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004141 } else {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004142 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004143 __set_chan_timer(chan, HZ / 10);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004144 res = L2CAP_CR_SEC_BLOCK;
4145 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004146 }
4147
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004148 rsp.scid = cpu_to_le16(chan->dcid);
4149 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004150 rsp.result = cpu_to_le16(res);
4151 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004152 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4153 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154 }
4155
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156 bh_unlock_sock(sk);
4157 }
4158
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004159 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004160
Linus Torvalds1da177e2005-04-16 15:20:36 -07004161 return 0;
4162}
4163
4164static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4165{
4166 struct l2cap_conn *conn = hcon->l2cap_data;
4167
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004168 if (!conn)
4169 conn = l2cap_conn_add(hcon, 0);
4170
4171 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172 goto drop;
4173
4174 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4175
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004176 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004178 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004179 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004180 int len;
4181
4182 if (conn->rx_len) {
4183 BT_ERR("Unexpected start frame (len %d)", skb->len);
4184 kfree_skb(conn->rx_skb);
4185 conn->rx_skb = NULL;
4186 conn->rx_len = 0;
4187 l2cap_conn_unreliable(conn, ECOMM);
4188 }
4189
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004190 /* Start fragment always begin with Basic L2CAP header */
4191 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192 BT_ERR("Frame is too short (len %d)", skb->len);
4193 l2cap_conn_unreliable(conn, ECOMM);
4194 goto drop;
4195 }
4196
4197 hdr = (struct l2cap_hdr *) skb->data;
4198 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004199 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004200
4201 if (len == skb->len) {
4202 /* Complete frame received */
4203 l2cap_recv_frame(conn, skb);
4204 return 0;
4205 }
4206
4207 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4208
4209 if (skb->len > len) {
4210 BT_ERR("Frame is too long (len %d, expected len %d)",
4211 skb->len, len);
4212 l2cap_conn_unreliable(conn, ECOMM);
4213 goto drop;
4214 }
4215
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004216 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004217
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004218 if (chan && chan->sk) {
4219 struct sock *sk = chan->sk;
4220
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004221 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004222 BT_ERR("Frame exceeding recv MTU (len %d, "
4223 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004224 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004225 bh_unlock_sock(sk);
4226 l2cap_conn_unreliable(conn, ECOMM);
4227 goto drop;
4228 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004229 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004230 }
4231
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004233 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4234 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004235 goto drop;
4236
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004237 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004238 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004239 conn->rx_len = len - skb->len;
4240 } else {
4241 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4242
4243 if (!conn->rx_len) {
4244 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4245 l2cap_conn_unreliable(conn, ECOMM);
4246 goto drop;
4247 }
4248
4249 if (skb->len > conn->rx_len) {
4250 BT_ERR("Fragment is too long (len %d, expected %d)",
4251 skb->len, conn->rx_len);
4252 kfree_skb(conn->rx_skb);
4253 conn->rx_skb = NULL;
4254 conn->rx_len = 0;
4255 l2cap_conn_unreliable(conn, ECOMM);
4256 goto drop;
4257 }
4258
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004259 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004260 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004261 conn->rx_len -= skb->len;
4262
4263 if (!conn->rx_len) {
4264 /* Complete frame received */
4265 l2cap_recv_frame(conn, conn->rx_skb);
4266 conn->rx_skb = NULL;
4267 }
4268 }
4269
4270drop:
4271 kfree_skb(skb);
4272 return 0;
4273}
4274
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004275static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004277 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004279 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004281 list_for_each_entry(c, &chan_list, global_l) {
4282 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004284 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 +01004285 batostr(&bt_sk(sk)->src),
4286 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004287 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004288 c->scid, c->dcid, c->imtu, c->omtu,
4289 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004290}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004291
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004292 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004293
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004294 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295}
4296
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004297static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4298{
4299 return single_open(file, l2cap_debugfs_show, inode->i_private);
4300}
4301
4302static const struct file_operations l2cap_debugfs_fops = {
4303 .open = l2cap_debugfs_open,
4304 .read = seq_read,
4305 .llseek = seq_lseek,
4306 .release = single_release,
4307};
4308
4309static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311static struct hci_proto l2cap_hci_proto = {
4312 .name = "L2CAP",
4313 .id = HCI_PROTO_L2CAP,
4314 .connect_ind = l2cap_connect_ind,
4315 .connect_cfm = l2cap_connect_cfm,
4316 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004317 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004318 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319 .recv_acldata = l2cap_recv_acldata
4320};
4321
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004322int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323{
4324 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004325
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004326 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004327 if (err < 0)
4328 return err;
4329
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330 err = hci_register_proto(&l2cap_hci_proto);
4331 if (err < 0) {
4332 BT_ERR("L2CAP protocol registration failed");
4333 bt_sock_unregister(BTPROTO_L2CAP);
4334 goto error;
4335 }
4336
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004337 if (bt_debugfs) {
4338 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4339 bt_debugfs, NULL, &l2cap_debugfs_fops);
4340 if (!l2cap_debugfs)
4341 BT_ERR("Failed to create L2CAP debug file");
4342 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344 return 0;
4345
4346error:
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004347 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004348 return err;
4349}
4350
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004351void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004353 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354
Linus Torvalds1da177e2005-04-16 15:20:36 -07004355 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4356 BT_ERR("L2CAP protocol unregistration failed");
4357
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004358 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004359}
4360
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004361module_param(disable_ertm, bool, 0644);
4362MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03004363
4364module_param(enable_hs, bool, 0644);
4365MODULE_PARM_DESC(enable_hs, "Enable High Speed");