blob: cf48330a7fdc47216b168a4a4fd00b0635f7c6a2 [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{
Andrei Emeltchenko457f4852011-10-31 16:17:21 +0200223 BT_DBG("chan %p state %d timeout %ld", chan, chan->state, timeout);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300224
Mat Martineau942ecc92011-06-29 14:35:21 -0700225 if (!mod_timer(timer, jiffies + msecs_to_jiffies(timeout)))
Mat Martineau774e5652011-06-29 14:35:20 -0700226 chan_hold(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300227}
228
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300229static void l2cap_clear_timer(struct l2cap_chan *chan, struct timer_list *timer)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300230{
Mat Martineau774e5652011-06-29 14:35:20 -0700231 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300232
Mat Martineau774e5652011-06-29 14:35:20 -0700233 if (timer_pending(timer) && del_timer(timer))
234 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300235}
236
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300237static void l2cap_state_change(struct l2cap_chan *chan, int state)
238{
239 chan->state = state;
240 chan->ops->state_change(chan->data, state);
241}
242
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300243static void l2cap_chan_timeout(unsigned long arg)
244{
245 struct l2cap_chan *chan = (struct l2cap_chan *) arg;
246 struct sock *sk = chan->sk;
247 int reason;
248
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300249 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300250
251 bh_lock_sock(sk);
252
253 if (sock_owned_by_user(sk)) {
254 /* sk is owned by user. Try again later */
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. Padovan89bc5002011-06-03 00:19:47 -0300261 if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300262 reason = ECONNREFUSED;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300263 else if (chan->state == BT_CONNECT &&
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300264 chan->sec_level != BT_SECURITY_SDP)
265 reason = ECONNREFUSED;
266 else
267 reason = ETIMEDOUT;
268
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300269 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300270
271 bh_unlock_sock(sk);
272
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300273 chan->ops->close(chan->data);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300274 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300275}
276
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300277struct l2cap_chan *l2cap_chan_create(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200278{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300279 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200280
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300281 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
282 if (!chan)
283 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200284
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300285 chan->sk = sk;
286
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300287 write_lock_bh(&chan_list_lock);
288 list_add(&chan->global_l, &chan_list);
289 write_unlock_bh(&chan_list_lock);
290
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300291 setup_timer(&chan->chan_timer, l2cap_chan_timeout, (unsigned long) chan);
292
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300293 chan->state = BT_OPEN;
294
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300295 atomic_set(&chan->refcnt, 1);
296
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
Andrei Emeltchenko8f7975b2011-10-13 16:18:54 +0300341 chan->local_id = L2CAP_BESTEFFORT_ID;
342 chan->local_stype = L2CAP_SERV_BESTEFFORT;
343 chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
344 chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
345 chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
346 chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
347
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300348 chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300349
350 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200351}
352
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900353/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200354 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300355static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200356{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300357 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300358 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200359 struct sock *parent = bt_sk(sk)->parent;
360
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300361 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200362
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300363 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200364
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900365 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300366 /* Delete from channel list */
367 write_lock_bh(&conn->chan_lock);
368 list_del(&chan->list);
369 write_unlock_bh(&conn->chan_lock);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300370 chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300371
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300372 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200373 hci_conn_put(conn->hcon);
374 }
375
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300376 l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200377 sock_set_flag(sk, SOCK_ZAPPED);
378
379 if (err)
380 sk->sk_err = err;
381
382 if (parent) {
383 bt_accept_unlink(sk);
384 parent->sk_data_ready(parent, 0);
385 } else
386 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300387
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300388 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
389 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300390 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300391
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300392 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300393
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300394 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300395 struct srej_list *l, *tmp;
396
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300397 __clear_retrans_timer(chan);
398 __clear_monitor_timer(chan);
399 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300400
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300401 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300402
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300403 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300404 list_del(&l->list);
405 kfree(l);
406 }
407 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200408}
409
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300410static void l2cap_chan_cleanup_listen(struct sock *parent)
411{
412 struct sock *sk;
413
414 BT_DBG("parent %p", parent);
415
416 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300417 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300418 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300419 __clear_chan_timer(chan);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300420 lock_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300421 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300422 release_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300423 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300424 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300425}
426
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300427void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300428{
429 struct l2cap_conn *conn = chan->conn;
430 struct sock *sk = chan->sk;
431
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300432 BT_DBG("chan %p state %d socket %p", chan, chan->state, sk->sk_socket);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300433
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300434 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300435 case BT_LISTEN:
436 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300437
438 l2cap_state_change(chan, BT_CLOSED);
439 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300440 break;
441
442 case BT_CONNECTED:
443 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300444 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300445 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300446 __clear_chan_timer(chan);
447 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300448 l2cap_send_disconn_req(conn, chan, reason);
449 } else
450 l2cap_chan_del(chan, reason);
451 break;
452
453 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300454 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300455 conn->hcon->type == ACL_LINK) {
456 struct l2cap_conn_rsp rsp;
457 __u16 result;
458
459 if (bt_sk(sk)->defer_setup)
460 result = L2CAP_CR_SEC_BLOCK;
461 else
462 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300463 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300464
465 rsp.scid = cpu_to_le16(chan->dcid);
466 rsp.dcid = cpu_to_le16(chan->scid);
467 rsp.result = cpu_to_le16(result);
468 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
469 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
470 sizeof(rsp), &rsp);
471 }
472
473 l2cap_chan_del(chan, reason);
474 break;
475
476 case BT_CONNECT:
477 case BT_DISCONN:
478 l2cap_chan_del(chan, reason);
479 break;
480
481 default:
482 sock_set_flag(sk, SOCK_ZAPPED);
483 break;
484 }
485}
486
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300487static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530488{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300489 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300490 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530491 case BT_SECURITY_HIGH:
492 return HCI_AT_DEDICATED_BONDING_MITM;
493 case BT_SECURITY_MEDIUM:
494 return HCI_AT_DEDICATED_BONDING;
495 default:
496 return HCI_AT_NO_BONDING;
497 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300498 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300499 if (chan->sec_level == BT_SECURITY_LOW)
500 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530501
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300502 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530503 return HCI_AT_NO_BONDING_MITM;
504 else
505 return HCI_AT_NO_BONDING;
506 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300507 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530508 case BT_SECURITY_HIGH:
509 return HCI_AT_GENERAL_BONDING_MITM;
510 case BT_SECURITY_MEDIUM:
511 return HCI_AT_GENERAL_BONDING;
512 default:
513 return HCI_AT_NO_BONDING;
514 }
515 }
516}
517
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200518/* Service level security */
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300519static inline int l2cap_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200520{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300521 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100522 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200523
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300524 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100525
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300526 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200527}
528
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200529static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200530{
531 u8 id;
532
533 /* Get next available identificator.
534 * 1 - 128 are used by kernel.
535 * 129 - 199 are reserved.
536 * 200 - 254 are used by utilities like l2ping, etc.
537 */
538
539 spin_lock_bh(&conn->lock);
540
541 if (++conn->tx_ident > 128)
542 conn->tx_ident = 1;
543
544 id = conn->tx_ident;
545
546 spin_unlock_bh(&conn->lock);
547
548 return id;
549}
550
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300551static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200552{
553 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200554 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200555
556 BT_DBG("code 0x%2.2x", code);
557
558 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300559 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200560
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200561 if (lmp_no_flush_capable(conn->hcon->hdev))
562 flags = ACL_START_NO_FLUSH;
563 else
564 flags = ACL_START;
565
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700566 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +0200567 skb->priority = HCI_PRIO_MAX;
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700568
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200569 hci_send_acl(conn->hchan, skb, flags);
570}
571
572static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
573{
574 struct hci_conn *hcon = chan->conn->hcon;
575 u16 flags;
576
577 BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
578 skb->priority);
579
580 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
581 lmp_no_flush_capable(hcon->hdev))
582 flags = ACL_START_NO_FLUSH;
583 else
584 flags = ACL_START;
585
586 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
587 hci_send_acl(chan->conn->hchan, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200588}
589
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300590static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300591{
592 struct sk_buff *skb;
593 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300594 struct l2cap_conn *conn = chan->conn;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300595 int count, hlen;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300596
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300597 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300598 return;
599
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300600 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
601 hlen = L2CAP_EXT_HDR_SIZE;
602 else
603 hlen = L2CAP_ENH_HDR_SIZE;
604
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300605 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300606 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300607
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300608 BT_DBG("chan %p, control 0x%8.8x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300609
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300610 count = min_t(unsigned int, conn->mtu, hlen);
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +0300611
612 control |= __set_sframe(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300613
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300614 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +0300615 control |= __set_ctrl_final(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300616
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300617 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +0300618 control |= __set_ctrl_poll(chan);
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300619
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300620 skb = bt_skb_alloc(count, GFP_ATOMIC);
621 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300622 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300623
624 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300625 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300626 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300627
628 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300629
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300630 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300631 u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
632 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300633 }
634
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200635 skb->priority = HCI_PRIO_MAX;
636 l2cap_do_send(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300637}
638
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300639static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300640{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300641 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300642 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300643 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300644 } else
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300645 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300646
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300647 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300648
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300649 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300650}
651
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300652static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300653{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300654 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300655}
656
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300657static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200658{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300659 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200660
661 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100662 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
663 return;
664
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300665 if (l2cap_check_security(chan) &&
666 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200667 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300668 req.scid = cpu_to_le16(chan->scid);
669 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200670
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300671 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300672 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200673
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300674 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
675 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200676 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200677 } else {
678 struct l2cap_info_req req;
679 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
680
681 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
682 conn->info_ident = l2cap_get_ident(conn);
683
684 mod_timer(&conn->info_timer, jiffies +
685 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
686
687 l2cap_send_cmd(conn, conn->info_ident,
688 L2CAP_INFO_REQ, sizeof(req), &req);
689 }
690}
691
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300692static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
693{
694 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300695 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300696 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
697
698 switch (mode) {
699 case L2CAP_MODE_ERTM:
700 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
701 case L2CAP_MODE_STREAMING:
702 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
703 default:
704 return 0x00;
705 }
706}
707
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300708static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300709{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300710 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300711 struct l2cap_disconn_req req;
712
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300713 if (!conn)
714 return;
715
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300716 sk = chan->sk;
717
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300718 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300719 __clear_retrans_timer(chan);
720 __clear_monitor_timer(chan);
721 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300722 }
723
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300724 req.dcid = cpu_to_le16(chan->dcid);
725 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300726 l2cap_send_cmd(conn, l2cap_get_ident(conn),
727 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300728
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300729 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300730 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300731}
732
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200734static void l2cap_conn_start(struct l2cap_conn *conn)
735{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300736 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200737
738 BT_DBG("conn %p", conn);
739
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300740 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200741
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300742 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300743 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300744
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200745 bh_lock_sock(sk);
746
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300747 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200748 bh_unlock_sock(sk);
749 continue;
750 }
751
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300752 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300753 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300754
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300755 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300756 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300757 bh_unlock_sock(sk);
758 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200759 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300760
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300761 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
762 && test_bit(CONF_STATE2_DEVICE,
763 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300764 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300765 * so release the lock */
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300766 read_unlock(&conn->chan_lock);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300767 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300768 read_lock(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300769 bh_unlock_sock(sk);
770 continue;
771 }
772
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300773 req.scid = cpu_to_le16(chan->scid);
774 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300775
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300776 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300777 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300778
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300779 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
780 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300781
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300782 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200783 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300784 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300785 rsp.scid = cpu_to_le16(chan->dcid);
786 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200787
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300788 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100789 if (bt_sk(sk)->defer_setup) {
790 struct sock *parent = bt_sk(sk)->parent;
791 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
792 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +0000793 if (parent)
794 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100795
796 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300797 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100798 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
799 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
800 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200801 } else {
802 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
803 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
804 }
805
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300806 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
807 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300808
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300809 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300810 rsp.result != L2CAP_CR_SUCCESS) {
811 bh_unlock_sock(sk);
812 continue;
813 }
814
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300815 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300816 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300817 l2cap_build_conf_req(chan, buf), buf);
818 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200819 }
820
821 bh_unlock_sock(sk);
822 }
823
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300824 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200825}
826
Ville Tervob62f3282011-02-10 22:38:50 -0300827/* Find socket with cid and source bdaddr.
828 * Returns closest match, locked.
829 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300830static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300831{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300832 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300833
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300834 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300835
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300836 list_for_each_entry(c, &chan_list, global_l) {
837 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300838
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300839 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300840 continue;
841
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300842 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300843 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300844 if (!bacmp(&bt_sk(sk)->src, src)) {
845 read_unlock(&chan_list_lock);
846 return c;
847 }
Ville Tervob62f3282011-02-10 22:38:50 -0300848
849 /* Closest match */
850 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300851 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300852 }
853 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300854
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300855 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300856
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300857 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300858}
859
860static void l2cap_le_conn_ready(struct l2cap_conn *conn)
861{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300862 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300863 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300864
865 BT_DBG("");
866
867 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300868 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300869 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300870 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300871 return;
872
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300873 parent = pchan->sk;
874
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300875 bh_lock_sock(parent);
876
Ville Tervob62f3282011-02-10 22:38:50 -0300877 /* Check for backlog size */
878 if (sk_acceptq_is_full(parent)) {
879 BT_DBG("backlog full %d", parent->sk_ack_backlog);
880 goto clean;
881 }
882
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300883 chan = pchan->ops->new_connection(pchan->data);
884 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300885 goto clean;
886
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300887 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300888
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300889 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300890
891 hci_conn_hold(conn->hcon);
892
Ville Tervob62f3282011-02-10 22:38:50 -0300893 bacpy(&bt_sk(sk)->src, conn->src);
894 bacpy(&bt_sk(sk)->dst, conn->dst);
895
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300896 bt_accept_enqueue(parent, sk);
897
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300898 __l2cap_chan_add(conn, chan);
899
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300900 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300901
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300902 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300903 parent->sk_data_ready(parent, 0);
904
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300905 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300906
907clean:
908 bh_unlock_sock(parent);
909}
910
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300911static void l2cap_chan_ready(struct sock *sk)
912{
913 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
914 struct sock *parent = bt_sk(sk)->parent;
915
916 BT_DBG("sk %p, parent %p", sk, parent);
917
918 chan->conf_state = 0;
919 __clear_chan_timer(chan);
920
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300921 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300922 sk->sk_state_change(sk);
923
924 if (parent)
925 parent->sk_data_ready(parent, 0);
926}
927
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200928static void l2cap_conn_ready(struct l2cap_conn *conn)
929{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300930 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200931
932 BT_DBG("conn %p", conn);
933
Ville Tervob62f3282011-02-10 22:38:50 -0300934 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
935 l2cap_le_conn_ready(conn);
936
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -0300937 if (conn->hcon->out && conn->hcon->type == LE_LINK)
938 smp_conn_security(conn, conn->hcon->pending_sec_level);
939
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300940 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200941
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300942 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300943 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300944
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200945 bh_lock_sock(sk);
946
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300947 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300948 if (smp_conn_security(conn, chan->sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300949 l2cap_chan_ready(sk);
Ville Tervoacd7d372011-02-10 22:38:49 -0300950
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300951 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300952 __clear_chan_timer(chan);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300953 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200954 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300955
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300956 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300957 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200958
959 bh_unlock_sock(sk);
960 }
961
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300962 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200963}
964
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200965/* Notify sockets that we cannot guaranty reliability anymore */
966static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
967{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300968 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200969
970 BT_DBG("conn %p", conn);
971
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300972 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200973
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300974 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300975 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300976
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +0300977 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200978 sk->sk_err = err;
979 }
980
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300981 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200982}
983
984static void l2cap_info_timeout(unsigned long arg)
985{
986 struct l2cap_conn *conn = (void *) arg;
987
Marcel Holtmann984947d2009-02-06 23:35:19 +0100988 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100989 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100990
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200991 l2cap_conn_start(conn);
992}
993
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300994static void l2cap_conn_del(struct hci_conn *hcon, int err)
995{
996 struct l2cap_conn *conn = hcon->l2cap_data;
997 struct l2cap_chan *chan, *l;
998 struct sock *sk;
999
1000 if (!conn)
1001 return;
1002
1003 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
1004
1005 kfree_skb(conn->rx_skb);
1006
1007 /* Kill channels */
1008 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
1009 sk = chan->sk;
1010 bh_lock_sock(sk);
1011 l2cap_chan_del(chan, err);
1012 bh_unlock_sock(sk);
1013 chan->ops->close(chan->data);
1014 }
1015
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001016 hci_chan_del(conn->hchan);
1017
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001018 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1019 del_timer_sync(&conn->info_timer);
1020
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001021 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) {
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001022 del_timer(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001023 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001024 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001025
1026 hcon->l2cap_data = NULL;
1027 kfree(conn);
1028}
1029
1030static void security_timeout(unsigned long arg)
1031{
1032 struct l2cap_conn *conn = (void *) arg;
1033
1034 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1035}
1036
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1038{
Marcel Holtmann01394182006-07-03 10:02:46 +02001039 struct l2cap_conn *conn = hcon->l2cap_data;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001040 struct hci_chan *hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041
Marcel Holtmann01394182006-07-03 10:02:46 +02001042 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 return conn;
1044
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001045 hchan = hci_chan_create(hcon);
1046 if (!hchan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001049 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1050 if (!conn) {
1051 hci_chan_del(hchan);
1052 return NULL;
1053 }
1054
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 hcon->l2cap_data = conn;
1056 conn->hcon = hcon;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001057 conn->hchan = hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001059 BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
Marcel Holtmann01394182006-07-03 10:02:46 +02001060
Ville Tervoacd7d372011-02-10 22:38:49 -03001061 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1062 conn->mtu = hcon->hdev->le_mtu;
1063 else
1064 conn->mtu = hcon->hdev->acl_mtu;
1065
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 conn->src = &hcon->hdev->bdaddr;
1067 conn->dst = &hcon->dst;
1068
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001069 conn->feat_mask = 0;
1070
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001072 rwlock_init(&conn->chan_lock);
1073
1074 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001076 if (hcon->type == LE_LINK)
1077 setup_timer(&conn->security_timer, security_timeout,
1078 (unsigned long) conn);
1079 else
Ville Tervob62f3282011-02-10 22:38:50 -03001080 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +00001081 (unsigned long) conn);
1082
Marcel Holtmann2950f212009-02-12 14:02:50 +01001083 conn->disc_reason = 0x13;
1084
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 return conn;
1086}
1087
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001088static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001090 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001091 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001092 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093}
1094
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096
1097/* Find socket with psm and source bdaddr.
1098 * Returns closest match.
1099 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001100static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001102 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001104 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001105
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001106 list_for_each_entry(c, &chan_list, global_l) {
1107 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001108
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001109 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 continue;
1111
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001112 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001114 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001115 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001116 return c;
1117 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118
1119 /* Closest match */
1120 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001121 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 }
1123 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001125 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001126
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001127 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128}
1129
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001130int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001132 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 bdaddr_t *src = &bt_sk(sk)->src;
1134 bdaddr_t *dst = &bt_sk(sk)->dst;
1135 struct l2cap_conn *conn;
1136 struct hci_conn *hcon;
1137 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001138 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001139 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001141 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001142 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001144 hdev = hci_get_route(dst, src);
1145 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 return -EHOSTUNREACH;
1147
1148 hci_dev_lock_bh(hdev);
1149
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001150 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001151
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001152 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001153 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001154 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001155 else
1156 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001157 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001158
Ville Tervo30e76272011-02-22 16:10:53 -03001159 if (IS_ERR(hcon)) {
1160 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001162 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163
1164 conn = l2cap_conn_add(hcon, 0);
1165 if (!conn) {
1166 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001167 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 goto done;
1169 }
1170
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 /* Update source addr of the socket */
1172 bacpy(src, conn->src);
1173
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001174 l2cap_chan_add(conn, chan);
1175
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001176 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001177 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178
1179 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001180 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001181 __clear_chan_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001182 if (l2cap_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001183 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001184 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001185 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 }
1187
Ville Tervo30e76272011-02-22 16:10:53 -03001188 err = 0;
1189
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190done:
1191 hci_dev_unlock_bh(hdev);
1192 hci_dev_put(hdev);
1193 return err;
1194}
1195
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001196int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001197{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001198 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001199 DECLARE_WAITQUEUE(wait, current);
1200 int err = 0;
1201 int timeo = HZ/5;
1202
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001203 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001204 set_current_state(TASK_INTERRUPTIBLE);
1205 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001206 if (!timeo)
1207 timeo = HZ/5;
1208
1209 if (signal_pending(current)) {
1210 err = sock_intr_errno(timeo);
1211 break;
1212 }
1213
1214 release_sock(sk);
1215 timeo = schedule_timeout(timeo);
1216 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001217 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001218
1219 err = sock_error(sk);
1220 if (err)
1221 break;
1222 }
1223 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001224 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001225 return err;
1226}
1227
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001228static void l2cap_monitor_timeout(unsigned long arg)
1229{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001230 struct l2cap_chan *chan = (void *) arg;
1231 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001232
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001233 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001234
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001235 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001236 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001237 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001238 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001239 return;
1240 }
1241
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001242 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001243 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001244
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001245 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001246 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001247}
1248
1249static void l2cap_retrans_timeout(unsigned long arg)
1250{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001251 struct l2cap_chan *chan = (void *) arg;
1252 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001253
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001254 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001255
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001256 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001257 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001258 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001259
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001260 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001261
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001262 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001263 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001264}
1265
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001266static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001267{
1268 struct sk_buff *skb;
1269
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001270 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001271 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001272 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001273 break;
1274
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001275 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001276 kfree_skb(skb);
1277
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001278 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001279 }
1280
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001281 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001282 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001283}
1284
Szymon Janc67c9e842011-07-28 16:24:33 +02001285static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001286{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001287 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001288 u32 control;
1289 u16 fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001290
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001291 while ((skb = skb_dequeue(&chan->tx_q))) {
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001292 control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001293 control |= __set_txseq(chan, chan->next_tx_seq);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001294 __put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001295
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001296 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001297 fcs = crc16(0, (u8 *)skb->data,
1298 skb->len - L2CAP_FCS_SIZE);
1299 put_unaligned_le16(fcs,
1300 skb->data + skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001301 }
1302
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001303 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001304
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001305 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001306 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001307}
1308
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001309static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001310{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001311 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001312 u16 fcs;
1313 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001314
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001315 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001316 if (!skb)
1317 return;
1318
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001319 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001320 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001321 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001322
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001323 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001324 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001325
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001326 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001327
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001328 if (chan->remote_max_tx &&
1329 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001330 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001331 return;
1332 }
1333
1334 tx_skb = skb_clone(skb, GFP_ATOMIC);
1335 bt_cb(skb)->retries++;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001336
1337 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001338 control &= __get_sar_mask(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001339
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001340 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001341 control |= __set_ctrl_final(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001342
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001343 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001344 control |= __set_txseq(chan, tx_seq);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001345
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001346 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001347
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001348 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001349 fcs = crc16(0, (u8 *)tx_skb->data,
1350 tx_skb->len - L2CAP_FCS_SIZE);
1351 put_unaligned_le16(fcs,
1352 tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001353 }
1354
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001355 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001356}
1357
Szymon Janc67c9e842011-07-28 16:24:33 +02001358static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001359{
1360 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001361 u16 fcs;
1362 u32 control;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001363 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001364
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001365 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001366 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001367
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001368 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001369
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001370 if (chan->remote_max_tx &&
1371 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001372 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001373 break;
1374 }
1375
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001376 tx_skb = skb_clone(skb, GFP_ATOMIC);
1377
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001378 bt_cb(skb)->retries++;
1379
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001380 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001381 control &= __get_sar_mask(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001382
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001383 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001384 control |= __set_ctrl_final(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001385
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001386 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001387 control |= __set_txseq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001388
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001389 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001390
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001391 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001392 fcs = crc16(0, (u8 *)skb->data,
1393 tx_skb->len - L2CAP_FCS_SIZE);
1394 put_unaligned_le16(fcs, skb->data +
1395 tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001396 }
1397
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001398 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001399
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001400 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001401
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001402 bt_cb(skb)->tx_seq = chan->next_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001403
1404 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001405
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301406 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001407 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301408
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001409 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001410
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001411 if (skb_queue_is_last(&chan->tx_q, skb))
1412 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001413 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001414 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001415
1416 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001417 }
1418
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001419 return nsent;
1420}
1421
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001422static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001423{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001424 int ret;
1425
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001426 if (!skb_queue_empty(&chan->tx_q))
1427 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001428
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001429 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001430 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001431 return ret;
1432}
1433
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001434static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001435{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001436 u32 control = 0;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001437
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001438 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001439
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001440 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001441 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001442 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001443 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001444 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001445 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001446
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001447 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001448 return;
1449
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001450 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001451 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001452}
1453
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001454static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001455{
1456 struct srej_list *tail;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001457 u32 control;
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001458
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001459 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001460 control |= __set_ctrl_final(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001461
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001462 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001463 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001464
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001465 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001466}
1467
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001468static 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 -07001469{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001470 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001471 struct sk_buff **frag;
1472 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001474 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001475 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476
1477 sent += count;
1478 len -= count;
1479
1480 /* Continuation fragments (no L2CAP header) */
1481 frag = &skb_shinfo(skb)->frag_list;
1482 while (len) {
1483 count = min_t(unsigned int, conn->mtu, len);
1484
1485 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1486 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001487 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001488 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1489 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001491 (*frag)->priority = skb->priority;
1492
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 sent += count;
1494 len -= count;
1495
1496 frag = &(*frag)->next;
1497 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498
1499 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001500}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001502static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
1503 struct msghdr *msg, size_t len,
1504 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001505{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001506 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001507 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001508 struct sk_buff *skb;
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001509 int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001510 struct l2cap_hdr *lh;
1511
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001512 BT_DBG("sk %p len %d priority %u", sk, (int)len, priority);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001513
1514 count = min_t(unsigned int, (conn->mtu - hlen), len);
1515 skb = bt_skb_send_alloc(sk, count + hlen,
1516 msg->msg_flags & MSG_DONTWAIT, &err);
1517 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001518 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001519
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001520 skb->priority = priority;
1521
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001522 /* Create L2CAP header */
1523 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001524 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001525 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001526 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001527
1528 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1529 if (unlikely(err < 0)) {
1530 kfree_skb(skb);
1531 return ERR_PTR(err);
1532 }
1533 return skb;
1534}
1535
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001536static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
1537 struct msghdr *msg, size_t len,
1538 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001539{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001540 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001541 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001542 struct sk_buff *skb;
1543 int err, count, hlen = L2CAP_HDR_SIZE;
1544 struct l2cap_hdr *lh;
1545
1546 BT_DBG("sk %p len %d", sk, (int)len);
1547
1548 count = min_t(unsigned int, (conn->mtu - hlen), len);
1549 skb = bt_skb_send_alloc(sk, count + hlen,
1550 msg->msg_flags & MSG_DONTWAIT, &err);
1551 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001552 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001553
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001554 skb->priority = priority;
1555
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001556 /* Create L2CAP header */
1557 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001558 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001559 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1560
1561 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1562 if (unlikely(err < 0)) {
1563 kfree_skb(skb);
1564 return ERR_PTR(err);
1565 }
1566 return skb;
1567}
1568
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001569static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1570 struct msghdr *msg, size_t len,
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001571 u32 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001572{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001573 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001574 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001575 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001576 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001577 struct l2cap_hdr *lh;
1578
1579 BT_DBG("sk %p len %d", sk, (int)len);
1580
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001581 if (!conn)
1582 return ERR_PTR(-ENOTCONN);
1583
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001584 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1585 hlen = L2CAP_EXT_HDR_SIZE;
1586 else
1587 hlen = L2CAP_ENH_HDR_SIZE;
1588
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001589 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001590 hlen += L2CAP_SDULEN_SIZE;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001591
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001592 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001593 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001594
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001595 count = min_t(unsigned int, (conn->mtu - hlen), len);
1596 skb = bt_skb_send_alloc(sk, count + hlen,
1597 msg->msg_flags & MSG_DONTWAIT, &err);
1598 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001599 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001600
1601 /* Create L2CAP header */
1602 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001603 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001604 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001605
1606 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
1607
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001608 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001609 put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001610
1611 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1612 if (unlikely(err < 0)) {
1613 kfree_skb(skb);
1614 return ERR_PTR(err);
1615 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001616
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001617 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001618 put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001619
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001620 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001621 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622}
1623
Szymon Janc67c9e842011-07-28 16:24:33 +02001624static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001625{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001626 struct sk_buff *skb;
1627 struct sk_buff_head sar_queue;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001628 u32 control;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001629 size_t size = 0;
1630
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001631 skb_queue_head_init(&sar_queue);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001632 control = __set_ctrl_sar(chan, L2CAP_SAR_START);
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001633 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001634 if (IS_ERR(skb))
1635 return PTR_ERR(skb);
1636
1637 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001638 len -= chan->remote_mps;
1639 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001640
1641 while (len > 0) {
1642 size_t buflen;
1643
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001644 if (len > chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001645 control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001646 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001647 } else {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001648 control = __set_ctrl_sar(chan, L2CAP_SAR_END);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001649 buflen = len;
1650 }
1651
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001652 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001653 if (IS_ERR(skb)) {
1654 skb_queue_purge(&sar_queue);
1655 return PTR_ERR(skb);
1656 }
1657
1658 __skb_queue_tail(&sar_queue, skb);
1659 len -= buflen;
1660 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001661 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001662 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1663 if (chan->tx_send_head == NULL)
1664 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001665
1666 return size;
1667}
1668
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001669int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
1670 u32 priority)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001671{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001672 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001673 u32 control;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001674 int err;
1675
1676 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001677 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001678 skb = l2cap_create_connless_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001679 if (IS_ERR(skb))
1680 return PTR_ERR(skb);
1681
1682 l2cap_do_send(chan, skb);
1683 return len;
1684 }
1685
1686 switch (chan->mode) {
1687 case L2CAP_MODE_BASIC:
1688 /* Check outgoing MTU */
1689 if (len > chan->omtu)
1690 return -EMSGSIZE;
1691
1692 /* Create a basic PDU */
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001693 skb = l2cap_create_basic_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001694 if (IS_ERR(skb))
1695 return PTR_ERR(skb);
1696
1697 l2cap_do_send(chan, skb);
1698 err = len;
1699 break;
1700
1701 case L2CAP_MODE_ERTM:
1702 case L2CAP_MODE_STREAMING:
1703 /* Entire SDU fits into one PDU */
1704 if (len <= chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001705 control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001706 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1707 0);
1708 if (IS_ERR(skb))
1709 return PTR_ERR(skb);
1710
1711 __skb_queue_tail(&chan->tx_q, skb);
1712
1713 if (chan->tx_send_head == NULL)
1714 chan->tx_send_head = skb;
1715
1716 } else {
1717 /* Segment SDU into multiples PDUs */
1718 err = l2cap_sar_segment_sdu(chan, msg, len);
1719 if (err < 0)
1720 return err;
1721 }
1722
1723 if (chan->mode == L2CAP_MODE_STREAMING) {
1724 l2cap_streaming_send(chan);
1725 err = len;
1726 break;
1727 }
1728
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001729 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1730 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001731 err = len;
1732 break;
1733 }
1734
1735 err = l2cap_ertm_send(chan);
1736 if (err >= 0)
1737 err = len;
1738
1739 break;
1740
1741 default:
1742 BT_DBG("bad state %1.1x", chan->mode);
1743 err = -EBADFD;
1744 }
1745
1746 return err;
1747}
1748
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749/* Copy frame to all raw sockets on that connection */
1750static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1751{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001753 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754
1755 BT_DBG("conn %p", conn);
1756
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001757 read_lock(&conn->chan_lock);
1758 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001759 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001760 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761 continue;
1762
1763 /* Don't send frame to the socket it came from */
1764 if (skb->sk == sk)
1765 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001766 nskb = skb_clone(skb, GFP_ATOMIC);
1767 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 continue;
1769
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001770 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771 kfree_skb(nskb);
1772 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001773 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774}
1775
1776/* ---- L2CAP signalling commands ---- */
1777static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1778 u8 code, u8 ident, u16 dlen, void *data)
1779{
1780 struct sk_buff *skb, **frag;
1781 struct l2cap_cmd_hdr *cmd;
1782 struct l2cap_hdr *lh;
1783 int len, count;
1784
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001785 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1786 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787
1788 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1789 count = min_t(unsigned int, conn->mtu, len);
1790
1791 skb = bt_skb_alloc(count, GFP_ATOMIC);
1792 if (!skb)
1793 return NULL;
1794
1795 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001796 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001797
1798 if (conn->hcon->type == LE_LINK)
1799 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1800 else
1801 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802
1803 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1804 cmd->code = code;
1805 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001806 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807
1808 if (dlen) {
1809 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1810 memcpy(skb_put(skb, count), data, count);
1811 data += count;
1812 }
1813
1814 len -= skb->len;
1815
1816 /* Continuation fragments (no L2CAP header) */
1817 frag = &skb_shinfo(skb)->frag_list;
1818 while (len) {
1819 count = min_t(unsigned int, conn->mtu, len);
1820
1821 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1822 if (!*frag)
1823 goto fail;
1824
1825 memcpy(skb_put(*frag, count), data, count);
1826
1827 len -= count;
1828 data += count;
1829
1830 frag = &(*frag)->next;
1831 }
1832
1833 return skb;
1834
1835fail:
1836 kfree_skb(skb);
1837 return NULL;
1838}
1839
1840static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1841{
1842 struct l2cap_conf_opt *opt = *ptr;
1843 int len;
1844
1845 len = L2CAP_CONF_OPT_SIZE + opt->len;
1846 *ptr += len;
1847
1848 *type = opt->type;
1849 *olen = opt->len;
1850
1851 switch (opt->len) {
1852 case 1:
1853 *val = *((u8 *) opt->val);
1854 break;
1855
1856 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001857 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 break;
1859
1860 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001861 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 break;
1863
1864 default:
1865 *val = (unsigned long) opt->val;
1866 break;
1867 }
1868
1869 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1870 return len;
1871}
1872
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1874{
1875 struct l2cap_conf_opt *opt = *ptr;
1876
1877 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1878
1879 opt->type = type;
1880 opt->len = len;
1881
1882 switch (len) {
1883 case 1:
1884 *((u8 *) opt->val) = val;
1885 break;
1886
1887 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001888 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 break;
1890
1891 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001892 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 break;
1894
1895 default:
1896 memcpy(opt->val, (void *) val, len);
1897 break;
1898 }
1899
1900 *ptr += L2CAP_CONF_OPT_SIZE + len;
1901}
1902
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001903static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
1904{
1905 struct l2cap_conf_efs efs;
1906
1907 switch(chan->mode) {
1908 case L2CAP_MODE_ERTM:
1909 efs.id = chan->local_id;
1910 efs.stype = chan->local_stype;
1911 efs.msdu = cpu_to_le16(chan->local_msdu);
1912 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1913 efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
1914 efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
1915 break;
1916
1917 case L2CAP_MODE_STREAMING:
1918 efs.id = 1;
1919 efs.stype = L2CAP_SERV_BESTEFFORT;
1920 efs.msdu = cpu_to_le16(chan->local_msdu);
1921 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1922 efs.acc_lat = 0;
1923 efs.flush_to = 0;
1924 break;
1925
1926 default:
1927 return;
1928 }
1929
1930 l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
1931 (unsigned long) &efs);
1932}
1933
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001934static void l2cap_ack_timeout(unsigned long arg)
1935{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001936 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001937
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001938 bh_lock_sock(chan->sk);
1939 l2cap_send_ack(chan);
1940 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001941}
1942
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001943static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001944{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001945 struct sock *sk = chan->sk;
1946
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001947 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001948 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001949 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001950 chan->num_acked = 0;
1951 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001952
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001953 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1954 (unsigned long) chan);
1955 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1956 (unsigned long) chan);
1957 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001958
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001959 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001960
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001961 INIT_LIST_HEAD(&chan->srej_l);
1962
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001963
1964 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001965}
1966
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001967static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1968{
1969 switch (mode) {
1970 case L2CAP_MODE_STREAMING:
1971 case L2CAP_MODE_ERTM:
1972 if (l2cap_mode_supported(mode, remote_feat_mask))
1973 return mode;
1974 /* fall through */
1975 default:
1976 return L2CAP_MODE_BASIC;
1977 }
1978}
1979
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001980static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
1981{
1982 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
1983}
1984
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001985static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
1986{
1987 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
1988}
1989
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001990static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
1991{
1992 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001993 __l2cap_ews_supported(chan)) {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001994 /* use extended control field */
1995 set_bit(FLAG_EXT_CTRL, &chan->flags);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001996 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
1997 } else {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001998 chan->tx_win = min_t(u16, chan->tx_win,
1999 L2CAP_DEFAULT_TX_WINDOW);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002000 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2001 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002002}
2003
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002004static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002007 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 void *ptr = req->data;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002009 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002011 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002013 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002014 goto done;
2015
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002016 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002017 case L2CAP_MODE_STREAMING:
2018 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002019 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002020 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002021
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002022 if (__l2cap_efs_supported(chan))
2023 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2024
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002025 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002026 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002027 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002028 break;
2029 }
2030
2031done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002032 if (chan->imtu != L2CAP_DEFAULT_MTU)
2033 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002034
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002035 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002036 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002037 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2038 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002039 break;
2040
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002041 rfc.mode = L2CAP_MODE_BASIC;
2042 rfc.txwin_size = 0;
2043 rfc.max_transmit = 0;
2044 rfc.retrans_timeout = 0;
2045 rfc.monitor_timeout = 0;
2046 rfc.max_pdu_size = 0;
2047
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002048 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2049 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002050 break;
2051
2052 case L2CAP_MODE_ERTM:
2053 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002054 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002055 rfc.retrans_timeout = 0;
2056 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002057
2058 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2059 L2CAP_EXT_HDR_SIZE -
2060 L2CAP_SDULEN_SIZE -
2061 L2CAP_FCS_SIZE);
2062 rfc.max_pdu_size = cpu_to_le16(size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002063
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002064 l2cap_txwin_setup(chan);
2065
2066 rfc.txwin_size = min_t(u16, chan->tx_win,
2067 L2CAP_DEFAULT_TX_WINDOW);
2068
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002069 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2070 (unsigned long) &rfc);
2071
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002072 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2073 l2cap_add_opt_efs(&ptr, chan);
2074
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002075 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002076 break;
2077
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002078 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002079 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002080 chan->fcs = L2CAP_FCS_NONE;
2081 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002082 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002083
2084 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2085 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2086 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002087 break;
2088
2089 case L2CAP_MODE_STREAMING:
2090 rfc.mode = L2CAP_MODE_STREAMING;
2091 rfc.txwin_size = 0;
2092 rfc.max_transmit = 0;
2093 rfc.retrans_timeout = 0;
2094 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002095
2096 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2097 L2CAP_EXT_HDR_SIZE -
2098 L2CAP_SDULEN_SIZE -
2099 L2CAP_FCS_SIZE);
2100 rfc.max_pdu_size = cpu_to_le16(size);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002101
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002102 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2103 (unsigned long) &rfc);
2104
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002105 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2106 l2cap_add_opt_efs(&ptr, chan);
2107
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002108 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002109 break;
2110
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002111 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002112 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002113 chan->fcs = L2CAP_FCS_NONE;
2114 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002115 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002116 break;
2117 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002119 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002120 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121
2122 return ptr - data;
2123}
2124
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002125static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002127 struct l2cap_conf_rsp *rsp = data;
2128 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002129 void *req = chan->conf_req;
2130 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002131 int type, hint, olen;
2132 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002133 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002134 struct l2cap_conf_efs efs;
2135 u8 remote_efs = 0;
Marcel Holtmann861d6882007-10-20 13:37:06 +02002136 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002137 u16 result = L2CAP_CONF_SUCCESS;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002138 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002140 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002141
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002142 while (len >= L2CAP_CONF_OPT_SIZE) {
2143 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002145 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002146 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002147
2148 switch (type) {
2149 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002150 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002151 break;
2152
2153 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002154 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002155 break;
2156
2157 case L2CAP_CONF_QOS:
2158 break;
2159
Marcel Holtmann6464f352007-10-20 13:39:51 +02002160 case L2CAP_CONF_RFC:
2161 if (olen == sizeof(rfc))
2162 memcpy(&rfc, (void *) val, olen);
2163 break;
2164
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002165 case L2CAP_CONF_FCS:
2166 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002167 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002168 break;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002169
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002170 case L2CAP_CONF_EFS:
2171 remote_efs = 1;
2172 if (olen == sizeof(efs))
2173 memcpy(&efs, (void *) val, olen);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002174 break;
2175
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002176 case L2CAP_CONF_EWS:
2177 if (!enable_hs)
2178 return -ECONNREFUSED;
2179
2180 set_bit(FLAG_EXT_CTRL, &chan->flags);
2181 set_bit(CONF_EWS_RECV, &chan->conf_state);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002182 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002183 chan->remote_tx_win = val;
2184 break;
2185
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002186 default:
2187 if (hint)
2188 break;
2189
2190 result = L2CAP_CONF_UNKNOWN;
2191 *((u8 *) ptr++) = type;
2192 break;
2193 }
2194 }
2195
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002196 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002197 goto done;
2198
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002199 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002200 case L2CAP_MODE_STREAMING:
2201 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002202 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002203 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002204 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002205 break;
2206 }
2207
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002208 if (remote_efs) {
2209 if (__l2cap_efs_supported(chan))
2210 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2211 else
2212 return -ECONNREFUSED;
2213 }
2214
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002215 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002216 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002217
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002218 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002219 }
2220
2221done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002222 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002223 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002224 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002225
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002226 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002227 return -ECONNREFUSED;
2228
2229 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2230 sizeof(rfc), (unsigned long) &rfc);
2231 }
2232
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002233 if (result == L2CAP_CONF_SUCCESS) {
2234 /* Configure output options and let the other side know
2235 * which ones we don't like. */
2236
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002237 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2238 result = L2CAP_CONF_UNACCEPT;
2239 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002240 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002241 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002242 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002243 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002244
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002245 if (remote_efs) {
2246 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2247 efs.stype != L2CAP_SERV_NOTRAFIC &&
2248 efs.stype != chan->local_stype) {
2249
2250 result = L2CAP_CONF_UNACCEPT;
2251
2252 if (chan->num_conf_req >= 1)
2253 return -ECONNREFUSED;
2254
2255 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002256 sizeof(efs),
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002257 (unsigned long) &efs);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002258 } else {
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002259 /* Send PENDING Conf Rsp */
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002260 result = L2CAP_CONF_PENDING;
2261 set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002262 }
2263 }
2264
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002265 switch (rfc.mode) {
2266 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002267 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002268 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002269 break;
2270
2271 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002272 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2273 chan->remote_tx_win = rfc.txwin_size;
2274 else
2275 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2276
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002277 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002278
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002279 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2280 chan->conn->mtu -
2281 L2CAP_EXT_HDR_SIZE -
2282 L2CAP_SDULEN_SIZE -
2283 L2CAP_FCS_SIZE);
2284 rfc.max_pdu_size = cpu_to_le16(size);
2285 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002286
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002287 rfc.retrans_timeout =
2288 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2289 rfc.monitor_timeout =
2290 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002291
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002292 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002293
2294 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2295 sizeof(rfc), (unsigned long) &rfc);
2296
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002297 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2298 chan->remote_id = efs.id;
2299 chan->remote_stype = efs.stype;
2300 chan->remote_msdu = le16_to_cpu(efs.msdu);
2301 chan->remote_flush_to =
2302 le32_to_cpu(efs.flush_to);
2303 chan->remote_acc_lat =
2304 le32_to_cpu(efs.acc_lat);
2305 chan->remote_sdu_itime =
2306 le32_to_cpu(efs.sdu_itime);
2307 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2308 sizeof(efs), (unsigned long) &efs);
2309 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002310 break;
2311
2312 case L2CAP_MODE_STREAMING:
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002313 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2314 chan->conn->mtu -
2315 L2CAP_EXT_HDR_SIZE -
2316 L2CAP_SDULEN_SIZE -
2317 L2CAP_FCS_SIZE);
2318 rfc.max_pdu_size = cpu_to_le16(size);
2319 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002320
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002321 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002322
2323 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2324 sizeof(rfc), (unsigned long) &rfc);
2325
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002326 break;
2327
2328 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002329 result = L2CAP_CONF_UNACCEPT;
2330
2331 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002332 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002333 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002334
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002335 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002336 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002337 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002338 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002339 rsp->result = cpu_to_le16(result);
2340 rsp->flags = cpu_to_le16(0x0000);
2341
2342 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343}
2344
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002345static 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 -03002346{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002347 struct l2cap_conf_req *req = data;
2348 void *ptr = req->data;
2349 int type, olen;
2350 unsigned long val;
2351 struct l2cap_conf_rfc rfc;
2352
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002353 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002354
2355 while (len >= L2CAP_CONF_OPT_SIZE) {
2356 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2357
2358 switch (type) {
2359 case L2CAP_CONF_MTU:
2360 if (val < L2CAP_DEFAULT_MIN_MTU) {
2361 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002362 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002363 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002364 chan->imtu = val;
2365 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002366 break;
2367
2368 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002369 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002370 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002371 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002372 break;
2373
2374 case L2CAP_CONF_RFC:
2375 if (olen == sizeof(rfc))
2376 memcpy(&rfc, (void *)val, olen);
2377
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002378 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002379 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002380 return -ECONNREFUSED;
2381
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002382 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002383
2384 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2385 sizeof(rfc), (unsigned long) &rfc);
2386 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002387
2388 case L2CAP_CONF_EWS:
2389 chan->tx_win = min_t(u16, val,
2390 L2CAP_DEFAULT_EXT_WINDOW);
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002391 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2392 chan->tx_win);
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002393 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002394 }
2395 }
2396
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002397 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002398 return -ECONNREFUSED;
2399
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002400 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002401
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002402 if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002403 switch (rfc.mode) {
2404 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002405 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2406 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2407 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002408 break;
2409 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002410 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002411 }
2412 }
2413
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002414 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002415 req->flags = cpu_to_le16(0x0000);
2416
2417 return ptr - data;
2418}
2419
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002420static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421{
2422 struct l2cap_conf_rsp *rsp = data;
2423 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002425 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002427 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002428 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002429 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430
2431 return ptr - data;
2432}
2433
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002434void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002435{
2436 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002437 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002438 u8 buf[128];
2439
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002440 rsp.scid = cpu_to_le16(chan->dcid);
2441 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002442 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2443 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2444 l2cap_send_cmd(conn, chan->ident,
2445 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2446
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002447 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002448 return;
2449
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002450 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2451 l2cap_build_conf_req(chan, buf), buf);
2452 chan->num_conf_req++;
2453}
2454
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002455static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002456{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002457 int type, olen;
2458 unsigned long val;
2459 struct l2cap_conf_rfc rfc;
2460
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002461 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002462
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002463 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002464 return;
2465
2466 while (len >= L2CAP_CONF_OPT_SIZE) {
2467 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2468
2469 switch (type) {
2470 case L2CAP_CONF_RFC:
2471 if (olen == sizeof(rfc))
2472 memcpy(&rfc, (void *)val, olen);
2473 goto done;
2474 }
2475 }
2476
2477done:
2478 switch (rfc.mode) {
2479 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002480 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2481 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2482 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002483 break;
2484 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002485 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002486 }
2487}
2488
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002489static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2490{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002491 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002492
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002493 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002494 return 0;
2495
2496 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2497 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002498 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002499
2500 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002501 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002502
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002503 l2cap_conn_start(conn);
2504 }
2505
2506 return 0;
2507}
2508
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2510{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2512 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002513 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002514 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002515 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516
2517 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002518 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519
2520 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2521
2522 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002523 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2524 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525 result = L2CAP_CR_BAD_PSM;
2526 goto sendresp;
2527 }
2528
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002529 parent = pchan->sk;
2530
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002531 bh_lock_sock(parent);
2532
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002533 /* Check if the ACL is secure enough (if not SDP) */
2534 if (psm != cpu_to_le16(0x0001) &&
2535 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002536 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002537 result = L2CAP_CR_SEC_BLOCK;
2538 goto response;
2539 }
2540
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541 result = L2CAP_CR_NO_MEM;
2542
2543 /* Check for backlog size */
2544 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002545 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546 goto response;
2547 }
2548
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002549 chan = pchan->ops->new_connection(pchan->data);
2550 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551 goto response;
2552
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002553 sk = chan->sk;
2554
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002555 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556
2557 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002558 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2559 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002561 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562 goto response;
2563 }
2564
2565 hci_conn_hold(conn->hcon);
2566
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 bacpy(&bt_sk(sk)->src, conn->src);
2568 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002569 chan->psm = psm;
2570 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002572 bt_accept_enqueue(parent, sk);
2573
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002574 __l2cap_chan_add(conn, chan);
2575
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002576 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002578 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002580 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581
Marcel Holtmann984947d2009-02-06 23:35:19 +01002582 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002583 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002584 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002585 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002586 result = L2CAP_CR_PEND;
2587 status = L2CAP_CS_AUTHOR_PEND;
2588 parent->sk_data_ready(parent, 0);
2589 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002590 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002591 result = L2CAP_CR_SUCCESS;
2592 status = L2CAP_CS_NO_INFO;
2593 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002594 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002595 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002596 result = L2CAP_CR_PEND;
2597 status = L2CAP_CS_AUTHEN_PEND;
2598 }
2599 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002600 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002601 result = L2CAP_CR_PEND;
2602 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603 }
2604
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002605 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606
2607response:
2608 bh_unlock_sock(parent);
2609
2610sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002611 rsp.scid = cpu_to_le16(scid);
2612 rsp.dcid = cpu_to_le16(dcid);
2613 rsp.result = cpu_to_le16(result);
2614 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002616
2617 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2618 struct l2cap_info_req info;
2619 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2620
2621 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2622 conn->info_ident = l2cap_get_ident(conn);
2623
2624 mod_timer(&conn->info_timer, jiffies +
2625 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2626
2627 l2cap_send_cmd(conn, conn->info_ident,
2628 L2CAP_INFO_REQ, sizeof(info), &info);
2629 }
2630
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002631 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002632 result == L2CAP_CR_SUCCESS) {
2633 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002634 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002635 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002636 l2cap_build_conf_req(chan, buf), buf);
2637 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002638 }
2639
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 return 0;
2641}
2642
2643static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2644{
2645 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2646 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002647 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648 struct sock *sk;
2649 u8 req[128];
2650
2651 scid = __le16_to_cpu(rsp->scid);
2652 dcid = __le16_to_cpu(rsp->dcid);
2653 result = __le16_to_cpu(rsp->result);
2654 status = __le16_to_cpu(rsp->status);
2655
2656 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2657
2658 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002659 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002660 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002661 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002663 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002664 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002665 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666 }
2667
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002668 sk = chan->sk;
2669
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670 switch (result) {
2671 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002672 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002673 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002674 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002675 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002676
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002677 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002678 break;
2679
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002681 l2cap_build_conf_req(chan, req), req);
2682 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683 break;
2684
2685 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002686 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687 break;
2688
2689 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002690 /* don't delete l2cap channel if sk is owned by user */
2691 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002692 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002693 __clear_chan_timer(chan);
2694 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002695 break;
2696 }
2697
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002698 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699 break;
2700 }
2701
2702 bh_unlock_sock(sk);
2703 return 0;
2704}
2705
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002706static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002707{
2708 /* FCS is enabled only in ERTM or streaming mode, if one or both
2709 * sides request it.
2710 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002711 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002712 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002713 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002714 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002715}
2716
Al Viro88219a02007-07-29 00:17:25 -07002717static 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 -07002718{
2719 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2720 u16 dcid, flags;
2721 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002722 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002724 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725
2726 dcid = __le16_to_cpu(req->dcid);
2727 flags = __le16_to_cpu(req->flags);
2728
2729 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2730
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002731 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002732 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 return -ENOENT;
2734
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002735 sk = chan->sk;
2736
David S. Miller033b1142011-07-21 13:38:42 -07002737 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002738 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002739
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002740 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2741 rej.scid = cpu_to_le16(chan->scid);
2742 rej.dcid = cpu_to_le16(chan->dcid);
2743
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002744 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2745 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002746 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002747 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002748
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002749 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002750 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002751 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002752 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002753 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002754 L2CAP_CONF_REJECT, flags), rsp);
2755 goto unlock;
2756 }
2757
2758 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002759 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2760 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761
2762 if (flags & 0x0001) {
2763 /* Incomplete config. Send empty response. */
2764 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002765 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002766 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 goto unlock;
2768 }
2769
2770 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002771 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002772 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002773 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002775 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002777 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002778 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002779
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002780 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002781 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002782
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002783 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002784 goto unlock;
2785
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002786 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002787 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002788
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002789 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002790
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002791 chan->next_tx_seq = 0;
2792 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002793 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002794 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002795 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002796
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002798 goto unlock;
2799 }
2800
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002801 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002802 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002804 l2cap_build_conf_req(chan, buf), buf);
2805 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806 }
2807
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002808 /* Got Conf Rsp PENDING from remote side and asume we sent
2809 Conf Rsp PENDING in the code above */
2810 if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
2811 test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2812
2813 /* check compatibility */
2814
2815 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2816 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2817
2818 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002819 l2cap_build_conf_rsp(chan, rsp,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002820 L2CAP_CONF_SUCCESS, 0x0000), rsp);
2821 }
2822
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823unlock:
2824 bh_unlock_sock(sk);
2825 return 0;
2826}
2827
2828static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2829{
2830 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2831 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002832 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002834 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835
2836 scid = __le16_to_cpu(rsp->scid);
2837 flags = __le16_to_cpu(rsp->flags);
2838 result = __le16_to_cpu(rsp->result);
2839
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002840 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2841 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002843 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002844 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845 return 0;
2846
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002847 sk = chan->sk;
2848
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849 switch (result) {
2850 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002851 l2cap_conf_rfc_get(chan, rsp->data, len);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002852 clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853 break;
2854
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002855 case L2CAP_CONF_PENDING:
2856 set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
2857
2858 if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2859 char buf[64];
2860
2861 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2862 buf, &result);
2863 if (len < 0) {
2864 l2cap_send_disconn_req(conn, chan, ECONNRESET);
2865 goto done;
2866 }
2867
2868 /* check compatibility */
2869
2870 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2871 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2872
2873 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002874 l2cap_build_conf_rsp(chan, buf,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002875 L2CAP_CONF_SUCCESS, 0x0000), buf);
2876 }
2877 goto done;
2878
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002880 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002881 char req[64];
2882
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002883 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002884 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002885 goto done;
2886 }
2887
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002888 /* throw out any old stored conf requests */
2889 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002890 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2891 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002892 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002893 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002894 goto done;
2895 }
2896
2897 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2898 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002899 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002900 if (result != L2CAP_CONF_SUCCESS)
2901 goto done;
2902 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002903 }
2904
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002905 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002906 sk->sk_err = ECONNRESET;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002907 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002908 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002909 goto done;
2910 }
2911
2912 if (flags & 0x01)
2913 goto done;
2914
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002915 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002917 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002918 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002919
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002920 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002921 chan->next_tx_seq = 0;
2922 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002923 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002924 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002925 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002926
Linus Torvalds1da177e2005-04-16 15:20:36 -07002927 l2cap_chan_ready(sk);
2928 }
2929
2930done:
2931 bh_unlock_sock(sk);
2932 return 0;
2933}
2934
2935static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2936{
2937 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2938 struct l2cap_disconn_rsp rsp;
2939 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002940 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002941 struct sock *sk;
2942
2943 scid = __le16_to_cpu(req->scid);
2944 dcid = __le16_to_cpu(req->dcid);
2945
2946 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2947
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002948 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002949 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002950 return 0;
2951
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002952 sk = chan->sk;
2953
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002954 rsp.dcid = cpu_to_le16(chan->scid);
2955 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2957
2958 sk->sk_shutdown = SHUTDOWN_MASK;
2959
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002960 /* don't delete l2cap channel if sk is owned by user */
2961 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002962 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002963 __clear_chan_timer(chan);
2964 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002965 bh_unlock_sock(sk);
2966 return 0;
2967 }
2968
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002969 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970 bh_unlock_sock(sk);
2971
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002972 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973 return 0;
2974}
2975
2976static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2977{
2978 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2979 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002980 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981 struct sock *sk;
2982
2983 scid = __le16_to_cpu(rsp->scid);
2984 dcid = __le16_to_cpu(rsp->dcid);
2985
2986 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2987
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002988 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002989 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990 return 0;
2991
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002992 sk = chan->sk;
2993
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002994 /* don't delete l2cap channel if sk is owned by user */
2995 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002996 l2cap_state_change(chan,BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002997 __clear_chan_timer(chan);
2998 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002999 bh_unlock_sock(sk);
3000 return 0;
3001 }
3002
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003003 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004 bh_unlock_sock(sk);
3005
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003006 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 return 0;
3008}
3009
3010static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3011{
3012 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013 u16 type;
3014
3015 type = __le16_to_cpu(req->type);
3016
3017 BT_DBG("type 0x%4.4x", type);
3018
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003019 if (type == L2CAP_IT_FEAT_MASK) {
3020 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003021 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003022 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3023 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3024 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003025 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003026 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3027 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003028 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003029 feat_mask |= L2CAP_FEAT_EXT_FLOW
3030 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003031
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003032 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003033 l2cap_send_cmd(conn, cmd->ident,
3034 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003035 } else if (type == L2CAP_IT_FIXED_CHAN) {
3036 u8 buf[12];
3037 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3038 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3039 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003040 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003041 l2cap_send_cmd(conn, cmd->ident,
3042 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003043 } else {
3044 struct l2cap_info_rsp rsp;
3045 rsp.type = cpu_to_le16(type);
3046 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3047 l2cap_send_cmd(conn, cmd->ident,
3048 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3049 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050
3051 return 0;
3052}
3053
3054static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3055{
3056 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3057 u16 type, result;
3058
3059 type = __le16_to_cpu(rsp->type);
3060 result = __le16_to_cpu(rsp->result);
3061
3062 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3063
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003064 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3065 if (cmd->ident != conn->info_ident ||
3066 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3067 return 0;
3068
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003069 del_timer(&conn->info_timer);
3070
Ville Tervoadb08ed2010-08-04 09:43:33 +03003071 if (result != L2CAP_IR_SUCCESS) {
3072 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3073 conn->info_ident = 0;
3074
3075 l2cap_conn_start(conn);
3076
3077 return 0;
3078 }
3079
Marcel Holtmann984947d2009-02-06 23:35:19 +01003080 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003081 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003082
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003083 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003084 struct l2cap_info_req req;
3085 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3086
3087 conn->info_ident = l2cap_get_ident(conn);
3088
3089 l2cap_send_cmd(conn, conn->info_ident,
3090 L2CAP_INFO_REQ, sizeof(req), &req);
3091 } else {
3092 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3093 conn->info_ident = 0;
3094
3095 l2cap_conn_start(conn);
3096 }
3097 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003098 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003099 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003100
3101 l2cap_conn_start(conn);
3102 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003103
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104 return 0;
3105}
3106
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003107static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3108 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3109 void *data)
3110{
3111 struct l2cap_create_chan_req *req = data;
3112 struct l2cap_create_chan_rsp rsp;
3113 u16 psm, scid;
3114
3115 if (cmd_len != sizeof(*req))
3116 return -EPROTO;
3117
3118 if (!enable_hs)
3119 return -EINVAL;
3120
3121 psm = le16_to_cpu(req->psm);
3122 scid = le16_to_cpu(req->scid);
3123
3124 BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3125
3126 /* Placeholder: Always reject */
3127 rsp.dcid = 0;
3128 rsp.scid = cpu_to_le16(scid);
3129 rsp.result = L2CAP_CR_NO_MEM;
3130 rsp.status = L2CAP_CS_NO_INFO;
3131
3132 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3133 sizeof(rsp), &rsp);
3134
3135 return 0;
3136}
3137
3138static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3139 struct l2cap_cmd_hdr *cmd, void *data)
3140{
3141 BT_DBG("conn %p", conn);
3142
3143 return l2cap_connect_rsp(conn, cmd, data);
3144}
3145
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003146static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02003147 u16 to_multiplier)
3148{
3149 u16 max_latency;
3150
3151 if (min > max || min < 6 || max > 3200)
3152 return -EINVAL;
3153
3154 if (to_multiplier < 10 || to_multiplier > 3200)
3155 return -EINVAL;
3156
3157 if (max >= to_multiplier * 8)
3158 return -EINVAL;
3159
3160 max_latency = (to_multiplier * 8 / max) - 1;
3161 if (latency > 499 || latency > max_latency)
3162 return -EINVAL;
3163
3164 return 0;
3165}
3166
3167static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3168 struct l2cap_cmd_hdr *cmd, u8 *data)
3169{
3170 struct hci_conn *hcon = conn->hcon;
3171 struct l2cap_conn_param_update_req *req;
3172 struct l2cap_conn_param_update_rsp rsp;
3173 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003174 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02003175
3176 if (!(hcon->link_mode & HCI_LM_MASTER))
3177 return -EINVAL;
3178
3179 cmd_len = __le16_to_cpu(cmd->len);
3180 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3181 return -EPROTO;
3182
3183 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003184 min = __le16_to_cpu(req->min);
3185 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02003186 latency = __le16_to_cpu(req->latency);
3187 to_multiplier = __le16_to_cpu(req->to_multiplier);
3188
3189 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3190 min, max, latency, to_multiplier);
3191
3192 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003193
3194 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
3195 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02003196 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3197 else
3198 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3199
3200 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3201 sizeof(rsp), &rsp);
3202
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003203 if (!err)
3204 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
3205
Claudio Takahaside731152011-02-11 19:28:55 -02003206 return 0;
3207}
3208
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003209static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
3210 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
3211{
3212 int err = 0;
3213
3214 switch (cmd->code) {
3215 case L2CAP_COMMAND_REJ:
3216 l2cap_command_rej(conn, cmd, data);
3217 break;
3218
3219 case L2CAP_CONN_REQ:
3220 err = l2cap_connect_req(conn, cmd, data);
3221 break;
3222
3223 case L2CAP_CONN_RSP:
3224 err = l2cap_connect_rsp(conn, cmd, data);
3225 break;
3226
3227 case L2CAP_CONF_REQ:
3228 err = l2cap_config_req(conn, cmd, cmd_len, data);
3229 break;
3230
3231 case L2CAP_CONF_RSP:
3232 err = l2cap_config_rsp(conn, cmd, data);
3233 break;
3234
3235 case L2CAP_DISCONN_REQ:
3236 err = l2cap_disconnect_req(conn, cmd, data);
3237 break;
3238
3239 case L2CAP_DISCONN_RSP:
3240 err = l2cap_disconnect_rsp(conn, cmd, data);
3241 break;
3242
3243 case L2CAP_ECHO_REQ:
3244 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3245 break;
3246
3247 case L2CAP_ECHO_RSP:
3248 break;
3249
3250 case L2CAP_INFO_REQ:
3251 err = l2cap_information_req(conn, cmd, data);
3252 break;
3253
3254 case L2CAP_INFO_RSP:
3255 err = l2cap_information_rsp(conn, cmd, data);
3256 break;
3257
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003258 case L2CAP_CREATE_CHAN_REQ:
3259 err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3260 break;
3261
3262 case L2CAP_CREATE_CHAN_RSP:
3263 err = l2cap_create_channel_rsp(conn, cmd, data);
3264 break;
3265
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003266 default:
3267 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3268 err = -EINVAL;
3269 break;
3270 }
3271
3272 return err;
3273}
3274
3275static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3276 struct l2cap_cmd_hdr *cmd, u8 *data)
3277{
3278 switch (cmd->code) {
3279 case L2CAP_COMMAND_REJ:
3280 return 0;
3281
3282 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003283 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003284
3285 case L2CAP_CONN_PARAM_UPDATE_RSP:
3286 return 0;
3287
3288 default:
3289 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3290 return -EINVAL;
3291 }
3292}
3293
3294static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3295 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296{
3297 u8 *data = skb->data;
3298 int len = skb->len;
3299 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003300 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003301
3302 l2cap_raw_recv(conn, skb);
3303
3304 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003305 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003306 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3307 data += L2CAP_CMD_HDR_SIZE;
3308 len -= L2CAP_CMD_HDR_SIZE;
3309
Al Viro88219a02007-07-29 00:17:25 -07003310 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003311
Al Viro88219a02007-07-29 00:17:25 -07003312 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 -07003313
Al Viro88219a02007-07-29 00:17:25 -07003314 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003315 BT_DBG("corrupted command");
3316 break;
3317 }
3318
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003319 if (conn->hcon->type == LE_LINK)
3320 err = l2cap_le_sig_cmd(conn, &cmd, data);
3321 else
3322 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003323
3324 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003325 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003326
3327 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003328
3329 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003330 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003331 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3332 }
3333
Al Viro88219a02007-07-29 00:17:25 -07003334 data += cmd_len;
3335 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336 }
3337
3338 kfree_skb(skb);
3339}
3340
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003341static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003342{
3343 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003344 int hdr_size;
3345
3346 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3347 hdr_size = L2CAP_EXT_HDR_SIZE;
3348 else
3349 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003350
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003351 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003352 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003353 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3354 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3355
3356 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003357 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003358 }
3359 return 0;
3360}
3361
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003362static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003363{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003364 u32 control = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003365
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003366 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003367
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003368 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003369
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003370 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003371 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003372 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003373 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003374 }
3375
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003376 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003377 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003378
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003379 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003380
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003381 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003382 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003383 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003384 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003385 }
3386}
3387
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003388static 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 -03003389{
3390 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003391 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003392
3393 bt_cb(skb)->tx_seq = tx_seq;
3394 bt_cb(skb)->sar = sar;
3395
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003396 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003397 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003398 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003399 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003400 }
3401
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003402 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003403
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003404 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003405 if (bt_cb(next_skb)->tx_seq == tx_seq)
3406 return -EINVAL;
3407
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003408 next_tx_seq_offset = __seq_offset(chan,
3409 bt_cb(next_skb)->tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003410
3411 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003412 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003413 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003414 }
3415
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003416 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003417 break;
3418
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003419 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003420
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003421 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003422
3423 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003424}
3425
Mat Martineau84084a32011-07-22 14:54:00 -07003426static void append_skb_frag(struct sk_buff *skb,
3427 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003428{
Mat Martineau84084a32011-07-22 14:54:00 -07003429 /* skb->len reflects data in skb as well as all fragments
3430 * skb->data_len reflects only data in fragments
3431 */
3432 if (!skb_has_frag_list(skb))
3433 skb_shinfo(skb)->frag_list = new_frag;
3434
3435 new_frag->next = NULL;
3436
3437 (*last_frag)->next = new_frag;
3438 *last_frag = new_frag;
3439
3440 skb->len += new_frag->len;
3441 skb->data_len += new_frag->len;
3442 skb->truesize += new_frag->truesize;
3443}
3444
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003445static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
Mat Martineau84084a32011-07-22 14:54:00 -07003446{
3447 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003448
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003449 switch (__get_ctrl_sar(chan, control)) {
3450 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003451 if (chan->sdu)
3452 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003453
Mat Martineau84084a32011-07-22 14:54:00 -07003454 err = chan->ops->recv(chan->data, skb);
3455 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003456
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003457 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003458 if (chan->sdu)
3459 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003460
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003461 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003462 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003463
Mat Martineau84084a32011-07-22 14:54:00 -07003464 if (chan->sdu_len > chan->imtu) {
3465 err = -EMSGSIZE;
3466 break;
3467 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003468
Mat Martineau84084a32011-07-22 14:54:00 -07003469 if (skb->len >= chan->sdu_len)
3470 break;
3471
3472 chan->sdu = skb;
3473 chan->sdu_last_frag = skb;
3474
3475 skb = NULL;
3476 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003477 break;
3478
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003479 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003480 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003481 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003482
Mat Martineau84084a32011-07-22 14:54:00 -07003483 append_skb_frag(chan->sdu, skb,
3484 &chan->sdu_last_frag);
3485 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003486
Mat Martineau84084a32011-07-22 14:54:00 -07003487 if (chan->sdu->len >= chan->sdu_len)
3488 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003489
Mat Martineau84084a32011-07-22 14:54:00 -07003490 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003491 break;
3492
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003493 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003494 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003495 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003496
Mat Martineau84084a32011-07-22 14:54:00 -07003497 append_skb_frag(chan->sdu, skb,
3498 &chan->sdu_last_frag);
3499 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003500
Mat Martineau84084a32011-07-22 14:54:00 -07003501 if (chan->sdu->len != chan->sdu_len)
3502 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003503
Mat Martineau84084a32011-07-22 14:54:00 -07003504 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003505
Mat Martineau84084a32011-07-22 14:54:00 -07003506 if (!err) {
3507 /* Reassembly complete */
3508 chan->sdu = NULL;
3509 chan->sdu_last_frag = NULL;
3510 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003511 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003512 break;
3513 }
3514
Mat Martineau84084a32011-07-22 14:54:00 -07003515 if (err) {
3516 kfree_skb(skb);
3517 kfree_skb(chan->sdu);
3518 chan->sdu = NULL;
3519 chan->sdu_last_frag = NULL;
3520 chan->sdu_len = 0;
3521 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003522
Mat Martineau84084a32011-07-22 14:54:00 -07003523 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003524}
3525
Mat Martineau26f880d2011-07-07 09:39:01 -07003526static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003527{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003528 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003529
Mat Martineau26f880d2011-07-07 09:39:01 -07003530 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003531
Mat Martineau26f880d2011-07-07 09:39:01 -07003532 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3533
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003534 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003535 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Mat Martineau26f880d2011-07-07 09:39:01 -07003536 l2cap_send_sframe(chan, control);
3537
3538 set_bit(CONN_RNR_SENT, &chan->conn_state);
3539
3540 __clear_ack_timer(chan);
3541}
3542
3543static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3544{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003545 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003546
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003547 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003548 goto done;
3549
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003550 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003551 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003552 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003553 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003554 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003555
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003556 __clear_retrans_timer(chan);
3557 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003558
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003559 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003560
3561done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003562 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3563 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003564
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003565 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003566}
3567
Mat Martineaue3281402011-07-07 09:39:02 -07003568void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003569{
Mat Martineaue3281402011-07-07 09:39:02 -07003570 if (chan->mode == L2CAP_MODE_ERTM) {
3571 if (busy)
3572 l2cap_ertm_enter_local_busy(chan);
3573 else
3574 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003575 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003576}
3577
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003578static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003579{
3580 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003581 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003582
Mat Martineaue3281402011-07-07 09:39:02 -07003583 while ((skb = skb_peek(&chan->srej_q)) &&
3584 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3585 int err;
3586
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003587 if (bt_cb(skb)->tx_seq != tx_seq)
3588 break;
3589
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003590 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003591 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003592 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003593
3594 if (err < 0) {
3595 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3596 break;
3597 }
3598
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003599 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
3600 tx_seq = __next_seq(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003601 }
3602}
3603
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003604static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003605{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003606 struct srej_list *l, *tmp;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003607 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003608
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003609 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003610 if (l->tx_seq == tx_seq) {
3611 list_del(&l->list);
3612 kfree(l);
3613 return;
3614 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003615 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003616 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003617 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003618 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003619 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003620 }
3621}
3622
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003623static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003624{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003625 struct srej_list *new;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003626 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003627
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003628 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003629 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003630 control |= __set_reqseq(chan, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003631 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003632
3633 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003634 new->tx_seq = chan->expected_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003635
3636 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
3637
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003638 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003639 }
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003640
3641 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003642}
3643
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003644static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003645{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003646 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003647 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003648 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003649 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003650 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003651 int err = 0;
3652
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003653 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%8.8x", chan, skb->len,
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003654 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003655
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003656 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003657 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003658 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003659 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003660 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003661 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003662 }
3663
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003664 chan->expected_ack_seq = req_seq;
3665 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003666
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003667 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003668
3669 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003670 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003671 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003672 goto drop;
3673 }
3674
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003675 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003676 goto drop;
3677
Mat Martineau02f1b642011-06-29 14:35:19 -07003678 if (tx_seq == chan->expected_tx_seq)
3679 goto expected;
3680
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003681 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003682 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003683
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003684 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003685 struct srej_list, list);
3686 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003687 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003688 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003689
3690 list_del(&first->list);
3691 kfree(first);
3692
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003693 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003694 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003695 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003696 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003697 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003698 }
3699 } else {
3700 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003701
3702 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003703 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003704 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003705
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003706 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003707 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003708 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003709 return 0;
3710 }
3711 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003712 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003713 }
3714 } else {
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003715 expected_tx_seq_offset = __seq_offset(chan,
3716 chan->expected_tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003717
3718 /* duplicated tx_seq */
3719 if (tx_seq_offset < expected_tx_seq_offset)
3720 goto drop;
3721
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003722 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003723
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003724 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003725
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003726 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003727 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003728
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003729 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003730 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003731
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003732 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003733
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003734 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003735
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003736 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003737 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003738 return 0;
3739
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003740expected:
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003741 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003742
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003743 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003744 bt_cb(skb)->tx_seq = tx_seq;
3745 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003746 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003747 return 0;
3748 }
3749
Mat Martineau84084a32011-07-22 14:54:00 -07003750 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003751 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
3752
Mat Martineaue3281402011-07-07 09:39:02 -07003753 if (err < 0) {
3754 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3755 return err;
3756 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003757
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003758 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003759 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003760 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003761 }
3762
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003763 __set_ack_timer(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003764
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003765 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3766 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003767 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003768
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003769 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003770
3771drop:
3772 kfree_skb(skb);
3773 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003774}
3775
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003776static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003777{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003778 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003779 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003780
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003781 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003782 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003783
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003784 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003785 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3786 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3787 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003788 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003789 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003790
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003791 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003792 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003793 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003794 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003795 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003796
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003797 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003798 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003799
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003800 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003801 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003802
3803 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003804 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003805 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003806 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003807
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003808 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3809 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003810 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003811 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003812 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003813 }
3814}
3815
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003816static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003817{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003818 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003819
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003820 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003821
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003822 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003823
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003824 chan->expected_ack_seq = tx_seq;
3825 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003826
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003827 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003828 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003829 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003830 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003831 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003832
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003833 if (test_bit(CONN_WAIT_F, &chan->conn_state))
3834 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003835 }
3836}
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003837static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003838{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003839 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003840
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003841 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003842
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003843 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003844
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003845 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003846 chan->expected_ack_seq = tx_seq;
3847 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003848
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003849 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003850 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003851
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003852 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003853
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003854 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003855 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003856 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003857 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003858 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003859 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003860 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003861 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003862 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003863 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003864 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003865 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003866 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003867 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003868 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003869 }
3870 }
3871}
3872
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003873static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003874{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003875 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003876
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003877 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003878
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003879 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003880 chan->expected_ack_seq = tx_seq;
3881 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003882
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003883 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003884 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003885
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003886 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003887 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003888 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003889 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003890 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003891 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003892
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003893 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003894 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003895 } else {
3896 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
3897 l2cap_send_sframe(chan, rx_control);
3898 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003899}
3900
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003901static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003902{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003903 BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003904
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003905 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003906 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003907 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003908 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003909 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003910 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003911 }
3912
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003913 switch (__get_ctrl_super(chan, rx_control)) {
3914 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003915 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003916 break;
3917
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003918 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003919 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003920 break;
3921
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003922 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003923 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003924 break;
3925
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003926 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003927 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003928 break;
3929 }
3930
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003931 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003932 return 0;
3933}
3934
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003935static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3936{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003937 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003938 u32 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003939 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003940 int len, next_tx_seq_offset, req_seq_offset;
3941
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003942 control = __get_control(chan, skb->data);
3943 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003944 len = skb->len;
3945
3946 /*
3947 * We can just drop the corrupted I-frame here.
3948 * Receiver will miss it and start proper recovery
3949 * procedures and ask retransmission.
3950 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003951 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003952 goto drop;
3953
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03003954 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003955 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003956
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003957 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003958 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003959
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003960 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003961 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003962 goto drop;
3963 }
3964
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003965 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003966
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003967 req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
3968
3969 next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
3970 chan->expected_ack_seq);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003971
3972 /* check for invalid req-seq */
3973 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003974 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003975 goto drop;
3976 }
3977
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03003978 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003979 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003980 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003981 goto drop;
3982 }
3983
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003984 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003985 } else {
3986 if (len != 0) {
3987 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003988 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003989 goto drop;
3990 }
3991
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003992 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003993 }
3994
3995 return 0;
3996
3997drop:
3998 kfree_skb(skb);
3999 return 0;
4000}
4001
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4003{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004004 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07004005 struct sock *sk = NULL;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004006 u32 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004007 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004008 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004010 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004011 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004012 BT_DBG("unknown cid 0x%4.4x", cid);
4013 goto drop;
4014 }
4015
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004016 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004017
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004018 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004020 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021 goto drop;
4022
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004023 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004024 case L2CAP_MODE_BASIC:
4025 /* If socket recv buffers overflows we drop data here
4026 * which is *bad* because L2CAP has to be reliable.
4027 * But we don't have any other choice. L2CAP doesn't
4028 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004030 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004031 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004033 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004034 goto done;
4035 break;
4036
4037 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004038 if (!sock_owned_by_user(sk)) {
4039 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004040 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004041 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004042 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03004043 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004044
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004045 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004046
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004047 case L2CAP_MODE_STREAMING:
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004048 control = __get_control(chan, skb->data);
4049 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004050 len = skb->len;
4051
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004052 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004053 goto drop;
4054
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004055 if (__is_sar_start(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004056 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004057
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004058 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004059 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004060
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004061 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004062 goto drop;
4063
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004064 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004065
Mat Martineau84084a32011-07-22 14:54:00 -07004066 if (chan->expected_tx_seq != tx_seq) {
4067 /* Frame(s) missing - must discard partial SDU */
4068 kfree_skb(chan->sdu);
4069 chan->sdu = NULL;
4070 chan->sdu_last_frag = NULL;
4071 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004072
Mat Martineau84084a32011-07-22 14:54:00 -07004073 /* TODO: Notify userland of missing data */
4074 }
4075
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004076 chan->expected_tx_seq = __next_seq(chan, tx_seq);
Mat Martineau84084a32011-07-22 14:54:00 -07004077
4078 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
4079 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004080
4081 goto done;
4082
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004083 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004084 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004085 break;
4086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087
4088drop:
4089 kfree_skb(skb);
4090
4091done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004092 if (sk)
4093 bh_unlock_sock(sk);
4094
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095 return 0;
4096}
4097
Al Viro8e036fc2007-07-29 00:16:36 -07004098static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004100 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004101 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004103 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
4104 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105 goto drop;
4106
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004107 sk = chan->sk;
4108
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00004109 bh_lock_sock(sk);
4110
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111 BT_DBG("sk %p, len %d", sk, skb->len);
4112
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004113 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114 goto drop;
4115
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004116 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117 goto drop;
4118
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004119 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120 goto done;
4121
4122drop:
4123 kfree_skb(skb);
4124
4125done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004126 if (sk)
4127 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128 return 0;
4129}
4130
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004131static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
4132{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004133 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004134 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004135
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004136 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
4137 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004138 goto drop;
4139
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004140 sk = chan->sk;
4141
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004142 bh_lock_sock(sk);
4143
4144 BT_DBG("sk %p, len %d", sk, skb->len);
4145
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004146 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004147 goto drop;
4148
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004149 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004150 goto drop;
4151
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004152 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004153 goto done;
4154
4155drop:
4156 kfree_skb(skb);
4157
4158done:
4159 if (sk)
4160 bh_unlock_sock(sk);
4161 return 0;
4162}
4163
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4165{
4166 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004167 u16 cid, len;
4168 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169
4170 skb_pull(skb, L2CAP_HDR_SIZE);
4171 cid = __le16_to_cpu(lh->cid);
4172 len = __le16_to_cpu(lh->len);
4173
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004174 if (len != skb->len) {
4175 kfree_skb(skb);
4176 return;
4177 }
4178
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4180
4181 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004182 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004183 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184 l2cap_sig_channel(conn, skb);
4185 break;
4186
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004187 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004188 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189 skb_pull(skb, 2);
4190 l2cap_conless_channel(conn, psm, skb);
4191 break;
4192
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004193 case L2CAP_CID_LE_DATA:
4194 l2cap_att_channel(conn, cid, skb);
4195 break;
4196
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004197 case L2CAP_CID_SMP:
4198 if (smp_sig_channel(conn, skb))
4199 l2cap_conn_del(conn->hcon, EACCES);
4200 break;
4201
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202 default:
4203 l2cap_data_channel(conn, cid, skb);
4204 break;
4205 }
4206}
4207
4208/* ---- L2CAP interface with lower layer (HCI) ---- */
4209
4210static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4211{
4212 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004213 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214
4215 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004216 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217
4218 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4219
4220 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004221 read_lock(&chan_list_lock);
4222 list_for_each_entry(c, &chan_list, global_l) {
4223 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004224
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004225 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226 continue;
4227
4228 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004229 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004230 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004231 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004233 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4234 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004235 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004236 lm2 |= HCI_LM_MASTER;
4237 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004238 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004239 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004240
4241 return exact ? lm1 : lm2;
4242}
4243
4244static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4245{
Marcel Holtmann01394182006-07-03 10:02:46 +02004246 struct l2cap_conn *conn;
4247
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4249
Ville Tervoacd7d372011-02-10 22:38:49 -03004250 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004251 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252
4253 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254 conn = l2cap_conn_add(hcon, status);
4255 if (conn)
4256 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004257 } else
Joe Perchese1750722011-06-29 18:18:29 -07004258 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004259
4260 return 0;
4261}
4262
Marcel Holtmann2950f212009-02-12 14:02:50 +01004263static int l2cap_disconn_ind(struct hci_conn *hcon)
4264{
4265 struct l2cap_conn *conn = hcon->l2cap_data;
4266
4267 BT_DBG("hcon %p", hcon);
4268
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03004269 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004270 return 0x13;
4271
4272 return conn->disc_reason;
4273}
4274
4275static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276{
4277 BT_DBG("hcon %p reason %d", hcon, reason);
4278
Ville Tervoacd7d372011-02-10 22:38:49 -03004279 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004280 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004281
Joe Perchese1750722011-06-29 18:18:29 -07004282 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004283
Linus Torvalds1da177e2005-04-16 15:20:36 -07004284 return 0;
4285}
4286
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004287static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004288{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004289 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004290 return;
4291
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004292 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004293 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004294 __clear_chan_timer(chan);
4295 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004296 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004297 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004298 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004299 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004300 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004301 }
4302}
4303
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004304static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004306 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004307 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308
Marcel Holtmann01394182006-07-03 10:02:46 +02004309 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004311
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312 BT_DBG("conn %p", conn);
4313
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004314 if (hcon->type == LE_LINK) {
4315 smp_distribute_keys(conn, 0);
4316 del_timer(&conn->security_timer);
4317 }
4318
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004319 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004320
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004321 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004322 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004323
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324 bh_lock_sock(sk);
4325
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004326 BT_DBG("chan->scid %d", chan->scid);
4327
4328 if (chan->scid == L2CAP_CID_LE_DATA) {
4329 if (!status && encrypt) {
4330 chan->sec_level = hcon->sec_level;
4331 l2cap_chan_ready(sk);
4332 }
4333
4334 bh_unlock_sock(sk);
4335 continue;
4336 }
4337
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004338 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004339 bh_unlock_sock(sk);
4340 continue;
4341 }
4342
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004343 if (!status && (chan->state == BT_CONNECTED ||
4344 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004345 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004346 bh_unlock_sock(sk);
4347 continue;
4348 }
4349
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004350 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004351 if (!status) {
4352 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004353 req.scid = cpu_to_le16(chan->scid);
4354 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004355
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004356 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004357 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004358
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004359 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004360 L2CAP_CONN_REQ, sizeof(req), &req);
4361 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004362 __clear_chan_timer(chan);
4363 __set_chan_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004364 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004365 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004366 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004367 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004368
4369 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004370 if (bt_sk(sk)->defer_setup) {
4371 struct sock *parent = bt_sk(sk)->parent;
4372 res = L2CAP_CR_PEND;
4373 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004374 if (parent)
4375 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004376 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004377 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004378 res = L2CAP_CR_SUCCESS;
4379 stat = L2CAP_CS_NO_INFO;
4380 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004381 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004382 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004383 __set_chan_timer(chan, HZ / 10);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004384 res = L2CAP_CR_SEC_BLOCK;
4385 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004386 }
4387
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004388 rsp.scid = cpu_to_le16(chan->dcid);
4389 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004390 rsp.result = cpu_to_le16(res);
4391 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004392 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4393 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394 }
4395
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396 bh_unlock_sock(sk);
4397 }
4398
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004399 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004400
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401 return 0;
4402}
4403
4404static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4405{
4406 struct l2cap_conn *conn = hcon->l2cap_data;
4407
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004408 if (!conn)
4409 conn = l2cap_conn_add(hcon, 0);
4410
4411 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412 goto drop;
4413
4414 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4415
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004416 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004418 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004419 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420 int len;
4421
4422 if (conn->rx_len) {
4423 BT_ERR("Unexpected start frame (len %d)", skb->len);
4424 kfree_skb(conn->rx_skb);
4425 conn->rx_skb = NULL;
4426 conn->rx_len = 0;
4427 l2cap_conn_unreliable(conn, ECOMM);
4428 }
4429
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004430 /* Start fragment always begin with Basic L2CAP header */
4431 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004432 BT_ERR("Frame is too short (len %d)", skb->len);
4433 l2cap_conn_unreliable(conn, ECOMM);
4434 goto drop;
4435 }
4436
4437 hdr = (struct l2cap_hdr *) skb->data;
4438 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004439 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440
4441 if (len == skb->len) {
4442 /* Complete frame received */
4443 l2cap_recv_frame(conn, skb);
4444 return 0;
4445 }
4446
4447 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4448
4449 if (skb->len > len) {
4450 BT_ERR("Frame is too long (len %d, expected len %d)",
4451 skb->len, len);
4452 l2cap_conn_unreliable(conn, ECOMM);
4453 goto drop;
4454 }
4455
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004456 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004457
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004458 if (chan && chan->sk) {
4459 struct sock *sk = chan->sk;
4460
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004461 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004462 BT_ERR("Frame exceeding recv MTU (len %d, "
4463 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004464 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004465 bh_unlock_sock(sk);
4466 l2cap_conn_unreliable(conn, ECOMM);
4467 goto drop;
4468 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004469 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004470 }
4471
Linus Torvalds1da177e2005-04-16 15:20:36 -07004472 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004473 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4474 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004475 goto drop;
4476
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004477 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004478 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004479 conn->rx_len = len - skb->len;
4480 } else {
4481 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4482
4483 if (!conn->rx_len) {
4484 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4485 l2cap_conn_unreliable(conn, ECOMM);
4486 goto drop;
4487 }
4488
4489 if (skb->len > conn->rx_len) {
4490 BT_ERR("Fragment is too long (len %d, expected %d)",
4491 skb->len, conn->rx_len);
4492 kfree_skb(conn->rx_skb);
4493 conn->rx_skb = NULL;
4494 conn->rx_len = 0;
4495 l2cap_conn_unreliable(conn, ECOMM);
4496 goto drop;
4497 }
4498
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004499 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004500 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004501 conn->rx_len -= skb->len;
4502
4503 if (!conn->rx_len) {
4504 /* Complete frame received */
4505 l2cap_recv_frame(conn, conn->rx_skb);
4506 conn->rx_skb = NULL;
4507 }
4508 }
4509
4510drop:
4511 kfree_skb(skb);
4512 return 0;
4513}
4514
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004515static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004516{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004517 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004518
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004519 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004520
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004521 list_for_each_entry(c, &chan_list, global_l) {
4522 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004523
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004524 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 +01004525 batostr(&bt_sk(sk)->src),
4526 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004527 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004528 c->scid, c->dcid, c->imtu, c->omtu,
4529 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004530}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004531
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004532 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004533
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004534 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004535}
4536
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004537static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4538{
4539 return single_open(file, l2cap_debugfs_show, inode->i_private);
4540}
4541
4542static const struct file_operations l2cap_debugfs_fops = {
4543 .open = l2cap_debugfs_open,
4544 .read = seq_read,
4545 .llseek = seq_lseek,
4546 .release = single_release,
4547};
4548
4549static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550
Linus Torvalds1da177e2005-04-16 15:20:36 -07004551static struct hci_proto l2cap_hci_proto = {
4552 .name = "L2CAP",
4553 .id = HCI_PROTO_L2CAP,
4554 .connect_ind = l2cap_connect_ind,
4555 .connect_cfm = l2cap_connect_cfm,
4556 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004557 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004558 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004559 .recv_acldata = l2cap_recv_acldata
4560};
4561
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004562int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004563{
4564 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004565
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004566 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004567 if (err < 0)
4568 return err;
4569
Linus Torvalds1da177e2005-04-16 15:20:36 -07004570 err = hci_register_proto(&l2cap_hci_proto);
4571 if (err < 0) {
4572 BT_ERR("L2CAP protocol registration failed");
4573 bt_sock_unregister(BTPROTO_L2CAP);
4574 goto error;
4575 }
4576
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004577 if (bt_debugfs) {
4578 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4579 bt_debugfs, NULL, &l2cap_debugfs_fops);
4580 if (!l2cap_debugfs)
4581 BT_ERR("Failed to create L2CAP debug file");
4582 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004583
Linus Torvalds1da177e2005-04-16 15:20:36 -07004584 return 0;
4585
4586error:
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004587 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004588 return err;
4589}
4590
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004591void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004592{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004593 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004594
Linus Torvalds1da177e2005-04-16 15:20:36 -07004595 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4596 BT_ERR("L2CAP protocol unregistration failed");
4597
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004598 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004599}
4600
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004601module_param(disable_ertm, bool, 0644);
4602MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03004603
4604module_param(enable_hs, bool, 0644);
4605MODULE_PARM_DESC(enable_hs, "Enable High Speed");