blob: ac2c41ada0fe7f13607dd8c0f681485431094ec0 [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
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200569 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200570}
571
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300572static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300573{
574 struct sk_buff *skb;
575 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300576 struct l2cap_conn *conn = chan->conn;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300577 int count, hlen;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200578 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300579
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300580 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300581 return;
582
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300583 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
584 hlen = L2CAP_EXT_HDR_SIZE;
585 else
586 hlen = L2CAP_ENH_HDR_SIZE;
587
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300588 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300589 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300590
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300591 BT_DBG("chan %p, control 0x%8.8x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300592
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300593 count = min_t(unsigned int, conn->mtu, hlen);
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +0300594
595 control |= __set_sframe(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300596
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300597 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +0300598 control |= __set_ctrl_final(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300599
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300600 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +0300601 control |= __set_ctrl_poll(chan);
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300602
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300603 skb = bt_skb_alloc(count, GFP_ATOMIC);
604 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300605 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300606
607 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300608 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300609 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300610
611 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300612
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300613 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300614 u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
615 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300616 }
617
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200618 if (lmp_no_flush_capable(conn->hcon->hdev))
619 flags = ACL_START_NO_FLUSH;
620 else
621 flags = ACL_START;
622
Andrei Emeltchenko15770b12011-10-11 14:04:33 +0300623 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700624
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300625 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300626}
627
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300628static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300629{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300630 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300631 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300632 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300633 } else
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300634 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300635
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300636 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300637
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300638 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300639}
640
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300641static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300642{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300643 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300644}
645
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300646static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200647{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300648 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200649
650 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100651 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
652 return;
653
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300654 if (l2cap_check_security(chan) &&
655 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200656 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300657 req.scid = cpu_to_le16(chan->scid);
658 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200659
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300660 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300661 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200662
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300663 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
664 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200665 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200666 } else {
667 struct l2cap_info_req req;
668 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
669
670 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
671 conn->info_ident = l2cap_get_ident(conn);
672
673 mod_timer(&conn->info_timer, jiffies +
674 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
675
676 l2cap_send_cmd(conn, conn->info_ident,
677 L2CAP_INFO_REQ, sizeof(req), &req);
678 }
679}
680
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300681static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
682{
683 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300684 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300685 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
686
687 switch (mode) {
688 case L2CAP_MODE_ERTM:
689 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
690 case L2CAP_MODE_STREAMING:
691 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
692 default:
693 return 0x00;
694 }
695}
696
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300697static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300698{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300699 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300700 struct l2cap_disconn_req req;
701
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300702 if (!conn)
703 return;
704
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300705 sk = chan->sk;
706
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300707 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300708 __clear_retrans_timer(chan);
709 __clear_monitor_timer(chan);
710 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300711 }
712
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300713 req.dcid = cpu_to_le16(chan->dcid);
714 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300715 l2cap_send_cmd(conn, l2cap_get_ident(conn),
716 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300717
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300718 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300719 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300720}
721
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200723static void l2cap_conn_start(struct l2cap_conn *conn)
724{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300725 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200726
727 BT_DBG("conn %p", conn);
728
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300729 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200730
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300731 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300732 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300733
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200734 bh_lock_sock(sk);
735
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300736 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200737 bh_unlock_sock(sk);
738 continue;
739 }
740
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300741 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300742 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300743
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300744 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300745 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300746 bh_unlock_sock(sk);
747 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200748 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300749
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300750 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
751 && test_bit(CONF_STATE2_DEVICE,
752 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300753 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300754 * so release the lock */
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300755 read_unlock(&conn->chan_lock);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300756 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300757 read_lock(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300758 bh_unlock_sock(sk);
759 continue;
760 }
761
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300762 req.scid = cpu_to_le16(chan->scid);
763 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300764
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300765 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300766 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300767
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300768 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
769 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300770
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300771 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200772 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300773 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300774 rsp.scid = cpu_to_le16(chan->dcid);
775 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200776
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300777 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100778 if (bt_sk(sk)->defer_setup) {
779 struct sock *parent = bt_sk(sk)->parent;
780 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
781 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +0000782 if (parent)
783 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100784
785 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300786 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100787 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
788 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
789 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200790 } else {
791 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
792 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
793 }
794
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300795 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
796 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300797
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300798 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300799 rsp.result != L2CAP_CR_SUCCESS) {
800 bh_unlock_sock(sk);
801 continue;
802 }
803
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300804 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300805 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300806 l2cap_build_conf_req(chan, buf), buf);
807 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200808 }
809
810 bh_unlock_sock(sk);
811 }
812
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300813 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200814}
815
Ville Tervob62f3282011-02-10 22:38:50 -0300816/* Find socket with cid and source bdaddr.
817 * Returns closest match, locked.
818 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300819static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300820{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300821 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300822
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300823 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300824
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300825 list_for_each_entry(c, &chan_list, global_l) {
826 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300827
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300828 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300829 continue;
830
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300831 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300832 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300833 if (!bacmp(&bt_sk(sk)->src, src)) {
834 read_unlock(&chan_list_lock);
835 return c;
836 }
Ville Tervob62f3282011-02-10 22:38:50 -0300837
838 /* Closest match */
839 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300840 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300841 }
842 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300843
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300844 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300845
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300846 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300847}
848
849static void l2cap_le_conn_ready(struct l2cap_conn *conn)
850{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300851 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300852 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300853
854 BT_DBG("");
855
856 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300857 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300858 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300859 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300860 return;
861
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300862 parent = pchan->sk;
863
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300864 bh_lock_sock(parent);
865
Ville Tervob62f3282011-02-10 22:38:50 -0300866 /* Check for backlog size */
867 if (sk_acceptq_is_full(parent)) {
868 BT_DBG("backlog full %d", parent->sk_ack_backlog);
869 goto clean;
870 }
871
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300872 chan = pchan->ops->new_connection(pchan->data);
873 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300874 goto clean;
875
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300876 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300877
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300878 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300879
880 hci_conn_hold(conn->hcon);
881
Ville Tervob62f3282011-02-10 22:38:50 -0300882 bacpy(&bt_sk(sk)->src, conn->src);
883 bacpy(&bt_sk(sk)->dst, conn->dst);
884
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300885 bt_accept_enqueue(parent, sk);
886
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300887 __l2cap_chan_add(conn, chan);
888
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300889 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300890
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300891 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300892 parent->sk_data_ready(parent, 0);
893
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300894 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300895
896clean:
897 bh_unlock_sock(parent);
898}
899
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300900static void l2cap_chan_ready(struct sock *sk)
901{
902 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
903 struct sock *parent = bt_sk(sk)->parent;
904
905 BT_DBG("sk %p, parent %p", sk, parent);
906
907 chan->conf_state = 0;
908 __clear_chan_timer(chan);
909
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300910 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300911 sk->sk_state_change(sk);
912
913 if (parent)
914 parent->sk_data_ready(parent, 0);
915}
916
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200917static void l2cap_conn_ready(struct l2cap_conn *conn)
918{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300919 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200920
921 BT_DBG("conn %p", conn);
922
Ville Tervob62f3282011-02-10 22:38:50 -0300923 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
924 l2cap_le_conn_ready(conn);
925
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -0300926 if (conn->hcon->out && conn->hcon->type == LE_LINK)
927 smp_conn_security(conn, conn->hcon->pending_sec_level);
928
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300929 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200930
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300931 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300932 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300933
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200934 bh_lock_sock(sk);
935
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300936 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300937 if (smp_conn_security(conn, chan->sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300938 l2cap_chan_ready(sk);
Ville Tervoacd7d372011-02-10 22:38:49 -0300939
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300940 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300941 __clear_chan_timer(chan);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300942 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200943 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300944
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300945 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300946 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200947
948 bh_unlock_sock(sk);
949 }
950
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300951 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200952}
953
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200954/* Notify sockets that we cannot guaranty reliability anymore */
955static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
956{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300957 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200958
959 BT_DBG("conn %p", conn);
960
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300961 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200962
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300963 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300964 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300965
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +0300966 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200967 sk->sk_err = err;
968 }
969
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300970 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200971}
972
973static void l2cap_info_timeout(unsigned long arg)
974{
975 struct l2cap_conn *conn = (void *) arg;
976
Marcel Holtmann984947d2009-02-06 23:35:19 +0100977 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100978 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100979
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200980 l2cap_conn_start(conn);
981}
982
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300983static void l2cap_conn_del(struct hci_conn *hcon, int err)
984{
985 struct l2cap_conn *conn = hcon->l2cap_data;
986 struct l2cap_chan *chan, *l;
987 struct sock *sk;
988
989 if (!conn)
990 return;
991
992 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
993
994 kfree_skb(conn->rx_skb);
995
996 /* Kill channels */
997 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
998 sk = chan->sk;
999 bh_lock_sock(sk);
1000 l2cap_chan_del(chan, err);
1001 bh_unlock_sock(sk);
1002 chan->ops->close(chan->data);
1003 }
1004
1005 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1006 del_timer_sync(&conn->info_timer);
1007
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001008 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) {
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001009 del_timer(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001010 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001011 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001012
1013 hcon->l2cap_data = NULL;
1014 kfree(conn);
1015}
1016
1017static void security_timeout(unsigned long arg)
1018{
1019 struct l2cap_conn *conn = (void *) arg;
1020
1021 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1022}
1023
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1025{
Marcel Holtmann01394182006-07-03 10:02:46 +02001026 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027
Marcel Holtmann01394182006-07-03 10:02:46 +02001028 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 return conn;
1030
Marcel Holtmann01394182006-07-03 10:02:46 +02001031 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1032 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034
1035 hcon->l2cap_data = conn;
1036 conn->hcon = hcon;
1037
Marcel Holtmann01394182006-07-03 10:02:46 +02001038 BT_DBG("hcon %p conn %p", hcon, conn);
1039
Ville Tervoacd7d372011-02-10 22:38:49 -03001040 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1041 conn->mtu = hcon->hdev->le_mtu;
1042 else
1043 conn->mtu = hcon->hdev->acl_mtu;
1044
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 conn->src = &hcon->hdev->bdaddr;
1046 conn->dst = &hcon->dst;
1047
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001048 conn->feat_mask = 0;
1049
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001051 rwlock_init(&conn->chan_lock);
1052
1053 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001055 if (hcon->type == LE_LINK)
1056 setup_timer(&conn->security_timer, security_timeout,
1057 (unsigned long) conn);
1058 else
Ville Tervob62f3282011-02-10 22:38:50 -03001059 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +00001060 (unsigned long) conn);
1061
Marcel Holtmann2950f212009-02-12 14:02:50 +01001062 conn->disc_reason = 0x13;
1063
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 return conn;
1065}
1066
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001067static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001069 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001070 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001071 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072}
1073
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075
1076/* Find socket with psm and source bdaddr.
1077 * Returns closest match.
1078 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001079static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001081 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001083 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001084
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001085 list_for_each_entry(c, &chan_list, global_l) {
1086 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001087
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001088 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 continue;
1090
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001091 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001093 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001094 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001095 return c;
1096 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097
1098 /* Closest match */
1099 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001100 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 }
1102 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001104 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001105
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001106 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107}
1108
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001109int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001111 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 bdaddr_t *src = &bt_sk(sk)->src;
1113 bdaddr_t *dst = &bt_sk(sk)->dst;
1114 struct l2cap_conn *conn;
1115 struct hci_conn *hcon;
1116 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001117 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001118 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001120 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001121 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001123 hdev = hci_get_route(dst, src);
1124 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 return -EHOSTUNREACH;
1126
1127 hci_dev_lock_bh(hdev);
1128
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001129 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001130
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001131 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001132 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001133 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001134 else
1135 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001136 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001137
Ville Tervo30e76272011-02-22 16:10:53 -03001138 if (IS_ERR(hcon)) {
1139 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001141 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
1143 conn = l2cap_conn_add(hcon, 0);
1144 if (!conn) {
1145 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001146 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 goto done;
1148 }
1149
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 /* Update source addr of the socket */
1151 bacpy(src, conn->src);
1152
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001153 l2cap_chan_add(conn, chan);
1154
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001155 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001156 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157
1158 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001159 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001160 __clear_chan_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001161 if (l2cap_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001162 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001163 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001164 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 }
1166
Ville Tervo30e76272011-02-22 16:10:53 -03001167 err = 0;
1168
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169done:
1170 hci_dev_unlock_bh(hdev);
1171 hci_dev_put(hdev);
1172 return err;
1173}
1174
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001175int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001176{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001177 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001178 DECLARE_WAITQUEUE(wait, current);
1179 int err = 0;
1180 int timeo = HZ/5;
1181
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001182 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001183 set_current_state(TASK_INTERRUPTIBLE);
1184 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001185 if (!timeo)
1186 timeo = HZ/5;
1187
1188 if (signal_pending(current)) {
1189 err = sock_intr_errno(timeo);
1190 break;
1191 }
1192
1193 release_sock(sk);
1194 timeo = schedule_timeout(timeo);
1195 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001196 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001197
1198 err = sock_error(sk);
1199 if (err)
1200 break;
1201 }
1202 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001203 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001204 return err;
1205}
1206
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001207static void l2cap_monitor_timeout(unsigned long arg)
1208{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001209 struct l2cap_chan *chan = (void *) arg;
1210 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001211
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001212 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001213
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001214 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001215 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001216 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001217 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001218 return;
1219 }
1220
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001221 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001222 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001223
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001224 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001225 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001226}
1227
1228static void l2cap_retrans_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. Padovan49208c92011-04-04 15:59:54 -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. Padovan6a026612011-04-01 00:38:50 -03001236 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001237 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001238
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001239 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001240
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001241 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001242 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001243}
1244
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001245static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001246{
1247 struct sk_buff *skb;
1248
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001249 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001250 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001251 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001252 break;
1253
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001254 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001255 kfree_skb(skb);
1256
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001257 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001258 }
1259
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001260 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001261 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001262}
1263
Szymon Janc67c9e842011-07-28 16:24:33 +02001264static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001265{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001266 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001267 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001268
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001269 BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
1270 skb->priority);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001271
Andrei Emeltchenkod57b0e82011-10-11 14:04:31 +03001272 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
1273 lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001274 flags = ACL_START_NO_FLUSH;
1275 else
1276 flags = ACL_START;
1277
Andrei Emeltchenko15770b12011-10-11 14:04:33 +03001278 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001279 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001280}
1281
Szymon Janc67c9e842011-07-28 16:24:33 +02001282static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001283{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001284 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001285 u32 control;
1286 u16 fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001287
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001288 while ((skb = skb_dequeue(&chan->tx_q))) {
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001289 control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001290 control |= __set_txseq(chan, chan->next_tx_seq);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001291 __put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001292
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001293 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001294 fcs = crc16(0, (u8 *)skb->data,
1295 skb->len - L2CAP_FCS_SIZE);
1296 put_unaligned_le16(fcs,
1297 skb->data + skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001298 }
1299
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001300 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001301
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001302 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001303 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001304}
1305
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001306static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001307{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001308 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001309 u16 fcs;
1310 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001311
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001312 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001313 if (!skb)
1314 return;
1315
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001316 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001317 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001318 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001319
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001320 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001321 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001322
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001323 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001324
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001325 if (chan->remote_max_tx &&
1326 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001327 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001328 return;
1329 }
1330
1331 tx_skb = skb_clone(skb, GFP_ATOMIC);
1332 bt_cb(skb)->retries++;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001333
1334 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001335 control &= __get_sar_mask(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001336
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001337 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001338 control |= __set_ctrl_final(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001339
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001340 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001341 control |= __set_txseq(chan, tx_seq);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001342
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001343 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001344
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001345 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001346 fcs = crc16(0, (u8 *)tx_skb->data,
1347 tx_skb->len - L2CAP_FCS_SIZE);
1348 put_unaligned_le16(fcs,
1349 tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001350 }
1351
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001352 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001353}
1354
Szymon Janc67c9e842011-07-28 16:24:33 +02001355static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001356{
1357 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001358 u16 fcs;
1359 u32 control;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001360 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001361
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001362 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001363 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001364
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001365 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001366
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001367 if (chan->remote_max_tx &&
1368 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001369 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001370 break;
1371 }
1372
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001373 tx_skb = skb_clone(skb, GFP_ATOMIC);
1374
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001375 bt_cb(skb)->retries++;
1376
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001377 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001378 control &= __get_sar_mask(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001379
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001380 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001381 control |= __set_ctrl_final(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001382
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001383 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001384 control |= __set_txseq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001385
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001386 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001387
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001388 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001389 fcs = crc16(0, (u8 *)skb->data,
1390 tx_skb->len - L2CAP_FCS_SIZE);
1391 put_unaligned_le16(fcs, skb->data +
1392 tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001393 }
1394
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001395 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001396
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001397 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001398
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001399 bt_cb(skb)->tx_seq = chan->next_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001400
1401 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001402
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301403 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001404 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301405
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001406 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001407
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001408 if (skb_queue_is_last(&chan->tx_q, skb))
1409 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001410 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001411 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001412
1413 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001414 }
1415
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001416 return nsent;
1417}
1418
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001419static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001420{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001421 int ret;
1422
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001423 if (!skb_queue_empty(&chan->tx_q))
1424 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001425
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001426 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001427 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001428 return ret;
1429}
1430
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001431static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001432{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001433 u32 control = 0;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001434
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001435 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001436
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001437 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001438 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001439 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001440 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001441 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001442 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001443
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001444 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001445 return;
1446
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001447 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001448 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001449}
1450
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001451static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001452{
1453 struct srej_list *tail;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001454 u32 control;
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001455
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001456 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001457 control |= __set_ctrl_final(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001458
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001459 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001460 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001461
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001462 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001463}
1464
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001465static 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 -07001466{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001467 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001468 struct sk_buff **frag;
1469 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001471 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001472 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473
1474 sent += count;
1475 len -= count;
1476
1477 /* Continuation fragments (no L2CAP header) */
1478 frag = &skb_shinfo(skb)->frag_list;
1479 while (len) {
1480 count = min_t(unsigned int, conn->mtu, len);
1481
1482 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1483 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001484 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001485 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1486 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001488 (*frag)->priority = skb->priority;
1489
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 sent += count;
1491 len -= count;
1492
1493 frag = &(*frag)->next;
1494 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495
1496 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001497}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001499static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
1500 struct msghdr *msg, size_t len,
1501 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001502{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001503 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001504 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001505 struct sk_buff *skb;
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001506 int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001507 struct l2cap_hdr *lh;
1508
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001509 BT_DBG("sk %p len %d priority %u", sk, (int)len, priority);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001510
1511 count = min_t(unsigned int, (conn->mtu - hlen), len);
1512 skb = bt_skb_send_alloc(sk, count + hlen,
1513 msg->msg_flags & MSG_DONTWAIT, &err);
1514 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001515 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001516
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001517 skb->priority = priority;
1518
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001519 /* Create L2CAP header */
1520 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001521 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001522 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001523 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001524
1525 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1526 if (unlikely(err < 0)) {
1527 kfree_skb(skb);
1528 return ERR_PTR(err);
1529 }
1530 return skb;
1531}
1532
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001533static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
1534 struct msghdr *msg, size_t len,
1535 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001536{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001537 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001538 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001539 struct sk_buff *skb;
1540 int err, count, hlen = L2CAP_HDR_SIZE;
1541 struct l2cap_hdr *lh;
1542
1543 BT_DBG("sk %p len %d", sk, (int)len);
1544
1545 count = min_t(unsigned int, (conn->mtu - hlen), len);
1546 skb = bt_skb_send_alloc(sk, count + hlen,
1547 msg->msg_flags & MSG_DONTWAIT, &err);
1548 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001549 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001550
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001551 skb->priority = priority;
1552
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001553 /* Create L2CAP header */
1554 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001555 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001556 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1557
1558 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1559 if (unlikely(err < 0)) {
1560 kfree_skb(skb);
1561 return ERR_PTR(err);
1562 }
1563 return skb;
1564}
1565
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001566static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1567 struct msghdr *msg, size_t len,
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001568 u32 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001569{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001570 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001571 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001572 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001573 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001574 struct l2cap_hdr *lh;
1575
1576 BT_DBG("sk %p len %d", sk, (int)len);
1577
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001578 if (!conn)
1579 return ERR_PTR(-ENOTCONN);
1580
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001581 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1582 hlen = L2CAP_EXT_HDR_SIZE;
1583 else
1584 hlen = L2CAP_ENH_HDR_SIZE;
1585
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001586 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001587 hlen += L2CAP_SDULEN_SIZE;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001588
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001589 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001590 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001591
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001592 count = min_t(unsigned int, (conn->mtu - hlen), len);
1593 skb = bt_skb_send_alloc(sk, count + hlen,
1594 msg->msg_flags & MSG_DONTWAIT, &err);
1595 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001596 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001597
1598 /* Create L2CAP header */
1599 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001600 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001601 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001602
1603 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
1604
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001605 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001606 put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001607
1608 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1609 if (unlikely(err < 0)) {
1610 kfree_skb(skb);
1611 return ERR_PTR(err);
1612 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001613
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001614 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001615 put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001616
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001617 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001618 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619}
1620
Szymon Janc67c9e842011-07-28 16:24:33 +02001621static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001622{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001623 struct sk_buff *skb;
1624 struct sk_buff_head sar_queue;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001625 u32 control;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001626 size_t size = 0;
1627
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001628 skb_queue_head_init(&sar_queue);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001629 control = __set_ctrl_sar(chan, L2CAP_SAR_START);
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001630 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001631 if (IS_ERR(skb))
1632 return PTR_ERR(skb);
1633
1634 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001635 len -= chan->remote_mps;
1636 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001637
1638 while (len > 0) {
1639 size_t buflen;
1640
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001641 if (len > chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001642 control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001643 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001644 } else {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001645 control = __set_ctrl_sar(chan, L2CAP_SAR_END);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001646 buflen = len;
1647 }
1648
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001649 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001650 if (IS_ERR(skb)) {
1651 skb_queue_purge(&sar_queue);
1652 return PTR_ERR(skb);
1653 }
1654
1655 __skb_queue_tail(&sar_queue, skb);
1656 len -= buflen;
1657 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001658 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001659 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1660 if (chan->tx_send_head == NULL)
1661 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001662
1663 return size;
1664}
1665
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001666int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
1667 u32 priority)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001668{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001669 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001670 u32 control;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001671 int err;
1672
1673 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001674 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001675 skb = l2cap_create_connless_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001676 if (IS_ERR(skb))
1677 return PTR_ERR(skb);
1678
1679 l2cap_do_send(chan, skb);
1680 return len;
1681 }
1682
1683 switch (chan->mode) {
1684 case L2CAP_MODE_BASIC:
1685 /* Check outgoing MTU */
1686 if (len > chan->omtu)
1687 return -EMSGSIZE;
1688
1689 /* Create a basic PDU */
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001690 skb = l2cap_create_basic_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001691 if (IS_ERR(skb))
1692 return PTR_ERR(skb);
1693
1694 l2cap_do_send(chan, skb);
1695 err = len;
1696 break;
1697
1698 case L2CAP_MODE_ERTM:
1699 case L2CAP_MODE_STREAMING:
1700 /* Entire SDU fits into one PDU */
1701 if (len <= chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001702 control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001703 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1704 0);
1705 if (IS_ERR(skb))
1706 return PTR_ERR(skb);
1707
1708 __skb_queue_tail(&chan->tx_q, skb);
1709
1710 if (chan->tx_send_head == NULL)
1711 chan->tx_send_head = skb;
1712
1713 } else {
1714 /* Segment SDU into multiples PDUs */
1715 err = l2cap_sar_segment_sdu(chan, msg, len);
1716 if (err < 0)
1717 return err;
1718 }
1719
1720 if (chan->mode == L2CAP_MODE_STREAMING) {
1721 l2cap_streaming_send(chan);
1722 err = len;
1723 break;
1724 }
1725
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001726 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1727 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001728 err = len;
1729 break;
1730 }
1731
1732 err = l2cap_ertm_send(chan);
1733 if (err >= 0)
1734 err = len;
1735
1736 break;
1737
1738 default:
1739 BT_DBG("bad state %1.1x", chan->mode);
1740 err = -EBADFD;
1741 }
1742
1743 return err;
1744}
1745
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746/* Copy frame to all raw sockets on that connection */
1747static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1748{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001750 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751
1752 BT_DBG("conn %p", conn);
1753
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001754 read_lock(&conn->chan_lock);
1755 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001756 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001757 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 continue;
1759
1760 /* Don't send frame to the socket it came from */
1761 if (skb->sk == sk)
1762 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001763 nskb = skb_clone(skb, GFP_ATOMIC);
1764 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765 continue;
1766
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001767 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 kfree_skb(nskb);
1769 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001770 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771}
1772
1773/* ---- L2CAP signalling commands ---- */
1774static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1775 u8 code, u8 ident, u16 dlen, void *data)
1776{
1777 struct sk_buff *skb, **frag;
1778 struct l2cap_cmd_hdr *cmd;
1779 struct l2cap_hdr *lh;
1780 int len, count;
1781
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001782 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1783 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784
1785 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1786 count = min_t(unsigned int, conn->mtu, len);
1787
1788 skb = bt_skb_alloc(count, GFP_ATOMIC);
1789 if (!skb)
1790 return NULL;
1791
1792 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001793 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001794
1795 if (conn->hcon->type == LE_LINK)
1796 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1797 else
1798 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799
1800 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1801 cmd->code = code;
1802 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001803 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804
1805 if (dlen) {
1806 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1807 memcpy(skb_put(skb, count), data, count);
1808 data += count;
1809 }
1810
1811 len -= skb->len;
1812
1813 /* Continuation fragments (no L2CAP header) */
1814 frag = &skb_shinfo(skb)->frag_list;
1815 while (len) {
1816 count = min_t(unsigned int, conn->mtu, len);
1817
1818 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1819 if (!*frag)
1820 goto fail;
1821
1822 memcpy(skb_put(*frag, count), data, count);
1823
1824 len -= count;
1825 data += count;
1826
1827 frag = &(*frag)->next;
1828 }
1829
1830 return skb;
1831
1832fail:
1833 kfree_skb(skb);
1834 return NULL;
1835}
1836
1837static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1838{
1839 struct l2cap_conf_opt *opt = *ptr;
1840 int len;
1841
1842 len = L2CAP_CONF_OPT_SIZE + opt->len;
1843 *ptr += len;
1844
1845 *type = opt->type;
1846 *olen = opt->len;
1847
1848 switch (opt->len) {
1849 case 1:
1850 *val = *((u8 *) opt->val);
1851 break;
1852
1853 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001854 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 break;
1856
1857 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001858 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 break;
1860
1861 default:
1862 *val = (unsigned long) opt->val;
1863 break;
1864 }
1865
1866 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1867 return len;
1868}
1869
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1871{
1872 struct l2cap_conf_opt *opt = *ptr;
1873
1874 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1875
1876 opt->type = type;
1877 opt->len = len;
1878
1879 switch (len) {
1880 case 1:
1881 *((u8 *) opt->val) = val;
1882 break;
1883
1884 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001885 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 break;
1887
1888 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001889 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 break;
1891
1892 default:
1893 memcpy(opt->val, (void *) val, len);
1894 break;
1895 }
1896
1897 *ptr += L2CAP_CONF_OPT_SIZE + len;
1898}
1899
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001900static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
1901{
1902 struct l2cap_conf_efs efs;
1903
1904 switch(chan->mode) {
1905 case L2CAP_MODE_ERTM:
1906 efs.id = chan->local_id;
1907 efs.stype = chan->local_stype;
1908 efs.msdu = cpu_to_le16(chan->local_msdu);
1909 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1910 efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
1911 efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
1912 break;
1913
1914 case L2CAP_MODE_STREAMING:
1915 efs.id = 1;
1916 efs.stype = L2CAP_SERV_BESTEFFORT;
1917 efs.msdu = cpu_to_le16(chan->local_msdu);
1918 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1919 efs.acc_lat = 0;
1920 efs.flush_to = 0;
1921 break;
1922
1923 default:
1924 return;
1925 }
1926
1927 l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
1928 (unsigned long) &efs);
1929}
1930
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001931static void l2cap_ack_timeout(unsigned long arg)
1932{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001933 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001934
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001935 bh_lock_sock(chan->sk);
1936 l2cap_send_ack(chan);
1937 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001938}
1939
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001940static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001941{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001942 struct sock *sk = chan->sk;
1943
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001944 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001945 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001946 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001947 chan->num_acked = 0;
1948 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001949
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001950 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1951 (unsigned long) chan);
1952 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1953 (unsigned long) chan);
1954 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001955
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001956 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001957
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001958 INIT_LIST_HEAD(&chan->srej_l);
1959
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001960
1961 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001962}
1963
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001964static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1965{
1966 switch (mode) {
1967 case L2CAP_MODE_STREAMING:
1968 case L2CAP_MODE_ERTM:
1969 if (l2cap_mode_supported(mode, remote_feat_mask))
1970 return mode;
1971 /* fall through */
1972 default:
1973 return L2CAP_MODE_BASIC;
1974 }
1975}
1976
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001977static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
1978{
1979 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
1980}
1981
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001982static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
1983{
1984 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
1985}
1986
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001987static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
1988{
1989 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001990 __l2cap_ews_supported(chan)) {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001991 /* use extended control field */
1992 set_bit(FLAG_EXT_CTRL, &chan->flags);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001993 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
1994 } else {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001995 chan->tx_win = min_t(u16, chan->tx_win,
1996 L2CAP_DEFAULT_TX_WINDOW);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001997 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
1998 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001999}
2000
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002001static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002004 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 void *ptr = req->data;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002006 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002008 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002010 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002011 goto done;
2012
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002013 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002014 case L2CAP_MODE_STREAMING:
2015 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002016 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002017 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002018
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002019 if (__l2cap_efs_supported(chan))
2020 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2021
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002022 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002023 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002024 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002025 break;
2026 }
2027
2028done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002029 if (chan->imtu != L2CAP_DEFAULT_MTU)
2030 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002031
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002032 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002033 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002034 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2035 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002036 break;
2037
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002038 rfc.mode = L2CAP_MODE_BASIC;
2039 rfc.txwin_size = 0;
2040 rfc.max_transmit = 0;
2041 rfc.retrans_timeout = 0;
2042 rfc.monitor_timeout = 0;
2043 rfc.max_pdu_size = 0;
2044
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002045 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2046 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002047 break;
2048
2049 case L2CAP_MODE_ERTM:
2050 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002051 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002052 rfc.retrans_timeout = 0;
2053 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002054
2055 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2056 L2CAP_EXT_HDR_SIZE -
2057 L2CAP_SDULEN_SIZE -
2058 L2CAP_FCS_SIZE);
2059 rfc.max_pdu_size = cpu_to_le16(size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002060
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002061 l2cap_txwin_setup(chan);
2062
2063 rfc.txwin_size = min_t(u16, chan->tx_win,
2064 L2CAP_DEFAULT_TX_WINDOW);
2065
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002066 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2067 (unsigned long) &rfc);
2068
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002069 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2070 l2cap_add_opt_efs(&ptr, chan);
2071
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002072 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002073 break;
2074
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002075 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002076 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002077 chan->fcs = L2CAP_FCS_NONE;
2078 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002079 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002080
2081 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2082 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2083 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002084 break;
2085
2086 case L2CAP_MODE_STREAMING:
2087 rfc.mode = L2CAP_MODE_STREAMING;
2088 rfc.txwin_size = 0;
2089 rfc.max_transmit = 0;
2090 rfc.retrans_timeout = 0;
2091 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002092
2093 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2094 L2CAP_EXT_HDR_SIZE -
2095 L2CAP_SDULEN_SIZE -
2096 L2CAP_FCS_SIZE);
2097 rfc.max_pdu_size = cpu_to_le16(size);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002098
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002099 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2100 (unsigned long) &rfc);
2101
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002102 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2103 l2cap_add_opt_efs(&ptr, chan);
2104
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002105 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002106 break;
2107
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002108 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002109 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002110 chan->fcs = L2CAP_FCS_NONE;
2111 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002112 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002113 break;
2114 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002116 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002117 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118
2119 return ptr - data;
2120}
2121
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002122static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002124 struct l2cap_conf_rsp *rsp = data;
2125 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002126 void *req = chan->conf_req;
2127 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002128 int type, hint, olen;
2129 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002130 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002131 struct l2cap_conf_efs efs;
2132 u8 remote_efs = 0;
Marcel Holtmann861d6882007-10-20 13:37:06 +02002133 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002134 u16 result = L2CAP_CONF_SUCCESS;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002135 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002137 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002138
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002139 while (len >= L2CAP_CONF_OPT_SIZE) {
2140 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002142 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002143 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002144
2145 switch (type) {
2146 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002147 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002148 break;
2149
2150 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002151 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002152 break;
2153
2154 case L2CAP_CONF_QOS:
2155 break;
2156
Marcel Holtmann6464f352007-10-20 13:39:51 +02002157 case L2CAP_CONF_RFC:
2158 if (olen == sizeof(rfc))
2159 memcpy(&rfc, (void *) val, olen);
2160 break;
2161
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002162 case L2CAP_CONF_FCS:
2163 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002164 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002165 break;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002166
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002167 case L2CAP_CONF_EFS:
2168 remote_efs = 1;
2169 if (olen == sizeof(efs))
2170 memcpy(&efs, (void *) val, olen);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002171 break;
2172
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002173 case L2CAP_CONF_EWS:
2174 if (!enable_hs)
2175 return -ECONNREFUSED;
2176
2177 set_bit(FLAG_EXT_CTRL, &chan->flags);
2178 set_bit(CONF_EWS_RECV, &chan->conf_state);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002179 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002180 chan->remote_tx_win = val;
2181 break;
2182
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002183 default:
2184 if (hint)
2185 break;
2186
2187 result = L2CAP_CONF_UNKNOWN;
2188 *((u8 *) ptr++) = type;
2189 break;
2190 }
2191 }
2192
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002193 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002194 goto done;
2195
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002196 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002197 case L2CAP_MODE_STREAMING:
2198 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002199 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002200 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002201 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002202 break;
2203 }
2204
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002205 if (remote_efs) {
2206 if (__l2cap_efs_supported(chan))
2207 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2208 else
2209 return -ECONNREFUSED;
2210 }
2211
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002212 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002213 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002214
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002215 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002216 }
2217
2218done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002219 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002220 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002221 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002222
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002223 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002224 return -ECONNREFUSED;
2225
2226 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2227 sizeof(rfc), (unsigned long) &rfc);
2228 }
2229
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002230 if (result == L2CAP_CONF_SUCCESS) {
2231 /* Configure output options and let the other side know
2232 * which ones we don't like. */
2233
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002234 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2235 result = L2CAP_CONF_UNACCEPT;
2236 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002237 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002238 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002239 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002240 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002241
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002242 if (remote_efs) {
2243 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2244 efs.stype != L2CAP_SERV_NOTRAFIC &&
2245 efs.stype != chan->local_stype) {
2246
2247 result = L2CAP_CONF_UNACCEPT;
2248
2249 if (chan->num_conf_req >= 1)
2250 return -ECONNREFUSED;
2251
2252 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002253 sizeof(efs),
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002254 (unsigned long) &efs);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002255 } else {
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002256 /* Send PENDING Conf Rsp */
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002257 result = L2CAP_CONF_PENDING;
2258 set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002259 }
2260 }
2261
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002262 switch (rfc.mode) {
2263 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002264 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002265 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002266 break;
2267
2268 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002269 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2270 chan->remote_tx_win = rfc.txwin_size;
2271 else
2272 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2273
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002274 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002275
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002276 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2277 chan->conn->mtu -
2278 L2CAP_EXT_HDR_SIZE -
2279 L2CAP_SDULEN_SIZE -
2280 L2CAP_FCS_SIZE);
2281 rfc.max_pdu_size = cpu_to_le16(size);
2282 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002283
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002284 rfc.retrans_timeout =
2285 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2286 rfc.monitor_timeout =
2287 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002288
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002289 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002290
2291 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2292 sizeof(rfc), (unsigned long) &rfc);
2293
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002294 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2295 chan->remote_id = efs.id;
2296 chan->remote_stype = efs.stype;
2297 chan->remote_msdu = le16_to_cpu(efs.msdu);
2298 chan->remote_flush_to =
2299 le32_to_cpu(efs.flush_to);
2300 chan->remote_acc_lat =
2301 le32_to_cpu(efs.acc_lat);
2302 chan->remote_sdu_itime =
2303 le32_to_cpu(efs.sdu_itime);
2304 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2305 sizeof(efs), (unsigned long) &efs);
2306 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002307 break;
2308
2309 case L2CAP_MODE_STREAMING:
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002310 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2311 chan->conn->mtu -
2312 L2CAP_EXT_HDR_SIZE -
2313 L2CAP_SDULEN_SIZE -
2314 L2CAP_FCS_SIZE);
2315 rfc.max_pdu_size = cpu_to_le16(size);
2316 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002317
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002318 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002319
2320 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2321 sizeof(rfc), (unsigned long) &rfc);
2322
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002323 break;
2324
2325 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002326 result = L2CAP_CONF_UNACCEPT;
2327
2328 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002329 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002330 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002331
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002332 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002333 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002334 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002335 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002336 rsp->result = cpu_to_le16(result);
2337 rsp->flags = cpu_to_le16(0x0000);
2338
2339 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340}
2341
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002342static 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 -03002343{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002344 struct l2cap_conf_req *req = data;
2345 void *ptr = req->data;
2346 int type, olen;
2347 unsigned long val;
2348 struct l2cap_conf_rfc rfc;
2349
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002350 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002351
2352 while (len >= L2CAP_CONF_OPT_SIZE) {
2353 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2354
2355 switch (type) {
2356 case L2CAP_CONF_MTU:
2357 if (val < L2CAP_DEFAULT_MIN_MTU) {
2358 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002359 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002360 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002361 chan->imtu = val;
2362 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002363 break;
2364
2365 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002366 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002367 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002368 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002369 break;
2370
2371 case L2CAP_CONF_RFC:
2372 if (olen == sizeof(rfc))
2373 memcpy(&rfc, (void *)val, olen);
2374
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002375 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002376 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002377 return -ECONNREFUSED;
2378
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002379 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002380
2381 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2382 sizeof(rfc), (unsigned long) &rfc);
2383 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002384
2385 case L2CAP_CONF_EWS:
2386 chan->tx_win = min_t(u16, val,
2387 L2CAP_DEFAULT_EXT_WINDOW);
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002388 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2389 chan->tx_win);
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002390 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002391 }
2392 }
2393
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002394 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002395 return -ECONNREFUSED;
2396
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002397 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002398
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002399 if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002400 switch (rfc.mode) {
2401 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002402 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2403 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2404 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002405 break;
2406 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002407 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002408 }
2409 }
2410
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002411 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002412 req->flags = cpu_to_le16(0x0000);
2413
2414 return ptr - data;
2415}
2416
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002417static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418{
2419 struct l2cap_conf_rsp *rsp = data;
2420 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002422 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002424 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002425 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002426 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427
2428 return ptr - data;
2429}
2430
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002431void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002432{
2433 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002434 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002435 u8 buf[128];
2436
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002437 rsp.scid = cpu_to_le16(chan->dcid);
2438 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002439 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2440 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2441 l2cap_send_cmd(conn, chan->ident,
2442 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2443
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002444 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002445 return;
2446
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002447 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2448 l2cap_build_conf_req(chan, buf), buf);
2449 chan->num_conf_req++;
2450}
2451
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002452static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002453{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002454 int type, olen;
2455 unsigned long val;
2456 struct l2cap_conf_rfc rfc;
2457
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002458 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002459
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002460 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002461 return;
2462
2463 while (len >= L2CAP_CONF_OPT_SIZE) {
2464 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2465
2466 switch (type) {
2467 case L2CAP_CONF_RFC:
2468 if (olen == sizeof(rfc))
2469 memcpy(&rfc, (void *)val, olen);
2470 goto done;
2471 }
2472 }
2473
2474done:
2475 switch (rfc.mode) {
2476 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002477 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2478 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2479 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002480 break;
2481 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002482 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002483 }
2484}
2485
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002486static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2487{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002488 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002489
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002490 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002491 return 0;
2492
2493 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2494 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002495 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002496
2497 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002498 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002499
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002500 l2cap_conn_start(conn);
2501 }
2502
2503 return 0;
2504}
2505
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2507{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2509 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002510 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002511 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002512 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513
2514 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002515 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516
2517 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2518
2519 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002520 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2521 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522 result = L2CAP_CR_BAD_PSM;
2523 goto sendresp;
2524 }
2525
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002526 parent = pchan->sk;
2527
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002528 bh_lock_sock(parent);
2529
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002530 /* Check if the ACL is secure enough (if not SDP) */
2531 if (psm != cpu_to_le16(0x0001) &&
2532 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002533 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002534 result = L2CAP_CR_SEC_BLOCK;
2535 goto response;
2536 }
2537
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538 result = L2CAP_CR_NO_MEM;
2539
2540 /* Check for backlog size */
2541 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002542 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543 goto response;
2544 }
2545
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002546 chan = pchan->ops->new_connection(pchan->data);
2547 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548 goto response;
2549
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002550 sk = chan->sk;
2551
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002552 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553
2554 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002555 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2556 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002558 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559 goto response;
2560 }
2561
2562 hci_conn_hold(conn->hcon);
2563
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564 bacpy(&bt_sk(sk)->src, conn->src);
2565 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002566 chan->psm = psm;
2567 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002569 bt_accept_enqueue(parent, sk);
2570
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002571 __l2cap_chan_add(conn, chan);
2572
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002573 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002575 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002577 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578
Marcel Holtmann984947d2009-02-06 23:35:19 +01002579 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002580 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002581 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002582 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002583 result = L2CAP_CR_PEND;
2584 status = L2CAP_CS_AUTHOR_PEND;
2585 parent->sk_data_ready(parent, 0);
2586 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002587 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002588 result = L2CAP_CR_SUCCESS;
2589 status = L2CAP_CS_NO_INFO;
2590 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002591 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002592 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002593 result = L2CAP_CR_PEND;
2594 status = L2CAP_CS_AUTHEN_PEND;
2595 }
2596 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002597 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002598 result = L2CAP_CR_PEND;
2599 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600 }
2601
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002602 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603
2604response:
2605 bh_unlock_sock(parent);
2606
2607sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002608 rsp.scid = cpu_to_le16(scid);
2609 rsp.dcid = cpu_to_le16(dcid);
2610 rsp.result = cpu_to_le16(result);
2611 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002613
2614 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2615 struct l2cap_info_req info;
2616 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2617
2618 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2619 conn->info_ident = l2cap_get_ident(conn);
2620
2621 mod_timer(&conn->info_timer, jiffies +
2622 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2623
2624 l2cap_send_cmd(conn, conn->info_ident,
2625 L2CAP_INFO_REQ, sizeof(info), &info);
2626 }
2627
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002628 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002629 result == L2CAP_CR_SUCCESS) {
2630 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002631 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002632 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002633 l2cap_build_conf_req(chan, buf), buf);
2634 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002635 }
2636
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637 return 0;
2638}
2639
2640static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2641{
2642 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2643 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002644 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645 struct sock *sk;
2646 u8 req[128];
2647
2648 scid = __le16_to_cpu(rsp->scid);
2649 dcid = __le16_to_cpu(rsp->dcid);
2650 result = __le16_to_cpu(rsp->result);
2651 status = __le16_to_cpu(rsp->status);
2652
2653 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2654
2655 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002656 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002657 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002658 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002660 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002661 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002662 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663 }
2664
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002665 sk = chan->sk;
2666
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667 switch (result) {
2668 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002669 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002670 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002671 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002672 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002673
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002674 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002675 break;
2676
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002678 l2cap_build_conf_req(chan, req), req);
2679 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 break;
2681
2682 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002683 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684 break;
2685
2686 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002687 /* don't delete l2cap channel if sk is owned by user */
2688 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002689 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002690 __clear_chan_timer(chan);
2691 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002692 break;
2693 }
2694
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002695 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696 break;
2697 }
2698
2699 bh_unlock_sock(sk);
2700 return 0;
2701}
2702
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002703static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002704{
2705 /* FCS is enabled only in ERTM or streaming mode, if one or both
2706 * sides request it.
2707 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002708 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002709 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002710 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002711 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002712}
2713
Al Viro88219a02007-07-29 00:17:25 -07002714static 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 -07002715{
2716 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2717 u16 dcid, flags;
2718 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002719 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002721 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722
2723 dcid = __le16_to_cpu(req->dcid);
2724 flags = __le16_to_cpu(req->flags);
2725
2726 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2727
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002728 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002729 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 return -ENOENT;
2731
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002732 sk = chan->sk;
2733
David S. Miller033b1142011-07-21 13:38:42 -07002734 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002735 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002736
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002737 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2738 rej.scid = cpu_to_le16(chan->scid);
2739 rej.dcid = cpu_to_le16(chan->dcid);
2740
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002741 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2742 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002743 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002744 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002745
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002746 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002747 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002748 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002749 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002750 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002751 L2CAP_CONF_REJECT, flags), rsp);
2752 goto unlock;
2753 }
2754
2755 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002756 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2757 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758
2759 if (flags & 0x0001) {
2760 /* Incomplete config. Send empty response. */
2761 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002762 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002763 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 goto unlock;
2765 }
2766
2767 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002768 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002769 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002770 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002772 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002774 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002775 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002776
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002777 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002778 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002779
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002780 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002781 goto unlock;
2782
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002783 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002784 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002785
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002786 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002787
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002788 chan->next_tx_seq = 0;
2789 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002790 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002791 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002792 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002793
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002795 goto unlock;
2796 }
2797
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002798 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002799 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002801 l2cap_build_conf_req(chan, buf), buf);
2802 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803 }
2804
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002805 /* Got Conf Rsp PENDING from remote side and asume we sent
2806 Conf Rsp PENDING in the code above */
2807 if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
2808 test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2809
2810 /* check compatibility */
2811
2812 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2813 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2814
2815 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002816 l2cap_build_conf_rsp(chan, rsp,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002817 L2CAP_CONF_SUCCESS, 0x0000), rsp);
2818 }
2819
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820unlock:
2821 bh_unlock_sock(sk);
2822 return 0;
2823}
2824
2825static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2826{
2827 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2828 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002829 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002831 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832
2833 scid = __le16_to_cpu(rsp->scid);
2834 flags = __le16_to_cpu(rsp->flags);
2835 result = __le16_to_cpu(rsp->result);
2836
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002837 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2838 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002839
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002840 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002841 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842 return 0;
2843
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002844 sk = chan->sk;
2845
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846 switch (result) {
2847 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002848 l2cap_conf_rfc_get(chan, rsp->data, len);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002849 clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850 break;
2851
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002852 case L2CAP_CONF_PENDING:
2853 set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
2854
2855 if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2856 char buf[64];
2857
2858 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2859 buf, &result);
2860 if (len < 0) {
2861 l2cap_send_disconn_req(conn, chan, ECONNRESET);
2862 goto done;
2863 }
2864
2865 /* check compatibility */
2866
2867 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2868 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2869
2870 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002871 l2cap_build_conf_rsp(chan, buf,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002872 L2CAP_CONF_SUCCESS, 0x0000), buf);
2873 }
2874 goto done;
2875
Linus Torvalds1da177e2005-04-16 15:20:36 -07002876 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002877 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002878 char req[64];
2879
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002880 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002881 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002882 goto done;
2883 }
2884
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002885 /* throw out any old stored conf requests */
2886 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002887 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2888 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002889 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002890 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002891 goto done;
2892 }
2893
2894 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2895 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002896 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002897 if (result != L2CAP_CONF_SUCCESS)
2898 goto done;
2899 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002900 }
2901
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002902 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002903 sk->sk_err = ECONNRESET;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002904 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002905 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906 goto done;
2907 }
2908
2909 if (flags & 0x01)
2910 goto done;
2911
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002912 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002914 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002915 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002916
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002917 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002918 chan->next_tx_seq = 0;
2919 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002920 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002921 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002922 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002923
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924 l2cap_chan_ready(sk);
2925 }
2926
2927done:
2928 bh_unlock_sock(sk);
2929 return 0;
2930}
2931
2932static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2933{
2934 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2935 struct l2cap_disconn_rsp rsp;
2936 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002937 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938 struct sock *sk;
2939
2940 scid = __le16_to_cpu(req->scid);
2941 dcid = __le16_to_cpu(req->dcid);
2942
2943 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2944
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002945 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002946 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947 return 0;
2948
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002949 sk = chan->sk;
2950
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002951 rsp.dcid = cpu_to_le16(chan->scid);
2952 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2954
2955 sk->sk_shutdown = SHUTDOWN_MASK;
2956
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002957 /* don't delete l2cap channel if sk is owned by user */
2958 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002959 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002960 __clear_chan_timer(chan);
2961 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002962 bh_unlock_sock(sk);
2963 return 0;
2964 }
2965
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002966 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002967 bh_unlock_sock(sk);
2968
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002969 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970 return 0;
2971}
2972
2973static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2974{
2975 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2976 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002977 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978 struct sock *sk;
2979
2980 scid = __le16_to_cpu(rsp->scid);
2981 dcid = __le16_to_cpu(rsp->dcid);
2982
2983 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2984
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002985 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002986 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987 return 0;
2988
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002989 sk = chan->sk;
2990
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002991 /* don't delete l2cap channel if sk is owned by user */
2992 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002993 l2cap_state_change(chan,BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002994 __clear_chan_timer(chan);
2995 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002996 bh_unlock_sock(sk);
2997 return 0;
2998 }
2999
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003000 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001 bh_unlock_sock(sk);
3002
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003003 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004 return 0;
3005}
3006
3007static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3008{
3009 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010 u16 type;
3011
3012 type = __le16_to_cpu(req->type);
3013
3014 BT_DBG("type 0x%4.4x", type);
3015
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003016 if (type == L2CAP_IT_FEAT_MASK) {
3017 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003018 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003019 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3020 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3021 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003022 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003023 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3024 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003025 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003026 feat_mask |= L2CAP_FEAT_EXT_FLOW
3027 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003028
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003029 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003030 l2cap_send_cmd(conn, cmd->ident,
3031 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003032 } else if (type == L2CAP_IT_FIXED_CHAN) {
3033 u8 buf[12];
3034 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3035 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3036 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003037 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003038 l2cap_send_cmd(conn, cmd->ident,
3039 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003040 } else {
3041 struct l2cap_info_rsp rsp;
3042 rsp.type = cpu_to_le16(type);
3043 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3044 l2cap_send_cmd(conn, cmd->ident,
3045 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3046 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047
3048 return 0;
3049}
3050
3051static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3052{
3053 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3054 u16 type, result;
3055
3056 type = __le16_to_cpu(rsp->type);
3057 result = __le16_to_cpu(rsp->result);
3058
3059 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3060
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003061 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3062 if (cmd->ident != conn->info_ident ||
3063 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3064 return 0;
3065
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003066 del_timer(&conn->info_timer);
3067
Ville Tervoadb08ed2010-08-04 09:43:33 +03003068 if (result != L2CAP_IR_SUCCESS) {
3069 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3070 conn->info_ident = 0;
3071
3072 l2cap_conn_start(conn);
3073
3074 return 0;
3075 }
3076
Marcel Holtmann984947d2009-02-06 23:35:19 +01003077 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003078 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003079
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003080 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003081 struct l2cap_info_req req;
3082 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3083
3084 conn->info_ident = l2cap_get_ident(conn);
3085
3086 l2cap_send_cmd(conn, conn->info_ident,
3087 L2CAP_INFO_REQ, sizeof(req), &req);
3088 } else {
3089 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3090 conn->info_ident = 0;
3091
3092 l2cap_conn_start(conn);
3093 }
3094 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003095 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003096 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003097
3098 l2cap_conn_start(conn);
3099 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003100
Linus Torvalds1da177e2005-04-16 15:20:36 -07003101 return 0;
3102}
3103
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003104static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02003105 u16 to_multiplier)
3106{
3107 u16 max_latency;
3108
3109 if (min > max || min < 6 || max > 3200)
3110 return -EINVAL;
3111
3112 if (to_multiplier < 10 || to_multiplier > 3200)
3113 return -EINVAL;
3114
3115 if (max >= to_multiplier * 8)
3116 return -EINVAL;
3117
3118 max_latency = (to_multiplier * 8 / max) - 1;
3119 if (latency > 499 || latency > max_latency)
3120 return -EINVAL;
3121
3122 return 0;
3123}
3124
3125static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3126 struct l2cap_cmd_hdr *cmd, u8 *data)
3127{
3128 struct hci_conn *hcon = conn->hcon;
3129 struct l2cap_conn_param_update_req *req;
3130 struct l2cap_conn_param_update_rsp rsp;
3131 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003132 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02003133
3134 if (!(hcon->link_mode & HCI_LM_MASTER))
3135 return -EINVAL;
3136
3137 cmd_len = __le16_to_cpu(cmd->len);
3138 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3139 return -EPROTO;
3140
3141 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003142 min = __le16_to_cpu(req->min);
3143 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02003144 latency = __le16_to_cpu(req->latency);
3145 to_multiplier = __le16_to_cpu(req->to_multiplier);
3146
3147 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3148 min, max, latency, to_multiplier);
3149
3150 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003151
3152 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
3153 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02003154 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3155 else
3156 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3157
3158 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3159 sizeof(rsp), &rsp);
3160
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003161 if (!err)
3162 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
3163
Claudio Takahaside731152011-02-11 19:28:55 -02003164 return 0;
3165}
3166
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003167static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
3168 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
3169{
3170 int err = 0;
3171
3172 switch (cmd->code) {
3173 case L2CAP_COMMAND_REJ:
3174 l2cap_command_rej(conn, cmd, data);
3175 break;
3176
3177 case L2CAP_CONN_REQ:
3178 err = l2cap_connect_req(conn, cmd, data);
3179 break;
3180
3181 case L2CAP_CONN_RSP:
3182 err = l2cap_connect_rsp(conn, cmd, data);
3183 break;
3184
3185 case L2CAP_CONF_REQ:
3186 err = l2cap_config_req(conn, cmd, cmd_len, data);
3187 break;
3188
3189 case L2CAP_CONF_RSP:
3190 err = l2cap_config_rsp(conn, cmd, data);
3191 break;
3192
3193 case L2CAP_DISCONN_REQ:
3194 err = l2cap_disconnect_req(conn, cmd, data);
3195 break;
3196
3197 case L2CAP_DISCONN_RSP:
3198 err = l2cap_disconnect_rsp(conn, cmd, data);
3199 break;
3200
3201 case L2CAP_ECHO_REQ:
3202 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3203 break;
3204
3205 case L2CAP_ECHO_RSP:
3206 break;
3207
3208 case L2CAP_INFO_REQ:
3209 err = l2cap_information_req(conn, cmd, data);
3210 break;
3211
3212 case L2CAP_INFO_RSP:
3213 err = l2cap_information_rsp(conn, cmd, data);
3214 break;
3215
3216 default:
3217 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3218 err = -EINVAL;
3219 break;
3220 }
3221
3222 return err;
3223}
3224
3225static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3226 struct l2cap_cmd_hdr *cmd, u8 *data)
3227{
3228 switch (cmd->code) {
3229 case L2CAP_COMMAND_REJ:
3230 return 0;
3231
3232 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003233 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003234
3235 case L2CAP_CONN_PARAM_UPDATE_RSP:
3236 return 0;
3237
3238 default:
3239 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3240 return -EINVAL;
3241 }
3242}
3243
3244static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3245 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003246{
3247 u8 *data = skb->data;
3248 int len = skb->len;
3249 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003250 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003251
3252 l2cap_raw_recv(conn, skb);
3253
3254 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003255 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3257 data += L2CAP_CMD_HDR_SIZE;
3258 len -= L2CAP_CMD_HDR_SIZE;
3259
Al Viro88219a02007-07-29 00:17:25 -07003260 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261
Al Viro88219a02007-07-29 00:17:25 -07003262 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 -07003263
Al Viro88219a02007-07-29 00:17:25 -07003264 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265 BT_DBG("corrupted command");
3266 break;
3267 }
3268
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003269 if (conn->hcon->type == LE_LINK)
3270 err = l2cap_le_sig_cmd(conn, &cmd, data);
3271 else
3272 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273
3274 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003275 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003276
3277 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003278
3279 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003280 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3282 }
3283
Al Viro88219a02007-07-29 00:17:25 -07003284 data += cmd_len;
3285 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003286 }
3287
3288 kfree_skb(skb);
3289}
3290
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003291static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003292{
3293 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003294 int hdr_size;
3295
3296 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3297 hdr_size = L2CAP_EXT_HDR_SIZE;
3298 else
3299 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003300
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003301 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003302 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003303 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3304 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3305
3306 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003307 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003308 }
3309 return 0;
3310}
3311
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003312static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003313{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003314 u32 control = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003315
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003316 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003317
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003318 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003319
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003320 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003321 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003322 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003323 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003324 }
3325
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003326 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003327 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003328
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003329 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003330
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003331 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003332 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003333 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003334 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003335 }
3336}
3337
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003338static 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 -03003339{
3340 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003341 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003342
3343 bt_cb(skb)->tx_seq = tx_seq;
3344 bt_cb(skb)->sar = sar;
3345
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003346 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003347 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003348 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003349 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003350 }
3351
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003352 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003353
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003354 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003355 if (bt_cb(next_skb)->tx_seq == tx_seq)
3356 return -EINVAL;
3357
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003358 next_tx_seq_offset = __seq_offset(chan,
3359 bt_cb(next_skb)->tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003360
3361 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003362 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003363 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003364 }
3365
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003366 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003367 break;
3368
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003369 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003370
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003371 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003372
3373 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003374}
3375
Mat Martineau84084a32011-07-22 14:54:00 -07003376static void append_skb_frag(struct sk_buff *skb,
3377 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003378{
Mat Martineau84084a32011-07-22 14:54:00 -07003379 /* skb->len reflects data in skb as well as all fragments
3380 * skb->data_len reflects only data in fragments
3381 */
3382 if (!skb_has_frag_list(skb))
3383 skb_shinfo(skb)->frag_list = new_frag;
3384
3385 new_frag->next = NULL;
3386
3387 (*last_frag)->next = new_frag;
3388 *last_frag = new_frag;
3389
3390 skb->len += new_frag->len;
3391 skb->data_len += new_frag->len;
3392 skb->truesize += new_frag->truesize;
3393}
3394
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003395static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
Mat Martineau84084a32011-07-22 14:54:00 -07003396{
3397 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003398
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003399 switch (__get_ctrl_sar(chan, control)) {
3400 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003401 if (chan->sdu)
3402 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003403
Mat Martineau84084a32011-07-22 14:54:00 -07003404 err = chan->ops->recv(chan->data, skb);
3405 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003406
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003407 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003408 if (chan->sdu)
3409 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003410
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003411 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003412 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003413
Mat Martineau84084a32011-07-22 14:54:00 -07003414 if (chan->sdu_len > chan->imtu) {
3415 err = -EMSGSIZE;
3416 break;
3417 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003418
Mat Martineau84084a32011-07-22 14:54:00 -07003419 if (skb->len >= chan->sdu_len)
3420 break;
3421
3422 chan->sdu = skb;
3423 chan->sdu_last_frag = skb;
3424
3425 skb = NULL;
3426 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003427 break;
3428
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003429 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003430 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003431 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003432
Mat Martineau84084a32011-07-22 14:54:00 -07003433 append_skb_frag(chan->sdu, skb,
3434 &chan->sdu_last_frag);
3435 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003436
Mat Martineau84084a32011-07-22 14:54:00 -07003437 if (chan->sdu->len >= chan->sdu_len)
3438 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003439
Mat Martineau84084a32011-07-22 14:54:00 -07003440 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003441 break;
3442
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003443 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003444 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003445 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003446
Mat Martineau84084a32011-07-22 14:54:00 -07003447 append_skb_frag(chan->sdu, skb,
3448 &chan->sdu_last_frag);
3449 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003450
Mat Martineau84084a32011-07-22 14:54:00 -07003451 if (chan->sdu->len != chan->sdu_len)
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, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003455
Mat Martineau84084a32011-07-22 14:54:00 -07003456 if (!err) {
3457 /* Reassembly complete */
3458 chan->sdu = NULL;
3459 chan->sdu_last_frag = NULL;
3460 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003461 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003462 break;
3463 }
3464
Mat Martineau84084a32011-07-22 14:54:00 -07003465 if (err) {
3466 kfree_skb(skb);
3467 kfree_skb(chan->sdu);
3468 chan->sdu = NULL;
3469 chan->sdu_last_frag = NULL;
3470 chan->sdu_len = 0;
3471 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003472
Mat Martineau84084a32011-07-22 14:54:00 -07003473 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003474}
3475
Mat Martineau26f880d2011-07-07 09:39:01 -07003476static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003477{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003478 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003479
Mat Martineau26f880d2011-07-07 09:39:01 -07003480 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003481
Mat Martineau26f880d2011-07-07 09:39:01 -07003482 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3483
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003484 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003485 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Mat Martineau26f880d2011-07-07 09:39:01 -07003486 l2cap_send_sframe(chan, control);
3487
3488 set_bit(CONN_RNR_SENT, &chan->conn_state);
3489
3490 __clear_ack_timer(chan);
3491}
3492
3493static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3494{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003495 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003496
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003497 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003498 goto done;
3499
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003500 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003501 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003502 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003503 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003504 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003505
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003506 __clear_retrans_timer(chan);
3507 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003508
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003509 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003510
3511done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003512 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3513 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003514
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003515 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003516}
3517
Mat Martineaue3281402011-07-07 09:39:02 -07003518void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003519{
Mat Martineaue3281402011-07-07 09:39:02 -07003520 if (chan->mode == L2CAP_MODE_ERTM) {
3521 if (busy)
3522 l2cap_ertm_enter_local_busy(chan);
3523 else
3524 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003525 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003526}
3527
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003528static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003529{
3530 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003531 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003532
Mat Martineaue3281402011-07-07 09:39:02 -07003533 while ((skb = skb_peek(&chan->srej_q)) &&
3534 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3535 int err;
3536
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003537 if (bt_cb(skb)->tx_seq != tx_seq)
3538 break;
3539
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003540 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003541 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003542 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003543
3544 if (err < 0) {
3545 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3546 break;
3547 }
3548
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003549 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
3550 tx_seq = __next_seq(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003551 }
3552}
3553
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003554static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003555{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003556 struct srej_list *l, *tmp;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003557 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003558
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003559 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003560 if (l->tx_seq == tx_seq) {
3561 list_del(&l->list);
3562 kfree(l);
3563 return;
3564 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003565 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003566 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003567 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003568 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003569 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003570 }
3571}
3572
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003573static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003574{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003575 struct srej_list *new;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003576 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003577
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003578 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003579 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003580 control |= __set_reqseq(chan, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003581 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003582
3583 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003584 new->tx_seq = chan->expected_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003585
3586 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
3587
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003588 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003589 }
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003590
3591 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003592}
3593
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003594static 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 -03003595{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003596 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003597 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003598 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003599 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003600 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003601 int err = 0;
3602
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003603 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 -03003604 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003605
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003606 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003607 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003608 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003609 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003610 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003611 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003612 }
3613
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003614 chan->expected_ack_seq = req_seq;
3615 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003616
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003617 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003618
3619 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003620 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003621 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003622 goto drop;
3623 }
3624
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003625 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003626 goto drop;
3627
Mat Martineau02f1b642011-06-29 14:35:19 -07003628 if (tx_seq == chan->expected_tx_seq)
3629 goto expected;
3630
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003631 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003632 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003633
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003634 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003635 struct srej_list, list);
3636 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003637 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003638 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003639
3640 list_del(&first->list);
3641 kfree(first);
3642
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003643 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003644 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003645 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003646 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003647 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003648 }
3649 } else {
3650 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003651
3652 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003653 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003654 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003655
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003656 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003657 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003658 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003659 return 0;
3660 }
3661 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003662 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003663 }
3664 } else {
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003665 expected_tx_seq_offset = __seq_offset(chan,
3666 chan->expected_tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003667
3668 /* duplicated tx_seq */
3669 if (tx_seq_offset < expected_tx_seq_offset)
3670 goto drop;
3671
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003672 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003673
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003674 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003675
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003676 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003677 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003678
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003679 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003680 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003681
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003682 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003683
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003684 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003685
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003686 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003687 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003688 return 0;
3689
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003690expected:
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003691 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003692
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003693 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003694 bt_cb(skb)->tx_seq = tx_seq;
3695 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003696 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003697 return 0;
3698 }
3699
Mat Martineau84084a32011-07-22 14:54:00 -07003700 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003701 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
3702
Mat Martineaue3281402011-07-07 09:39:02 -07003703 if (err < 0) {
3704 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3705 return err;
3706 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003707
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003708 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003709 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003710 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003711 }
3712
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003713 __set_ack_timer(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003714
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003715 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3716 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003717 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003718
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003719 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003720
3721drop:
3722 kfree_skb(skb);
3723 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003724}
3725
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003726static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003727{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003728 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003729 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003730
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003731 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003732 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003733
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003734 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003735 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3736 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3737 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003738 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003739 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003740
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003741 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003742 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003743 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003744 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003745 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003746
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003747 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003748 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003749
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003750 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003751 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003752
3753 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003754 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003755 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003756 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003757
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003758 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3759 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003760 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003761 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003762 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003763 }
3764}
3765
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003766static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003767{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003768 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003769
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003770 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003771
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003772 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003773
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003774 chan->expected_ack_seq = tx_seq;
3775 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003776
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003777 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003778 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003779 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003780 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003781 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003782
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003783 if (test_bit(CONN_WAIT_F, &chan->conn_state))
3784 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003785 }
3786}
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003787static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003788{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003789 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003790
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003791 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003792
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003793 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003794
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003795 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003796 chan->expected_ack_seq = tx_seq;
3797 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003798
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003799 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003800 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003801
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003802 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003803
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003804 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003805 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003806 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003807 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003808 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003809 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003810 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003811 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003812 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003813 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003814 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003815 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003816 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003817 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003818 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003819 }
3820 }
3821}
3822
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003823static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003824{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003825 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003826
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003827 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003828
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003829 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003830 chan->expected_ack_seq = tx_seq;
3831 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003832
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003833 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003834 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003835
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003836 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003837 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003838 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003839 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003840 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003841 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003842
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003843 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003844 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003845 } else {
3846 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
3847 l2cap_send_sframe(chan, rx_control);
3848 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003849}
3850
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003851static 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 -03003852{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003853 BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003854
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003855 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003856 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003857 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003858 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003859 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003860 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003861 }
3862
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003863 switch (__get_ctrl_super(chan, rx_control)) {
3864 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003865 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003866 break;
3867
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003868 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003869 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003870 break;
3871
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003872 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003873 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003874 break;
3875
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003876 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003877 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003878 break;
3879 }
3880
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003881 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003882 return 0;
3883}
3884
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003885static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3886{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003887 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003888 u32 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003889 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003890 int len, next_tx_seq_offset, req_seq_offset;
3891
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003892 control = __get_control(chan, skb->data);
3893 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003894 len = skb->len;
3895
3896 /*
3897 * We can just drop the corrupted I-frame here.
3898 * Receiver will miss it and start proper recovery
3899 * procedures and ask retransmission.
3900 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003901 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003902 goto drop;
3903
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03003904 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003905 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003906
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003907 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003908 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003909
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003910 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003911 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003912 goto drop;
3913 }
3914
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003915 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003916
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003917 req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
3918
3919 next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
3920 chan->expected_ack_seq);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003921
3922 /* check for invalid req-seq */
3923 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003924 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003925 goto drop;
3926 }
3927
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03003928 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003929 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003930 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003931 goto drop;
3932 }
3933
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003934 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003935 } else {
3936 if (len != 0) {
3937 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003938 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003939 goto drop;
3940 }
3941
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003942 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003943 }
3944
3945 return 0;
3946
3947drop:
3948 kfree_skb(skb);
3949 return 0;
3950}
3951
Linus Torvalds1da177e2005-04-16 15:20:36 -07003952static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3953{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003954 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003955 struct sock *sk = NULL;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003956 u32 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003957 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003958 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003960 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003961 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962 BT_DBG("unknown cid 0x%4.4x", cid);
3963 goto drop;
3964 }
3965
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003966 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003967
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003968 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003970 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003971 goto drop;
3972
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003973 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003974 case L2CAP_MODE_BASIC:
3975 /* If socket recv buffers overflows we drop data here
3976 * which is *bad* because L2CAP has to be reliable.
3977 * But we don't have any other choice. L2CAP doesn't
3978 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003979
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003980 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003981 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003983 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003984 goto done;
3985 break;
3986
3987 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003988 if (!sock_owned_by_user(sk)) {
3989 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003990 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003991 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003992 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003993 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003994
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003995 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003996
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003997 case L2CAP_MODE_STREAMING:
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003998 control = __get_control(chan, skb->data);
3999 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004000 len = skb->len;
4001
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004002 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004003 goto drop;
4004
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004005 if (__is_sar_start(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004006 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004007
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004008 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004009 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004010
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004011 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004012 goto drop;
4013
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004014 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004015
Mat Martineau84084a32011-07-22 14:54:00 -07004016 if (chan->expected_tx_seq != tx_seq) {
4017 /* Frame(s) missing - must discard partial SDU */
4018 kfree_skb(chan->sdu);
4019 chan->sdu = NULL;
4020 chan->sdu_last_frag = NULL;
4021 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004022
Mat Martineau84084a32011-07-22 14:54:00 -07004023 /* TODO: Notify userland of missing data */
4024 }
4025
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004026 chan->expected_tx_seq = __next_seq(chan, tx_seq);
Mat Martineau84084a32011-07-22 14:54:00 -07004027
4028 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
4029 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004030
4031 goto done;
4032
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004033 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004034 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004035 break;
4036 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037
4038drop:
4039 kfree_skb(skb);
4040
4041done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004042 if (sk)
4043 bh_unlock_sock(sk);
4044
Linus Torvalds1da177e2005-04-16 15:20:36 -07004045 return 0;
4046}
4047
Al Viro8e036fc2007-07-29 00:16:36 -07004048static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004050 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004051 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004053 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
4054 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055 goto drop;
4056
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004057 sk = chan->sk;
4058
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00004059 bh_lock_sock(sk);
4060
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061 BT_DBG("sk %p, len %d", sk, skb->len);
4062
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004063 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064 goto drop;
4065
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004066 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067 goto drop;
4068
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004069 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004070 goto done;
4071
4072drop:
4073 kfree_skb(skb);
4074
4075done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004076 if (sk)
4077 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078 return 0;
4079}
4080
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004081static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
4082{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004083 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004084 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004085
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004086 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
4087 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004088 goto drop;
4089
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004090 sk = chan->sk;
4091
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004092 bh_lock_sock(sk);
4093
4094 BT_DBG("sk %p, len %d", sk, skb->len);
4095
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004096 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004097 goto drop;
4098
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004099 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004100 goto drop;
4101
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004102 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004103 goto done;
4104
4105drop:
4106 kfree_skb(skb);
4107
4108done:
4109 if (sk)
4110 bh_unlock_sock(sk);
4111 return 0;
4112}
4113
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4115{
4116 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004117 u16 cid, len;
4118 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119
4120 skb_pull(skb, L2CAP_HDR_SIZE);
4121 cid = __le16_to_cpu(lh->cid);
4122 len = __le16_to_cpu(lh->len);
4123
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004124 if (len != skb->len) {
4125 kfree_skb(skb);
4126 return;
4127 }
4128
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4130
4131 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004132 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004133 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134 l2cap_sig_channel(conn, skb);
4135 break;
4136
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004137 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004138 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004139 skb_pull(skb, 2);
4140 l2cap_conless_channel(conn, psm, skb);
4141 break;
4142
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004143 case L2CAP_CID_LE_DATA:
4144 l2cap_att_channel(conn, cid, skb);
4145 break;
4146
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004147 case L2CAP_CID_SMP:
4148 if (smp_sig_channel(conn, skb))
4149 l2cap_conn_del(conn->hcon, EACCES);
4150 break;
4151
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152 default:
4153 l2cap_data_channel(conn, cid, skb);
4154 break;
4155 }
4156}
4157
4158/* ---- L2CAP interface with lower layer (HCI) ---- */
4159
4160static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4161{
4162 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004163 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164
4165 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004166 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004167
4168 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4169
4170 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004171 read_lock(&chan_list_lock);
4172 list_for_each_entry(c, &chan_list, global_l) {
4173 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004174
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004175 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176 continue;
4177
4178 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004179 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004180 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004181 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004183 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4184 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004185 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004186 lm2 |= HCI_LM_MASTER;
4187 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004189 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004190
4191 return exact ? lm1 : lm2;
4192}
4193
4194static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4195{
Marcel Holtmann01394182006-07-03 10:02:46 +02004196 struct l2cap_conn *conn;
4197
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4199
Ville Tervoacd7d372011-02-10 22:38:49 -03004200 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004201 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202
4203 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204 conn = l2cap_conn_add(hcon, status);
4205 if (conn)
4206 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004207 } else
Joe Perchese1750722011-06-29 18:18:29 -07004208 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209
4210 return 0;
4211}
4212
Marcel Holtmann2950f212009-02-12 14:02:50 +01004213static int l2cap_disconn_ind(struct hci_conn *hcon)
4214{
4215 struct l2cap_conn *conn = hcon->l2cap_data;
4216
4217 BT_DBG("hcon %p", hcon);
4218
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03004219 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004220 return 0x13;
4221
4222 return conn->disc_reason;
4223}
4224
4225static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226{
4227 BT_DBG("hcon %p reason %d", hcon, reason);
4228
Ville Tervoacd7d372011-02-10 22:38:49 -03004229 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004230 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231
Joe Perchese1750722011-06-29 18:18:29 -07004232 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004233
Linus Torvalds1da177e2005-04-16 15:20:36 -07004234 return 0;
4235}
4236
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004237static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004238{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004239 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004240 return;
4241
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004242 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004243 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004244 __clear_chan_timer(chan);
4245 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004246 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004247 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004248 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004249 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004250 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004251 }
4252}
4253
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004254static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004255{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004256 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004257 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004258
Marcel Holtmann01394182006-07-03 10:02:46 +02004259 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004261
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262 BT_DBG("conn %p", conn);
4263
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004264 if (hcon->type == LE_LINK) {
4265 smp_distribute_keys(conn, 0);
4266 del_timer(&conn->security_timer);
4267 }
4268
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004269 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004270
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004271 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004272 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004273
Linus Torvalds1da177e2005-04-16 15:20:36 -07004274 bh_lock_sock(sk);
4275
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004276 BT_DBG("chan->scid %d", chan->scid);
4277
4278 if (chan->scid == L2CAP_CID_LE_DATA) {
4279 if (!status && encrypt) {
4280 chan->sec_level = hcon->sec_level;
4281 l2cap_chan_ready(sk);
4282 }
4283
4284 bh_unlock_sock(sk);
4285 continue;
4286 }
4287
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004288 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004289 bh_unlock_sock(sk);
4290 continue;
4291 }
4292
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004293 if (!status && (chan->state == BT_CONNECTED ||
4294 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004295 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004296 bh_unlock_sock(sk);
4297 continue;
4298 }
4299
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004300 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004301 if (!status) {
4302 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004303 req.scid = cpu_to_le16(chan->scid);
4304 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004305
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004306 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004307 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004308
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004309 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004310 L2CAP_CONN_REQ, sizeof(req), &req);
4311 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004312 __clear_chan_timer(chan);
4313 __set_chan_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004314 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004315 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004316 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004317 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004318
4319 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004320 if (bt_sk(sk)->defer_setup) {
4321 struct sock *parent = bt_sk(sk)->parent;
4322 res = L2CAP_CR_PEND;
4323 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004324 if (parent)
4325 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004326 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004327 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004328 res = L2CAP_CR_SUCCESS;
4329 stat = L2CAP_CS_NO_INFO;
4330 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004331 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004332 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004333 __set_chan_timer(chan, HZ / 10);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004334 res = L2CAP_CR_SEC_BLOCK;
4335 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004336 }
4337
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004338 rsp.scid = cpu_to_le16(chan->dcid);
4339 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004340 rsp.result = cpu_to_le16(res);
4341 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004342 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4343 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344 }
4345
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346 bh_unlock_sock(sk);
4347 }
4348
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004349 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004350
Linus Torvalds1da177e2005-04-16 15:20:36 -07004351 return 0;
4352}
4353
4354static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4355{
4356 struct l2cap_conn *conn = hcon->l2cap_data;
4357
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004358 if (!conn)
4359 conn = l2cap_conn_add(hcon, 0);
4360
4361 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004362 goto drop;
4363
4364 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4365
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004366 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004368 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004369 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004370 int len;
4371
4372 if (conn->rx_len) {
4373 BT_ERR("Unexpected start frame (len %d)", skb->len);
4374 kfree_skb(conn->rx_skb);
4375 conn->rx_skb = NULL;
4376 conn->rx_len = 0;
4377 l2cap_conn_unreliable(conn, ECOMM);
4378 }
4379
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004380 /* Start fragment always begin with Basic L2CAP header */
4381 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382 BT_ERR("Frame is too short (len %d)", skb->len);
4383 l2cap_conn_unreliable(conn, ECOMM);
4384 goto drop;
4385 }
4386
4387 hdr = (struct l2cap_hdr *) skb->data;
4388 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004389 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004390
4391 if (len == skb->len) {
4392 /* Complete frame received */
4393 l2cap_recv_frame(conn, skb);
4394 return 0;
4395 }
4396
4397 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4398
4399 if (skb->len > len) {
4400 BT_ERR("Frame is too long (len %d, expected len %d)",
4401 skb->len, len);
4402 l2cap_conn_unreliable(conn, ECOMM);
4403 goto drop;
4404 }
4405
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004406 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004407
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004408 if (chan && chan->sk) {
4409 struct sock *sk = chan->sk;
4410
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004411 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004412 BT_ERR("Frame exceeding recv MTU (len %d, "
4413 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004414 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004415 bh_unlock_sock(sk);
4416 l2cap_conn_unreliable(conn, ECOMM);
4417 goto drop;
4418 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004419 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004420 }
4421
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004423 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4424 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004425 goto drop;
4426
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004427 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004428 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429 conn->rx_len = len - skb->len;
4430 } else {
4431 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4432
4433 if (!conn->rx_len) {
4434 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4435 l2cap_conn_unreliable(conn, ECOMM);
4436 goto drop;
4437 }
4438
4439 if (skb->len > conn->rx_len) {
4440 BT_ERR("Fragment is too long (len %d, expected %d)",
4441 skb->len, conn->rx_len);
4442 kfree_skb(conn->rx_skb);
4443 conn->rx_skb = NULL;
4444 conn->rx_len = 0;
4445 l2cap_conn_unreliable(conn, ECOMM);
4446 goto drop;
4447 }
4448
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004449 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004450 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004451 conn->rx_len -= skb->len;
4452
4453 if (!conn->rx_len) {
4454 /* Complete frame received */
4455 l2cap_recv_frame(conn, conn->rx_skb);
4456 conn->rx_skb = NULL;
4457 }
4458 }
4459
4460drop:
4461 kfree_skb(skb);
4462 return 0;
4463}
4464
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004465static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004466{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004467 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004468
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004469 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004470
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004471 list_for_each_entry(c, &chan_list, global_l) {
4472 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004473
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004474 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 +01004475 batostr(&bt_sk(sk)->src),
4476 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004477 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004478 c->scid, c->dcid, c->imtu, c->omtu,
4479 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004480}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004481
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004482 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004483
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004484 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004485}
4486
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004487static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4488{
4489 return single_open(file, l2cap_debugfs_show, inode->i_private);
4490}
4491
4492static const struct file_operations l2cap_debugfs_fops = {
4493 .open = l2cap_debugfs_open,
4494 .read = seq_read,
4495 .llseek = seq_lseek,
4496 .release = single_release,
4497};
4498
4499static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004500
Linus Torvalds1da177e2005-04-16 15:20:36 -07004501static struct hci_proto l2cap_hci_proto = {
4502 .name = "L2CAP",
4503 .id = HCI_PROTO_L2CAP,
4504 .connect_ind = l2cap_connect_ind,
4505 .connect_cfm = l2cap_connect_cfm,
4506 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004507 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004508 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004509 .recv_acldata = l2cap_recv_acldata
4510};
4511
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004512int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004513{
4514 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004515
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004516 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004517 if (err < 0)
4518 return err;
4519
Linus Torvalds1da177e2005-04-16 15:20:36 -07004520 err = hci_register_proto(&l2cap_hci_proto);
4521 if (err < 0) {
4522 BT_ERR("L2CAP protocol registration failed");
4523 bt_sock_unregister(BTPROTO_L2CAP);
4524 goto error;
4525 }
4526
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004527 if (bt_debugfs) {
4528 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4529 bt_debugfs, NULL, &l2cap_debugfs_fops);
4530 if (!l2cap_debugfs)
4531 BT_ERR("Failed to create L2CAP debug file");
4532 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004533
Linus Torvalds1da177e2005-04-16 15:20:36 -07004534 return 0;
4535
4536error:
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004537 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004538 return err;
4539}
4540
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004541void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004542{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004543 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004544
Linus Torvalds1da177e2005-04-16 15:20:36 -07004545 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4546 BT_ERR("L2CAP protocol unregistration failed");
4547
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004548 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004549}
4550
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004551module_param(disable_ertm, bool, 0644);
4552MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03004553
4554module_param(enable_hs, bool, 0644);
4555MODULE_PARM_DESC(enable_hs, "Enable High Speed");