blob: 18b0bba8630f735ff9b824212ae9b2753a012d05 [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. Padovan710f9b0a2011-03-25 14:30:37 -030072static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030073static void l2cap_send_disconn_req(struct l2cap_conn *conn,
74 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030076static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
77
Marcel Holtmann01394182006-07-03 10:02:46 +020078/* ---- L2CAP channels ---- */
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -030079
80static inline void chan_hold(struct l2cap_chan *c)
81{
82 atomic_inc(&c->refcnt);
83}
84
85static inline void chan_put(struct l2cap_chan *c)
86{
87 if (atomic_dec_and_test(&c->refcnt))
88 kfree(c);
89}
90
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030091static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020092{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030093 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030094
95 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030096 if (c->dcid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030097 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020098 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030099 return NULL;
100
Marcel Holtmann01394182006-07-03 10:02:46 +0200101}
102
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300103static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200104{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300105 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300106
107 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300108 if (c->scid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300109 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200110 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300111 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200112}
113
114/* Find channel with given SCID.
115 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300116static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200117{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300118 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300119
120 read_lock(&conn->chan_lock);
121 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300122 if (c)
123 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300124 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300125 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200126}
127
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300128static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200129{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300130 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300131
132 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300133 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300134 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200135 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300136 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200137}
138
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300139static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200140{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300141 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300142
143 read_lock(&conn->chan_lock);
144 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300145 if (c)
146 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300147 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300148 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200149}
150
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300151static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300152{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300153 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300154
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300155 list_for_each_entry(c, &chan_list, global_l) {
156 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300157 goto found;
158 }
159
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300160 c = NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300161found:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300162 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300163}
164
165int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
166{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300167 int err;
168
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300169 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300170
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300171 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300172 err = -EADDRINUSE;
173 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300174 }
175
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300176 if (psm) {
177 chan->psm = psm;
178 chan->sport = psm;
179 err = 0;
180 } else {
181 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300182
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300183 err = -EINVAL;
184 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300185 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300186 chan->psm = cpu_to_le16(p);
187 chan->sport = cpu_to_le16(p);
188 err = 0;
189 break;
190 }
191 }
192
193done:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300194 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300195 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300196}
197
198int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
199{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300200 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300201
202 chan->scid = scid;
203
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300204 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300205
206 return 0;
207}
208
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300209static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200210{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300211 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200212
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300213 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300214 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200215 return cid;
216 }
217
218 return 0;
219}
220
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300221static void l2cap_set_timer(struct l2cap_chan *chan, struct timer_list *timer, long timeout)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300222{
Mat Martineau774e5652011-06-29 14:35:20 -0700223 BT_DBG("chan %p state %d timeout %ld", chan->sk, chan->state, timeout);
Gustavo F. 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;
567
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200568 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200569}
570
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300571static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300572{
573 struct sk_buff *skb;
574 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300575 struct l2cap_conn *conn = chan->conn;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300576 int count, hlen;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200577 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300578
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300579 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300580 return;
581
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300582 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
583 hlen = L2CAP_EXT_HDR_SIZE;
584 else
585 hlen = L2CAP_ENH_HDR_SIZE;
586
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300587 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300588 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300589
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300590 BT_DBG("chan %p, control 0x%8.8x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300591
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300592 count = min_t(unsigned int, conn->mtu, hlen);
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +0300593
594 control |= __set_sframe(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300595
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300596 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +0300597 control |= __set_ctrl_final(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300598
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300599 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +0300600 control |= __set_ctrl_poll(chan);
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300601
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300602 skb = bt_skb_alloc(count, GFP_ATOMIC);
603 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300604 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300605
606 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300607 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300608 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300609
610 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300611
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300612 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300613 u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
614 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300615 }
616
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200617 if (lmp_no_flush_capable(conn->hcon->hdev))
618 flags = ACL_START_NO_FLUSH;
619 else
620 flags = ACL_START;
621
Andrei Emeltchenko15770b12011-10-11 14:04:33 +0300622 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700623
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300624 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300625}
626
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300627static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300628{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300629 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300630 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300631 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300632 } else
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300633 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300634
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300635 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300636
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300637 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300638}
639
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300640static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300641{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300642 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300643}
644
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300645static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200646{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300647 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200648
649 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100650 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
651 return;
652
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300653 if (l2cap_check_security(chan) &&
654 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200655 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300656 req.scid = cpu_to_le16(chan->scid);
657 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200658
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300659 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300660 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200661
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300662 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
663 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200664 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200665 } else {
666 struct l2cap_info_req req;
667 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
668
669 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
670 conn->info_ident = l2cap_get_ident(conn);
671
672 mod_timer(&conn->info_timer, jiffies +
673 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
674
675 l2cap_send_cmd(conn, conn->info_ident,
676 L2CAP_INFO_REQ, sizeof(req), &req);
677 }
678}
679
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300680static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
681{
682 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300683 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300684 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
685
686 switch (mode) {
687 case L2CAP_MODE_ERTM:
688 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
689 case L2CAP_MODE_STREAMING:
690 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
691 default:
692 return 0x00;
693 }
694}
695
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300696static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300697{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300698 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300699 struct l2cap_disconn_req req;
700
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300701 if (!conn)
702 return;
703
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300704 sk = chan->sk;
705
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300706 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300707 __clear_retrans_timer(chan);
708 __clear_monitor_timer(chan);
709 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300710 }
711
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300712 req.dcid = cpu_to_le16(chan->dcid);
713 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300714 l2cap_send_cmd(conn, l2cap_get_ident(conn),
715 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300716
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300717 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300718 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300719}
720
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200722static void l2cap_conn_start(struct l2cap_conn *conn)
723{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300724 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200725
726 BT_DBG("conn %p", conn);
727
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300728 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200729
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300730 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300731 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300732
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200733 bh_lock_sock(sk);
734
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300735 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200736 bh_unlock_sock(sk);
737 continue;
738 }
739
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300740 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300741 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300742
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300743 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300744 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300745 bh_unlock_sock(sk);
746 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200747 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300748
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300749 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
750 && test_bit(CONF_STATE2_DEVICE,
751 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300752 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300753 * so release the lock */
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300754 read_unlock(&conn->chan_lock);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300755 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300756 read_lock(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300757 bh_unlock_sock(sk);
758 continue;
759 }
760
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300761 req.scid = cpu_to_le16(chan->scid);
762 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300763
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300764 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300765 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300766
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300767 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
768 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300769
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300770 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200771 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300772 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300773 rsp.scid = cpu_to_le16(chan->dcid);
774 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200775
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300776 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100777 if (bt_sk(sk)->defer_setup) {
778 struct sock *parent = bt_sk(sk)->parent;
779 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
780 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +0000781 if (parent)
782 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100783
784 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300785 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100786 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
787 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
788 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200789 } else {
790 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
791 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
792 }
793
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300794 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
795 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300796
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300797 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300798 rsp.result != L2CAP_CR_SUCCESS) {
799 bh_unlock_sock(sk);
800 continue;
801 }
802
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300803 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300804 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300805 l2cap_build_conf_req(chan, buf), buf);
806 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200807 }
808
809 bh_unlock_sock(sk);
810 }
811
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300812 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200813}
814
Ville Tervob62f3282011-02-10 22:38:50 -0300815/* Find socket with cid and source bdaddr.
816 * Returns closest match, locked.
817 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300818static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300819{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300820 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300821
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300822 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300823
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300824 list_for_each_entry(c, &chan_list, global_l) {
825 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300826
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300827 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300828 continue;
829
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300830 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300831 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300832 if (!bacmp(&bt_sk(sk)->src, src)) {
833 read_unlock(&chan_list_lock);
834 return c;
835 }
Ville Tervob62f3282011-02-10 22:38:50 -0300836
837 /* Closest match */
838 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300839 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300840 }
841 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300842
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300843 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300844
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300845 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300846}
847
848static void l2cap_le_conn_ready(struct l2cap_conn *conn)
849{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300850 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300851 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300852
853 BT_DBG("");
854
855 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300856 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300857 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300858 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300859 return;
860
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300861 parent = pchan->sk;
862
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300863 bh_lock_sock(parent);
864
Ville Tervob62f3282011-02-10 22:38:50 -0300865 /* Check for backlog size */
866 if (sk_acceptq_is_full(parent)) {
867 BT_DBG("backlog full %d", parent->sk_ack_backlog);
868 goto clean;
869 }
870
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300871 chan = pchan->ops->new_connection(pchan->data);
872 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300873 goto clean;
874
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300875 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300876
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300877 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300878
879 hci_conn_hold(conn->hcon);
880
Ville Tervob62f3282011-02-10 22:38:50 -0300881 bacpy(&bt_sk(sk)->src, conn->src);
882 bacpy(&bt_sk(sk)->dst, conn->dst);
883
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300884 bt_accept_enqueue(parent, sk);
885
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300886 __l2cap_chan_add(conn, chan);
887
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300888 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300889
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300890 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300891 parent->sk_data_ready(parent, 0);
892
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300893 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300894
895clean:
896 bh_unlock_sock(parent);
897}
898
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300899static void l2cap_chan_ready(struct sock *sk)
900{
901 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
902 struct sock *parent = bt_sk(sk)->parent;
903
904 BT_DBG("sk %p, parent %p", sk, parent);
905
906 chan->conf_state = 0;
907 __clear_chan_timer(chan);
908
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300909 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300910 sk->sk_state_change(sk);
911
912 if (parent)
913 parent->sk_data_ready(parent, 0);
914}
915
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200916static void l2cap_conn_ready(struct l2cap_conn *conn)
917{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300918 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200919
920 BT_DBG("conn %p", conn);
921
Ville Tervob62f3282011-02-10 22:38:50 -0300922 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
923 l2cap_le_conn_ready(conn);
924
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -0300925 if (conn->hcon->out && conn->hcon->type == LE_LINK)
926 smp_conn_security(conn, conn->hcon->pending_sec_level);
927
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300928 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200929
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300930 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300931 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300932
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200933 bh_lock_sock(sk);
934
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300935 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300936 if (smp_conn_security(conn, chan->sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300937 l2cap_chan_ready(sk);
Ville Tervoacd7d372011-02-10 22:38:49 -0300938
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300939 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300940 __clear_chan_timer(chan);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300941 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200942 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300943
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300944 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300945 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200946
947 bh_unlock_sock(sk);
948 }
949
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300950 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200951}
952
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200953/* Notify sockets that we cannot guaranty reliability anymore */
954static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
955{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300956 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200957
958 BT_DBG("conn %p", conn);
959
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300960 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200961
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300962 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300963 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300964
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +0300965 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200966 sk->sk_err = err;
967 }
968
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300969 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200970}
971
972static void l2cap_info_timeout(unsigned long arg)
973{
974 struct l2cap_conn *conn = (void *) arg;
975
Marcel Holtmann984947d2009-02-06 23:35:19 +0100976 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100977 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100978
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200979 l2cap_conn_start(conn);
980}
981
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300982static void l2cap_conn_del(struct hci_conn *hcon, int err)
983{
984 struct l2cap_conn *conn = hcon->l2cap_data;
985 struct l2cap_chan *chan, *l;
986 struct sock *sk;
987
988 if (!conn)
989 return;
990
991 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
992
993 kfree_skb(conn->rx_skb);
994
995 /* Kill channels */
996 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
997 sk = chan->sk;
998 bh_lock_sock(sk);
999 l2cap_chan_del(chan, err);
1000 bh_unlock_sock(sk);
1001 chan->ops->close(chan->data);
1002 }
1003
1004 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1005 del_timer_sync(&conn->info_timer);
1006
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001007 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) {
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001008 del_timer(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001009 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001010 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001011
1012 hcon->l2cap_data = NULL;
1013 kfree(conn);
1014}
1015
1016static void security_timeout(unsigned long arg)
1017{
1018 struct l2cap_conn *conn = (void *) arg;
1019
1020 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1021}
1022
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1024{
Marcel Holtmann01394182006-07-03 10:02:46 +02001025 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026
Marcel Holtmann01394182006-07-03 10:02:46 +02001027 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 return conn;
1029
Marcel Holtmann01394182006-07-03 10:02:46 +02001030 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1031 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033
1034 hcon->l2cap_data = conn;
1035 conn->hcon = hcon;
1036
Marcel Holtmann01394182006-07-03 10:02:46 +02001037 BT_DBG("hcon %p conn %p", hcon, conn);
1038
Ville Tervoacd7d372011-02-10 22:38:49 -03001039 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1040 conn->mtu = hcon->hdev->le_mtu;
1041 else
1042 conn->mtu = hcon->hdev->acl_mtu;
1043
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 conn->src = &hcon->hdev->bdaddr;
1045 conn->dst = &hcon->dst;
1046
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001047 conn->feat_mask = 0;
1048
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001050 rwlock_init(&conn->chan_lock);
1051
1052 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001054 if (hcon->type == LE_LINK)
1055 setup_timer(&conn->security_timer, security_timeout,
1056 (unsigned long) conn);
1057 else
Ville Tervob62f3282011-02-10 22:38:50 -03001058 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +00001059 (unsigned long) conn);
1060
Marcel Holtmann2950f212009-02-12 14:02:50 +01001061 conn->disc_reason = 0x13;
1062
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 return conn;
1064}
1065
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001066static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001068 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001069 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001070 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071}
1072
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074
1075/* Find socket with psm and source bdaddr.
1076 * Returns closest match.
1077 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001078static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001080 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001082 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001083
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001084 list_for_each_entry(c, &chan_list, global_l) {
1085 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001086
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001087 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 continue;
1089
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001090 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001092 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001093 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001094 return c;
1095 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096
1097 /* Closest match */
1098 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001099 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 }
1101 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001103 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001104
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001105 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106}
1107
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001108int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001110 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 bdaddr_t *src = &bt_sk(sk)->src;
1112 bdaddr_t *dst = &bt_sk(sk)->dst;
1113 struct l2cap_conn *conn;
1114 struct hci_conn *hcon;
1115 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001116 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001117 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001119 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001120 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001122 hdev = hci_get_route(dst, src);
1123 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 return -EHOSTUNREACH;
1125
1126 hci_dev_lock_bh(hdev);
1127
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001128 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001129
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001130 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001131 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001132 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001133 else
1134 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001135 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001136
Ville Tervo30e76272011-02-22 16:10:53 -03001137 if (IS_ERR(hcon)) {
1138 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001140 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141
1142 conn = l2cap_conn_add(hcon, 0);
1143 if (!conn) {
1144 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001145 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 goto done;
1147 }
1148
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 /* Update source addr of the socket */
1150 bacpy(src, conn->src);
1151
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001152 l2cap_chan_add(conn, chan);
1153
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001154 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001155 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156
1157 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001158 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001159 __clear_chan_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001160 if (l2cap_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001161 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001162 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001163 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 }
1165
Ville Tervo30e76272011-02-22 16:10:53 -03001166 err = 0;
1167
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168done:
1169 hci_dev_unlock_bh(hdev);
1170 hci_dev_put(hdev);
1171 return err;
1172}
1173
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001174int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001175{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001176 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001177 DECLARE_WAITQUEUE(wait, current);
1178 int err = 0;
1179 int timeo = HZ/5;
1180
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001181 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001182 set_current_state(TASK_INTERRUPTIBLE);
1183 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001184 if (!timeo)
1185 timeo = HZ/5;
1186
1187 if (signal_pending(current)) {
1188 err = sock_intr_errno(timeo);
1189 break;
1190 }
1191
1192 release_sock(sk);
1193 timeo = schedule_timeout(timeo);
1194 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001195 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001196
1197 err = sock_error(sk);
1198 if (err)
1199 break;
1200 }
1201 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001202 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001203 return err;
1204}
1205
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001206static void l2cap_monitor_timeout(unsigned long arg)
1207{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001208 struct l2cap_chan *chan = (void *) arg;
1209 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001210
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001211 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001212
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001213 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001214 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001215 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001216 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001217 return;
1218 }
1219
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001220 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001221 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001222
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001223 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001224 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001225}
1226
1227static void l2cap_retrans_timeout(unsigned long arg)
1228{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001229 struct l2cap_chan *chan = (void *) arg;
1230 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001231
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001232 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001233
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001234 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001235 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001236 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001237
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001238 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001239
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001240 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001241 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001242}
1243
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001244static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001245{
1246 struct sk_buff *skb;
1247
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001248 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001249 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001250 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001251 break;
1252
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001253 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001254 kfree_skb(skb);
1255
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001256 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001257 }
1258
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001259 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001260 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001261}
1262
Szymon Janc67c9e842011-07-28 16:24:33 +02001263static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001264{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001265 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001266 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001267
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001268 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001269
Andrei Emeltchenkod57b0e82011-10-11 14:04:31 +03001270 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
1271 lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001272 flags = ACL_START_NO_FLUSH;
1273 else
1274 flags = ACL_START;
1275
Andrei Emeltchenko15770b12011-10-11 14:04:33 +03001276 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001277 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001278}
1279
Szymon Janc67c9e842011-07-28 16:24:33 +02001280static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001281{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001282 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001283 u32 control;
1284 u16 fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001285
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001286 while ((skb = skb_dequeue(&chan->tx_q))) {
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001287 control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001288 control |= __set_txseq(chan, chan->next_tx_seq);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001289 __put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001290
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001291 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001292 fcs = crc16(0, (u8 *)skb->data,
1293 skb->len - L2CAP_FCS_SIZE);
1294 put_unaligned_le16(fcs,
1295 skb->data + skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001296 }
1297
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001298 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001299
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001300 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001301 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001302}
1303
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001304static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001305{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001306 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001307 u16 fcs;
1308 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001309
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001310 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001311 if (!skb)
1312 return;
1313
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001314 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001315 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001316 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001317
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001318 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001319 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001320
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001321 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001322
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001323 if (chan->remote_max_tx &&
1324 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001325 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001326 return;
1327 }
1328
1329 tx_skb = skb_clone(skb, GFP_ATOMIC);
1330 bt_cb(skb)->retries++;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001331
1332 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001333 control &= __get_sar_mask(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001334
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001335 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001336 control |= __set_ctrl_final(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001337
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001338 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001339 control |= __set_txseq(chan, tx_seq);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001340
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001341 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001342
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001343 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001344 fcs = crc16(0, (u8 *)tx_skb->data,
1345 tx_skb->len - L2CAP_FCS_SIZE);
1346 put_unaligned_le16(fcs,
1347 tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001348 }
1349
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001350 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001351}
1352
Szymon Janc67c9e842011-07-28 16:24:33 +02001353static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001354{
1355 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001356 u16 fcs;
1357 u32 control;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001358 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001359
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001360 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001361 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001362
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001363 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001364
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001365 if (chan->remote_max_tx &&
1366 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001367 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001368 break;
1369 }
1370
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001371 tx_skb = skb_clone(skb, GFP_ATOMIC);
1372
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001373 bt_cb(skb)->retries++;
1374
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001375 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001376 control &= __get_sar_mask(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001377
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001378 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001379 control |= __set_ctrl_final(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001380
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001381 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001382 control |= __set_txseq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001383
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001384 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001385
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001386 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001387 fcs = crc16(0, (u8 *)skb->data,
1388 tx_skb->len - L2CAP_FCS_SIZE);
1389 put_unaligned_le16(fcs, skb->data +
1390 tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001391 }
1392
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001393 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001394
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001395 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001396
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001397 bt_cb(skb)->tx_seq = chan->next_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001398
1399 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001400
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301401 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001402 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301403
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001404 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001405
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001406 if (skb_queue_is_last(&chan->tx_q, skb))
1407 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001408 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001409 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001410
1411 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001412 }
1413
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001414 return nsent;
1415}
1416
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001417static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001418{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001419 int ret;
1420
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001421 if (!skb_queue_empty(&chan->tx_q))
1422 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001423
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001424 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001425 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001426 return ret;
1427}
1428
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001429static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001430{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001431 u32 control = 0;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001432
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001433 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001434
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001435 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001436 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001437 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001438 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001439 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001440 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001441
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001442 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001443 return;
1444
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001445 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001446 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001447}
1448
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001449static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001450{
1451 struct srej_list *tail;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001452 u32 control;
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001453
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001454 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001455 control |= __set_ctrl_final(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001456
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001457 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001458 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001459
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001460 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001461}
1462
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001463static 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 -07001464{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001465 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001466 struct sk_buff **frag;
1467 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001469 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001470 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471
1472 sent += count;
1473 len -= count;
1474
1475 /* Continuation fragments (no L2CAP header) */
1476 frag = &skb_shinfo(skb)->frag_list;
1477 while (len) {
1478 count = min_t(unsigned int, conn->mtu, len);
1479
1480 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1481 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001482 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001483 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1484 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485
1486 sent += count;
1487 len -= count;
1488
1489 frag = &(*frag)->next;
1490 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491
1492 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001493}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494
Szymon Janc67c9e842011-07-28 16:24:33 +02001495static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001496{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001497 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001498 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001499 struct sk_buff *skb;
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001500 int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001501 struct l2cap_hdr *lh;
1502
1503 BT_DBG("sk %p len %d", sk, (int)len);
1504
1505 count = min_t(unsigned int, (conn->mtu - hlen), len);
1506 skb = bt_skb_send_alloc(sk, count + hlen,
1507 msg->msg_flags & MSG_DONTWAIT, &err);
1508 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001509 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001510
1511 /* Create L2CAP header */
1512 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001513 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001514 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001515 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001516
1517 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1518 if (unlikely(err < 0)) {
1519 kfree_skb(skb);
1520 return ERR_PTR(err);
1521 }
1522 return skb;
1523}
1524
Szymon Janc67c9e842011-07-28 16:24:33 +02001525static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001526{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001527 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001528 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001529 struct sk_buff *skb;
1530 int err, count, hlen = L2CAP_HDR_SIZE;
1531 struct l2cap_hdr *lh;
1532
1533 BT_DBG("sk %p len %d", sk, (int)len);
1534
1535 count = min_t(unsigned int, (conn->mtu - hlen), len);
1536 skb = bt_skb_send_alloc(sk, count + hlen,
1537 msg->msg_flags & MSG_DONTWAIT, &err);
1538 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001539 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001540
1541 /* Create L2CAP header */
1542 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001543 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001544 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1545
1546 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1547 if (unlikely(err < 0)) {
1548 kfree_skb(skb);
1549 return ERR_PTR(err);
1550 }
1551 return skb;
1552}
1553
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001554static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1555 struct msghdr *msg, size_t len,
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001556 u32 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001557{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001558 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001559 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001560 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001561 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001562 struct l2cap_hdr *lh;
1563
1564 BT_DBG("sk %p len %d", sk, (int)len);
1565
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001566 if (!conn)
1567 return ERR_PTR(-ENOTCONN);
1568
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001569 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1570 hlen = L2CAP_EXT_HDR_SIZE;
1571 else
1572 hlen = L2CAP_ENH_HDR_SIZE;
1573
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001574 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001575 hlen += L2CAP_SDULEN_SIZE;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001576
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001577 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001578 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001579
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001580 count = min_t(unsigned int, (conn->mtu - hlen), len);
1581 skb = bt_skb_send_alloc(sk, count + hlen,
1582 msg->msg_flags & MSG_DONTWAIT, &err);
1583 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001584 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001585
1586 /* Create L2CAP header */
1587 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001588 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001589 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001590
1591 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
1592
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001593 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001594 put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001595
1596 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1597 if (unlikely(err < 0)) {
1598 kfree_skb(skb);
1599 return ERR_PTR(err);
1600 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001601
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001602 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001603 put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001604
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001605 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001606 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607}
1608
Szymon Janc67c9e842011-07-28 16:24:33 +02001609static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001610{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001611 struct sk_buff *skb;
1612 struct sk_buff_head sar_queue;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001613 u32 control;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001614 size_t size = 0;
1615
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001616 skb_queue_head_init(&sar_queue);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001617 control = __set_ctrl_sar(chan, L2CAP_SAR_START);
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001618 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001619 if (IS_ERR(skb))
1620 return PTR_ERR(skb);
1621
1622 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001623 len -= chan->remote_mps;
1624 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001625
1626 while (len > 0) {
1627 size_t buflen;
1628
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001629 if (len > chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001630 control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001631 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001632 } else {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001633 control = __set_ctrl_sar(chan, L2CAP_SAR_END);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001634 buflen = len;
1635 }
1636
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001637 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001638 if (IS_ERR(skb)) {
1639 skb_queue_purge(&sar_queue);
1640 return PTR_ERR(skb);
1641 }
1642
1643 __skb_queue_tail(&sar_queue, skb);
1644 len -= buflen;
1645 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001646 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001647 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1648 if (chan->tx_send_head == NULL)
1649 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001650
1651 return size;
1652}
1653
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001654int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1655{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001656 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001657 u32 control;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001658 int err;
1659
1660 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001661 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001662 skb = l2cap_create_connless_pdu(chan, msg, len);
1663 if (IS_ERR(skb))
1664 return PTR_ERR(skb);
1665
1666 l2cap_do_send(chan, skb);
1667 return len;
1668 }
1669
1670 switch (chan->mode) {
1671 case L2CAP_MODE_BASIC:
1672 /* Check outgoing MTU */
1673 if (len > chan->omtu)
1674 return -EMSGSIZE;
1675
1676 /* Create a basic PDU */
1677 skb = l2cap_create_basic_pdu(chan, msg, len);
1678 if (IS_ERR(skb))
1679 return PTR_ERR(skb);
1680
1681 l2cap_do_send(chan, skb);
1682 err = len;
1683 break;
1684
1685 case L2CAP_MODE_ERTM:
1686 case L2CAP_MODE_STREAMING:
1687 /* Entire SDU fits into one PDU */
1688 if (len <= chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001689 control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001690 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1691 0);
1692 if (IS_ERR(skb))
1693 return PTR_ERR(skb);
1694
1695 __skb_queue_tail(&chan->tx_q, skb);
1696
1697 if (chan->tx_send_head == NULL)
1698 chan->tx_send_head = skb;
1699
1700 } else {
1701 /* Segment SDU into multiples PDUs */
1702 err = l2cap_sar_segment_sdu(chan, msg, len);
1703 if (err < 0)
1704 return err;
1705 }
1706
1707 if (chan->mode == L2CAP_MODE_STREAMING) {
1708 l2cap_streaming_send(chan);
1709 err = len;
1710 break;
1711 }
1712
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001713 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1714 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001715 err = len;
1716 break;
1717 }
1718
1719 err = l2cap_ertm_send(chan);
1720 if (err >= 0)
1721 err = len;
1722
1723 break;
1724
1725 default:
1726 BT_DBG("bad state %1.1x", chan->mode);
1727 err = -EBADFD;
1728 }
1729
1730 return err;
1731}
1732
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733/* Copy frame to all raw sockets on that connection */
1734static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1735{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001737 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738
1739 BT_DBG("conn %p", conn);
1740
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001741 read_lock(&conn->chan_lock);
1742 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001743 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001744 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 continue;
1746
1747 /* Don't send frame to the socket it came from */
1748 if (skb->sk == sk)
1749 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001750 nskb = skb_clone(skb, GFP_ATOMIC);
1751 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 continue;
1753
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001754 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 kfree_skb(nskb);
1756 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001757 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758}
1759
1760/* ---- L2CAP signalling commands ---- */
1761static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1762 u8 code, u8 ident, u16 dlen, void *data)
1763{
1764 struct sk_buff *skb, **frag;
1765 struct l2cap_cmd_hdr *cmd;
1766 struct l2cap_hdr *lh;
1767 int len, count;
1768
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001769 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1770 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771
1772 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1773 count = min_t(unsigned int, conn->mtu, len);
1774
1775 skb = bt_skb_alloc(count, GFP_ATOMIC);
1776 if (!skb)
1777 return NULL;
1778
1779 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001780 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001781
1782 if (conn->hcon->type == LE_LINK)
1783 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1784 else
1785 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786
1787 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1788 cmd->code = code;
1789 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001790 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791
1792 if (dlen) {
1793 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1794 memcpy(skb_put(skb, count), data, count);
1795 data += count;
1796 }
1797
1798 len -= skb->len;
1799
1800 /* Continuation fragments (no L2CAP header) */
1801 frag = &skb_shinfo(skb)->frag_list;
1802 while (len) {
1803 count = min_t(unsigned int, conn->mtu, len);
1804
1805 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1806 if (!*frag)
1807 goto fail;
1808
1809 memcpy(skb_put(*frag, count), data, count);
1810
1811 len -= count;
1812 data += count;
1813
1814 frag = &(*frag)->next;
1815 }
1816
1817 return skb;
1818
1819fail:
1820 kfree_skb(skb);
1821 return NULL;
1822}
1823
1824static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1825{
1826 struct l2cap_conf_opt *opt = *ptr;
1827 int len;
1828
1829 len = L2CAP_CONF_OPT_SIZE + opt->len;
1830 *ptr += len;
1831
1832 *type = opt->type;
1833 *olen = opt->len;
1834
1835 switch (opt->len) {
1836 case 1:
1837 *val = *((u8 *) opt->val);
1838 break;
1839
1840 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001841 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 break;
1843
1844 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001845 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 break;
1847
1848 default:
1849 *val = (unsigned long) opt->val;
1850 break;
1851 }
1852
1853 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1854 return len;
1855}
1856
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1858{
1859 struct l2cap_conf_opt *opt = *ptr;
1860
1861 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1862
1863 opt->type = type;
1864 opt->len = len;
1865
1866 switch (len) {
1867 case 1:
1868 *((u8 *) opt->val) = val;
1869 break;
1870
1871 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001872 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 break;
1874
1875 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001876 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 break;
1878
1879 default:
1880 memcpy(opt->val, (void *) val, len);
1881 break;
1882 }
1883
1884 *ptr += L2CAP_CONF_OPT_SIZE + len;
1885}
1886
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001887static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
1888{
1889 struct l2cap_conf_efs efs;
1890
1891 switch(chan->mode) {
1892 case L2CAP_MODE_ERTM:
1893 efs.id = chan->local_id;
1894 efs.stype = chan->local_stype;
1895 efs.msdu = cpu_to_le16(chan->local_msdu);
1896 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1897 efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
1898 efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
1899 break;
1900
1901 case L2CAP_MODE_STREAMING:
1902 efs.id = 1;
1903 efs.stype = L2CAP_SERV_BESTEFFORT;
1904 efs.msdu = cpu_to_le16(chan->local_msdu);
1905 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1906 efs.acc_lat = 0;
1907 efs.flush_to = 0;
1908 break;
1909
1910 default:
1911 return;
1912 }
1913
1914 l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
1915 (unsigned long) &efs);
1916}
1917
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001918static void l2cap_ack_timeout(unsigned long arg)
1919{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001920 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001921
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001922 bh_lock_sock(chan->sk);
1923 l2cap_send_ack(chan);
1924 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001925}
1926
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001927static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001928{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001929 struct sock *sk = chan->sk;
1930
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001931 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001932 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001933 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001934 chan->num_acked = 0;
1935 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001936
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001937 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1938 (unsigned long) chan);
1939 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1940 (unsigned long) chan);
1941 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001942
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001943 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001944
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001945 INIT_LIST_HEAD(&chan->srej_l);
1946
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001947
1948 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001949}
1950
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001951static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1952{
1953 switch (mode) {
1954 case L2CAP_MODE_STREAMING:
1955 case L2CAP_MODE_ERTM:
1956 if (l2cap_mode_supported(mode, remote_feat_mask))
1957 return mode;
1958 /* fall through */
1959 default:
1960 return L2CAP_MODE_BASIC;
1961 }
1962}
1963
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001964static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
1965{
1966 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
1967}
1968
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001969static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
1970{
1971 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
1972}
1973
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001974static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
1975{
1976 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001977 __l2cap_ews_supported(chan)) {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001978 /* use extended control field */
1979 set_bit(FLAG_EXT_CTRL, &chan->flags);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001980 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
1981 } else {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001982 chan->tx_win = min_t(u16, chan->tx_win,
1983 L2CAP_DEFAULT_TX_WINDOW);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001984 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
1985 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001986}
1987
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03001988static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001991 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 void *ptr = req->data;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03001993 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001995 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001997 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001998 goto done;
1999
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002000 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002001 case L2CAP_MODE_STREAMING:
2002 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002003 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002004 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002005
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002006 if (__l2cap_efs_supported(chan))
2007 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2008
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002009 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002010 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002011 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002012 break;
2013 }
2014
2015done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002016 if (chan->imtu != L2CAP_DEFAULT_MTU)
2017 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002018
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002019 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002020 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002021 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2022 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002023 break;
2024
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002025 rfc.mode = L2CAP_MODE_BASIC;
2026 rfc.txwin_size = 0;
2027 rfc.max_transmit = 0;
2028 rfc.retrans_timeout = 0;
2029 rfc.monitor_timeout = 0;
2030 rfc.max_pdu_size = 0;
2031
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002032 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2033 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002034 break;
2035
2036 case L2CAP_MODE_ERTM:
2037 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002038 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002039 rfc.retrans_timeout = 0;
2040 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002041
2042 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2043 L2CAP_EXT_HDR_SIZE -
2044 L2CAP_SDULEN_SIZE -
2045 L2CAP_FCS_SIZE);
2046 rfc.max_pdu_size = cpu_to_le16(size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002047
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002048 l2cap_txwin_setup(chan);
2049
2050 rfc.txwin_size = min_t(u16, chan->tx_win,
2051 L2CAP_DEFAULT_TX_WINDOW);
2052
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002053 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2054 (unsigned long) &rfc);
2055
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002056 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2057 l2cap_add_opt_efs(&ptr, chan);
2058
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002059 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002060 break;
2061
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002062 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002063 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002064 chan->fcs = L2CAP_FCS_NONE;
2065 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002066 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002067
2068 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2069 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2070 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002071 break;
2072
2073 case L2CAP_MODE_STREAMING:
2074 rfc.mode = L2CAP_MODE_STREAMING;
2075 rfc.txwin_size = 0;
2076 rfc.max_transmit = 0;
2077 rfc.retrans_timeout = 0;
2078 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002079
2080 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2081 L2CAP_EXT_HDR_SIZE -
2082 L2CAP_SDULEN_SIZE -
2083 L2CAP_FCS_SIZE);
2084 rfc.max_pdu_size = cpu_to_le16(size);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002085
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002086 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2087 (unsigned long) &rfc);
2088
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002089 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2090 l2cap_add_opt_efs(&ptr, chan);
2091
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002092 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002093 break;
2094
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002095 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002096 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002097 chan->fcs = L2CAP_FCS_NONE;
2098 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002099 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002100 break;
2101 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002103 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002104 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105
2106 return ptr - data;
2107}
2108
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002109static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002111 struct l2cap_conf_rsp *rsp = data;
2112 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002113 void *req = chan->conf_req;
2114 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002115 int type, hint, olen;
2116 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002117 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002118 struct l2cap_conf_efs efs;
2119 u8 remote_efs = 0;
Marcel Holtmann861d6882007-10-20 13:37:06 +02002120 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002121 u16 result = L2CAP_CONF_SUCCESS;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002122 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002124 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002125
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002126 while (len >= L2CAP_CONF_OPT_SIZE) {
2127 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002129 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002130 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002131
2132 switch (type) {
2133 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002134 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002135 break;
2136
2137 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002138 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002139 break;
2140
2141 case L2CAP_CONF_QOS:
2142 break;
2143
Marcel Holtmann6464f352007-10-20 13:39:51 +02002144 case L2CAP_CONF_RFC:
2145 if (olen == sizeof(rfc))
2146 memcpy(&rfc, (void *) val, olen);
2147 break;
2148
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002149 case L2CAP_CONF_FCS:
2150 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002151 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002152 break;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002153
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002154 case L2CAP_CONF_EFS:
2155 remote_efs = 1;
2156 if (olen == sizeof(efs))
2157 memcpy(&efs, (void *) val, olen);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002158 break;
2159
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002160 case L2CAP_CONF_EWS:
2161 if (!enable_hs)
2162 return -ECONNREFUSED;
2163
2164 set_bit(FLAG_EXT_CTRL, &chan->flags);
2165 set_bit(CONF_EWS_RECV, &chan->conf_state);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002166 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002167 chan->remote_tx_win = val;
2168 break;
2169
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002170 default:
2171 if (hint)
2172 break;
2173
2174 result = L2CAP_CONF_UNKNOWN;
2175 *((u8 *) ptr++) = type;
2176 break;
2177 }
2178 }
2179
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002180 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002181 goto done;
2182
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002183 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002184 case L2CAP_MODE_STREAMING:
2185 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002186 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002187 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002188 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002189 break;
2190 }
2191
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002192 if (remote_efs) {
2193 if (__l2cap_efs_supported(chan))
2194 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2195 else
2196 return -ECONNREFUSED;
2197 }
2198
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002199 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002200 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002201
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002202 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002203 }
2204
2205done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002206 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002207 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002208 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002209
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002210 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002211 return -ECONNREFUSED;
2212
2213 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2214 sizeof(rfc), (unsigned long) &rfc);
2215 }
2216
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002217 if (result == L2CAP_CONF_SUCCESS) {
2218 /* Configure output options and let the other side know
2219 * which ones we don't like. */
2220
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002221 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2222 result = L2CAP_CONF_UNACCEPT;
2223 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002224 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002225 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002226 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002227 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002228
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002229 if (remote_efs) {
2230 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2231 efs.stype != L2CAP_SERV_NOTRAFIC &&
2232 efs.stype != chan->local_stype) {
2233
2234 result = L2CAP_CONF_UNACCEPT;
2235
2236 if (chan->num_conf_req >= 1)
2237 return -ECONNREFUSED;
2238
2239 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002240 sizeof(efs),
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002241 (unsigned long) &efs);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002242 } else {
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002243 /* Send PENDING Conf Rsp */
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002244 result = L2CAP_CONF_PENDING;
2245 set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002246 }
2247 }
2248
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002249 switch (rfc.mode) {
2250 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002251 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002252 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002253 break;
2254
2255 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002256 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2257 chan->remote_tx_win = rfc.txwin_size;
2258 else
2259 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2260
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002261 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002262
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002263 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2264 chan->conn->mtu -
2265 L2CAP_EXT_HDR_SIZE -
2266 L2CAP_SDULEN_SIZE -
2267 L2CAP_FCS_SIZE);
2268 rfc.max_pdu_size = cpu_to_le16(size);
2269 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002270
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002271 rfc.retrans_timeout =
2272 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2273 rfc.monitor_timeout =
2274 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002275
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002276 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002277
2278 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2279 sizeof(rfc), (unsigned long) &rfc);
2280
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002281 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2282 chan->remote_id = efs.id;
2283 chan->remote_stype = efs.stype;
2284 chan->remote_msdu = le16_to_cpu(efs.msdu);
2285 chan->remote_flush_to =
2286 le32_to_cpu(efs.flush_to);
2287 chan->remote_acc_lat =
2288 le32_to_cpu(efs.acc_lat);
2289 chan->remote_sdu_itime =
2290 le32_to_cpu(efs.sdu_itime);
2291 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2292 sizeof(efs), (unsigned long) &efs);
2293 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002294 break;
2295
2296 case L2CAP_MODE_STREAMING:
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002297 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2298 chan->conn->mtu -
2299 L2CAP_EXT_HDR_SIZE -
2300 L2CAP_SDULEN_SIZE -
2301 L2CAP_FCS_SIZE);
2302 rfc.max_pdu_size = cpu_to_le16(size);
2303 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002304
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002305 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002306
2307 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2308 sizeof(rfc), (unsigned long) &rfc);
2309
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002310 break;
2311
2312 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002313 result = L2CAP_CONF_UNACCEPT;
2314
2315 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002316 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002317 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002318
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002319 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002320 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002321 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002322 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002323 rsp->result = cpu_to_le16(result);
2324 rsp->flags = cpu_to_le16(0x0000);
2325
2326 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327}
2328
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002329static 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 -03002330{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002331 struct l2cap_conf_req *req = data;
2332 void *ptr = req->data;
2333 int type, olen;
2334 unsigned long val;
2335 struct l2cap_conf_rfc rfc;
2336
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002337 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002338
2339 while (len >= L2CAP_CONF_OPT_SIZE) {
2340 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2341
2342 switch (type) {
2343 case L2CAP_CONF_MTU:
2344 if (val < L2CAP_DEFAULT_MIN_MTU) {
2345 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002346 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002347 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002348 chan->imtu = val;
2349 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002350 break;
2351
2352 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002353 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002354 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002355 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002356 break;
2357
2358 case L2CAP_CONF_RFC:
2359 if (olen == sizeof(rfc))
2360 memcpy(&rfc, (void *)val, olen);
2361
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002362 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002363 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002364 return -ECONNREFUSED;
2365
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002366 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002367
2368 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2369 sizeof(rfc), (unsigned long) &rfc);
2370 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002371
2372 case L2CAP_CONF_EWS:
2373 chan->tx_win = min_t(u16, val,
2374 L2CAP_DEFAULT_EXT_WINDOW);
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002375 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2376 chan->tx_win);
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002377 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002378 }
2379 }
2380
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002381 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002382 return -ECONNREFUSED;
2383
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002384 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002385
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002386 if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002387 switch (rfc.mode) {
2388 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002389 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2390 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2391 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002392 break;
2393 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002394 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002395 }
2396 }
2397
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002398 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002399 req->flags = cpu_to_le16(0x0000);
2400
2401 return ptr - data;
2402}
2403
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002404static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405{
2406 struct l2cap_conf_rsp *rsp = data;
2407 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002409 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002411 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002412 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002413 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414
2415 return ptr - data;
2416}
2417
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002418void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002419{
2420 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002421 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002422 u8 buf[128];
2423
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002424 rsp.scid = cpu_to_le16(chan->dcid);
2425 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002426 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2427 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2428 l2cap_send_cmd(conn, chan->ident,
2429 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2430
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002431 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002432 return;
2433
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002434 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2435 l2cap_build_conf_req(chan, buf), buf);
2436 chan->num_conf_req++;
2437}
2438
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002439static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002440{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002441 int type, olen;
2442 unsigned long val;
2443 struct l2cap_conf_rfc rfc;
2444
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002445 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002446
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002447 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002448 return;
2449
2450 while (len >= L2CAP_CONF_OPT_SIZE) {
2451 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2452
2453 switch (type) {
2454 case L2CAP_CONF_RFC:
2455 if (olen == sizeof(rfc))
2456 memcpy(&rfc, (void *)val, olen);
2457 goto done;
2458 }
2459 }
2460
2461done:
2462 switch (rfc.mode) {
2463 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002464 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2465 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2466 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002467 break;
2468 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002469 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002470 }
2471}
2472
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002473static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2474{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002475 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002476
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002477 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002478 return 0;
2479
2480 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2481 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002482 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002483
2484 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002485 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002486
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002487 l2cap_conn_start(conn);
2488 }
2489
2490 return 0;
2491}
2492
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2494{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2496 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002497 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002498 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002499 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500
2501 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002502 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503
2504 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2505
2506 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002507 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2508 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509 result = L2CAP_CR_BAD_PSM;
2510 goto sendresp;
2511 }
2512
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002513 parent = pchan->sk;
2514
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002515 bh_lock_sock(parent);
2516
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002517 /* Check if the ACL is secure enough (if not SDP) */
2518 if (psm != cpu_to_le16(0x0001) &&
2519 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002520 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002521 result = L2CAP_CR_SEC_BLOCK;
2522 goto response;
2523 }
2524
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525 result = L2CAP_CR_NO_MEM;
2526
2527 /* Check for backlog size */
2528 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002529 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530 goto response;
2531 }
2532
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002533 chan = pchan->ops->new_connection(pchan->data);
2534 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535 goto response;
2536
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002537 sk = chan->sk;
2538
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002539 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540
2541 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002542 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2543 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002545 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546 goto response;
2547 }
2548
2549 hci_conn_hold(conn->hcon);
2550
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551 bacpy(&bt_sk(sk)->src, conn->src);
2552 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002553 chan->psm = psm;
2554 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002556 bt_accept_enqueue(parent, sk);
2557
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002558 __l2cap_chan_add(conn, chan);
2559
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002560 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002562 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002564 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565
Marcel Holtmann984947d2009-02-06 23:35:19 +01002566 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002567 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002568 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002569 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002570 result = L2CAP_CR_PEND;
2571 status = L2CAP_CS_AUTHOR_PEND;
2572 parent->sk_data_ready(parent, 0);
2573 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002574 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002575 result = L2CAP_CR_SUCCESS;
2576 status = L2CAP_CS_NO_INFO;
2577 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002578 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002579 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002580 result = L2CAP_CR_PEND;
2581 status = L2CAP_CS_AUTHEN_PEND;
2582 }
2583 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002584 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002585 result = L2CAP_CR_PEND;
2586 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 }
2588
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002589 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590
2591response:
2592 bh_unlock_sock(parent);
2593
2594sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002595 rsp.scid = cpu_to_le16(scid);
2596 rsp.dcid = cpu_to_le16(dcid);
2597 rsp.result = cpu_to_le16(result);
2598 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002600
2601 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2602 struct l2cap_info_req info;
2603 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2604
2605 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2606 conn->info_ident = l2cap_get_ident(conn);
2607
2608 mod_timer(&conn->info_timer, jiffies +
2609 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2610
2611 l2cap_send_cmd(conn, conn->info_ident,
2612 L2CAP_INFO_REQ, sizeof(info), &info);
2613 }
2614
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002615 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002616 result == L2CAP_CR_SUCCESS) {
2617 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002618 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002619 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002620 l2cap_build_conf_req(chan, buf), buf);
2621 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002622 }
2623
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624 return 0;
2625}
2626
2627static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2628{
2629 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2630 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002631 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 struct sock *sk;
2633 u8 req[128];
2634
2635 scid = __le16_to_cpu(rsp->scid);
2636 dcid = __le16_to_cpu(rsp->dcid);
2637 result = __le16_to_cpu(rsp->result);
2638 status = __le16_to_cpu(rsp->status);
2639
2640 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2641
2642 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002643 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002644 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002645 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002647 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002648 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002649 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650 }
2651
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002652 sk = chan->sk;
2653
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654 switch (result) {
2655 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002656 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002657 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002658 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002659 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002660
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002661 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002662 break;
2663
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002665 l2cap_build_conf_req(chan, req), req);
2666 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667 break;
2668
2669 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002670 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671 break;
2672
2673 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002674 /* don't delete l2cap channel if sk is owned by user */
2675 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002676 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002677 __clear_chan_timer(chan);
2678 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002679 break;
2680 }
2681
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002682 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683 break;
2684 }
2685
2686 bh_unlock_sock(sk);
2687 return 0;
2688}
2689
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002690static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002691{
2692 /* FCS is enabled only in ERTM or streaming mode, if one or both
2693 * sides request it.
2694 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002695 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002696 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002697 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002698 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002699}
2700
Al Viro88219a02007-07-29 00:17:25 -07002701static 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 -07002702{
2703 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2704 u16 dcid, flags;
2705 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002706 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002708 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709
2710 dcid = __le16_to_cpu(req->dcid);
2711 flags = __le16_to_cpu(req->flags);
2712
2713 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2714
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002715 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002716 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717 return -ENOENT;
2718
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002719 sk = chan->sk;
2720
David S. Miller033b1142011-07-21 13:38:42 -07002721 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002722 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002723
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002724 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2725 rej.scid = cpu_to_le16(chan->scid);
2726 rej.dcid = cpu_to_le16(chan->dcid);
2727
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002728 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2729 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002730 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002731 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002732
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002733 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002734 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002735 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002736 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002737 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002738 L2CAP_CONF_REJECT, flags), rsp);
2739 goto unlock;
2740 }
2741
2742 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002743 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2744 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745
2746 if (flags & 0x0001) {
2747 /* Incomplete config. Send empty response. */
2748 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002749 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002750 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751 goto unlock;
2752 }
2753
2754 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002755 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002756 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002757 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002759 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002761 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002762 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002763
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002764 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002765 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002766
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002767 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002768 goto unlock;
2769
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002770 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002771 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002772
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002773 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002774
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002775 chan->next_tx_seq = 0;
2776 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002777 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002778 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002779 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002780
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002782 goto unlock;
2783 }
2784
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002785 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002786 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002788 l2cap_build_conf_req(chan, buf), buf);
2789 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790 }
2791
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002792 /* Got Conf Rsp PENDING from remote side and asume we sent
2793 Conf Rsp PENDING in the code above */
2794 if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
2795 test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2796
2797 /* check compatibility */
2798
2799 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2800 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2801
2802 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002803 l2cap_build_conf_rsp(chan, rsp,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002804 L2CAP_CONF_SUCCESS, 0x0000), rsp);
2805 }
2806
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807unlock:
2808 bh_unlock_sock(sk);
2809 return 0;
2810}
2811
2812static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2813{
2814 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2815 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002816 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002818 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819
2820 scid = __le16_to_cpu(rsp->scid);
2821 flags = __le16_to_cpu(rsp->flags);
2822 result = __le16_to_cpu(rsp->result);
2823
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002824 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2825 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002827 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002828 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829 return 0;
2830
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002831 sk = chan->sk;
2832
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833 switch (result) {
2834 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002835 l2cap_conf_rfc_get(chan, rsp->data, len);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002836 clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837 break;
2838
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002839 case L2CAP_CONF_PENDING:
2840 set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
2841
2842 if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2843 char buf[64];
2844
2845 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2846 buf, &result);
2847 if (len < 0) {
2848 l2cap_send_disconn_req(conn, chan, ECONNRESET);
2849 goto done;
2850 }
2851
2852 /* check compatibility */
2853
2854 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2855 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2856
2857 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002858 l2cap_build_conf_rsp(chan, buf,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002859 L2CAP_CONF_SUCCESS, 0x0000), buf);
2860 }
2861 goto done;
2862
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002864 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002865 char req[64];
2866
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002867 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002868 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002869 goto done;
2870 }
2871
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002872 /* throw out any old stored conf requests */
2873 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002874 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2875 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002876 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002877 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002878 goto done;
2879 }
2880
2881 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2882 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002883 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002884 if (result != L2CAP_CONF_SUCCESS)
2885 goto done;
2886 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887 }
2888
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002889 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002890 sk->sk_err = ECONNRESET;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002891 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002892 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893 goto done;
2894 }
2895
2896 if (flags & 0x01)
2897 goto done;
2898
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002899 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002900
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002901 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002902 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002903
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002904 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002905 chan->next_tx_seq = 0;
2906 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002907 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002908 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002909 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002910
Linus Torvalds1da177e2005-04-16 15:20:36 -07002911 l2cap_chan_ready(sk);
2912 }
2913
2914done:
2915 bh_unlock_sock(sk);
2916 return 0;
2917}
2918
2919static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2920{
2921 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2922 struct l2cap_disconn_rsp rsp;
2923 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002924 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925 struct sock *sk;
2926
2927 scid = __le16_to_cpu(req->scid);
2928 dcid = __le16_to_cpu(req->dcid);
2929
2930 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2931
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002932 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002933 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002934 return 0;
2935
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002936 sk = chan->sk;
2937
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002938 rsp.dcid = cpu_to_le16(chan->scid);
2939 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2941
2942 sk->sk_shutdown = SHUTDOWN_MASK;
2943
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002944 /* don't delete l2cap channel if sk is owned by user */
2945 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002946 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002947 __clear_chan_timer(chan);
2948 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002949 bh_unlock_sock(sk);
2950 return 0;
2951 }
2952
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002953 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954 bh_unlock_sock(sk);
2955
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002956 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957 return 0;
2958}
2959
2960static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2961{
2962 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2963 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002964 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965 struct sock *sk;
2966
2967 scid = __le16_to_cpu(rsp->scid);
2968 dcid = __le16_to_cpu(rsp->dcid);
2969
2970 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2971
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002972 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002973 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002974 return 0;
2975
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002976 sk = chan->sk;
2977
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002978 /* don't delete l2cap channel if sk is owned by user */
2979 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002980 l2cap_state_change(chan,BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002981 __clear_chan_timer(chan);
2982 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002983 bh_unlock_sock(sk);
2984 return 0;
2985 }
2986
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002987 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988 bh_unlock_sock(sk);
2989
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002990 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991 return 0;
2992}
2993
2994static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2995{
2996 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997 u16 type;
2998
2999 type = __le16_to_cpu(req->type);
3000
3001 BT_DBG("type 0x%4.4x", type);
3002
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003003 if (type == L2CAP_IT_FEAT_MASK) {
3004 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003005 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003006 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3007 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3008 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003009 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003010 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3011 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003012 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003013 feat_mask |= L2CAP_FEAT_EXT_FLOW
3014 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003015
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003016 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003017 l2cap_send_cmd(conn, cmd->ident,
3018 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003019 } else if (type == L2CAP_IT_FIXED_CHAN) {
3020 u8 buf[12];
3021 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3022 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3023 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003024 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003025 l2cap_send_cmd(conn, cmd->ident,
3026 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003027 } else {
3028 struct l2cap_info_rsp rsp;
3029 rsp.type = cpu_to_le16(type);
3030 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3031 l2cap_send_cmd(conn, cmd->ident,
3032 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3033 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034
3035 return 0;
3036}
3037
3038static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3039{
3040 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3041 u16 type, result;
3042
3043 type = __le16_to_cpu(rsp->type);
3044 result = __le16_to_cpu(rsp->result);
3045
3046 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3047
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003048 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3049 if (cmd->ident != conn->info_ident ||
3050 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3051 return 0;
3052
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003053 del_timer(&conn->info_timer);
3054
Ville Tervoadb08ed2010-08-04 09:43:33 +03003055 if (result != L2CAP_IR_SUCCESS) {
3056 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3057 conn->info_ident = 0;
3058
3059 l2cap_conn_start(conn);
3060
3061 return 0;
3062 }
3063
Marcel Holtmann984947d2009-02-06 23:35:19 +01003064 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003065 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003066
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003067 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003068 struct l2cap_info_req req;
3069 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3070
3071 conn->info_ident = l2cap_get_ident(conn);
3072
3073 l2cap_send_cmd(conn, conn->info_ident,
3074 L2CAP_INFO_REQ, sizeof(req), &req);
3075 } else {
3076 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3077 conn->info_ident = 0;
3078
3079 l2cap_conn_start(conn);
3080 }
3081 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003082 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003083 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003084
3085 l2cap_conn_start(conn);
3086 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003087
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088 return 0;
3089}
3090
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003091static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02003092 u16 to_multiplier)
3093{
3094 u16 max_latency;
3095
3096 if (min > max || min < 6 || max > 3200)
3097 return -EINVAL;
3098
3099 if (to_multiplier < 10 || to_multiplier > 3200)
3100 return -EINVAL;
3101
3102 if (max >= to_multiplier * 8)
3103 return -EINVAL;
3104
3105 max_latency = (to_multiplier * 8 / max) - 1;
3106 if (latency > 499 || latency > max_latency)
3107 return -EINVAL;
3108
3109 return 0;
3110}
3111
3112static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3113 struct l2cap_cmd_hdr *cmd, u8 *data)
3114{
3115 struct hci_conn *hcon = conn->hcon;
3116 struct l2cap_conn_param_update_req *req;
3117 struct l2cap_conn_param_update_rsp rsp;
3118 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003119 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02003120
3121 if (!(hcon->link_mode & HCI_LM_MASTER))
3122 return -EINVAL;
3123
3124 cmd_len = __le16_to_cpu(cmd->len);
3125 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3126 return -EPROTO;
3127
3128 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003129 min = __le16_to_cpu(req->min);
3130 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02003131 latency = __le16_to_cpu(req->latency);
3132 to_multiplier = __le16_to_cpu(req->to_multiplier);
3133
3134 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3135 min, max, latency, to_multiplier);
3136
3137 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003138
3139 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
3140 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02003141 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3142 else
3143 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3144
3145 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3146 sizeof(rsp), &rsp);
3147
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003148 if (!err)
3149 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
3150
Claudio Takahaside731152011-02-11 19:28:55 -02003151 return 0;
3152}
3153
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003154static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
3155 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
3156{
3157 int err = 0;
3158
3159 switch (cmd->code) {
3160 case L2CAP_COMMAND_REJ:
3161 l2cap_command_rej(conn, cmd, data);
3162 break;
3163
3164 case L2CAP_CONN_REQ:
3165 err = l2cap_connect_req(conn, cmd, data);
3166 break;
3167
3168 case L2CAP_CONN_RSP:
3169 err = l2cap_connect_rsp(conn, cmd, data);
3170 break;
3171
3172 case L2CAP_CONF_REQ:
3173 err = l2cap_config_req(conn, cmd, cmd_len, data);
3174 break;
3175
3176 case L2CAP_CONF_RSP:
3177 err = l2cap_config_rsp(conn, cmd, data);
3178 break;
3179
3180 case L2CAP_DISCONN_REQ:
3181 err = l2cap_disconnect_req(conn, cmd, data);
3182 break;
3183
3184 case L2CAP_DISCONN_RSP:
3185 err = l2cap_disconnect_rsp(conn, cmd, data);
3186 break;
3187
3188 case L2CAP_ECHO_REQ:
3189 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3190 break;
3191
3192 case L2CAP_ECHO_RSP:
3193 break;
3194
3195 case L2CAP_INFO_REQ:
3196 err = l2cap_information_req(conn, cmd, data);
3197 break;
3198
3199 case L2CAP_INFO_RSP:
3200 err = l2cap_information_rsp(conn, cmd, data);
3201 break;
3202
3203 default:
3204 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3205 err = -EINVAL;
3206 break;
3207 }
3208
3209 return err;
3210}
3211
3212static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3213 struct l2cap_cmd_hdr *cmd, u8 *data)
3214{
3215 switch (cmd->code) {
3216 case L2CAP_COMMAND_REJ:
3217 return 0;
3218
3219 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003220 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003221
3222 case L2CAP_CONN_PARAM_UPDATE_RSP:
3223 return 0;
3224
3225 default:
3226 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3227 return -EINVAL;
3228 }
3229}
3230
3231static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3232 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003233{
3234 u8 *data = skb->data;
3235 int len = skb->len;
3236 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003237 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003238
3239 l2cap_raw_recv(conn, skb);
3240
3241 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003242 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3244 data += L2CAP_CMD_HDR_SIZE;
3245 len -= L2CAP_CMD_HDR_SIZE;
3246
Al Viro88219a02007-07-29 00:17:25 -07003247 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248
Al Viro88219a02007-07-29 00:17:25 -07003249 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 -07003250
Al Viro88219a02007-07-29 00:17:25 -07003251 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003252 BT_DBG("corrupted command");
3253 break;
3254 }
3255
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003256 if (conn->hcon->type == LE_LINK)
3257 err = l2cap_le_sig_cmd(conn, &cmd, data);
3258 else
3259 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260
3261 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003262 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003263
3264 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265
3266 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003267 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003268 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3269 }
3270
Al Viro88219a02007-07-29 00:17:25 -07003271 data += cmd_len;
3272 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273 }
3274
3275 kfree_skb(skb);
3276}
3277
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003278static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003279{
3280 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003281 int hdr_size;
3282
3283 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3284 hdr_size = L2CAP_EXT_HDR_SIZE;
3285 else
3286 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003287
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003288 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003289 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003290 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3291 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3292
3293 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003294 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003295 }
3296 return 0;
3297}
3298
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003299static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003300{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003301 u32 control = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003302
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003303 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003304
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003305 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003306
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003307 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003308 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003309 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003310 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003311 }
3312
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003313 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003314 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003315
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003316 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003317
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003318 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003319 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003320 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003321 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003322 }
3323}
3324
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003325static 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 -03003326{
3327 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003328 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003329
3330 bt_cb(skb)->tx_seq = tx_seq;
3331 bt_cb(skb)->sar = sar;
3332
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003333 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003334 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003335 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003336 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003337 }
3338
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003339 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003340
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003341 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003342 if (bt_cb(next_skb)->tx_seq == tx_seq)
3343 return -EINVAL;
3344
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003345 next_tx_seq_offset = __seq_offset(chan,
3346 bt_cb(next_skb)->tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003347
3348 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003349 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003350 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003351 }
3352
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003353 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003354 break;
3355
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003356 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003357
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003358 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003359
3360 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003361}
3362
Mat Martineau84084a32011-07-22 14:54:00 -07003363static void append_skb_frag(struct sk_buff *skb,
3364 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003365{
Mat Martineau84084a32011-07-22 14:54:00 -07003366 /* skb->len reflects data in skb as well as all fragments
3367 * skb->data_len reflects only data in fragments
3368 */
3369 if (!skb_has_frag_list(skb))
3370 skb_shinfo(skb)->frag_list = new_frag;
3371
3372 new_frag->next = NULL;
3373
3374 (*last_frag)->next = new_frag;
3375 *last_frag = new_frag;
3376
3377 skb->len += new_frag->len;
3378 skb->data_len += new_frag->len;
3379 skb->truesize += new_frag->truesize;
3380}
3381
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003382static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
Mat Martineau84084a32011-07-22 14:54:00 -07003383{
3384 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003385
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003386 switch (__get_ctrl_sar(chan, control)) {
3387 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003388 if (chan->sdu)
3389 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003390
Mat Martineau84084a32011-07-22 14:54:00 -07003391 err = chan->ops->recv(chan->data, skb);
3392 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003393
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003394 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003395 if (chan->sdu)
3396 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003397
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003398 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003399 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003400
Mat Martineau84084a32011-07-22 14:54:00 -07003401 if (chan->sdu_len > chan->imtu) {
3402 err = -EMSGSIZE;
3403 break;
3404 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003405
Mat Martineau84084a32011-07-22 14:54:00 -07003406 if (skb->len >= chan->sdu_len)
3407 break;
3408
3409 chan->sdu = skb;
3410 chan->sdu_last_frag = skb;
3411
3412 skb = NULL;
3413 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003414 break;
3415
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003416 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003417 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003418 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003419
Mat Martineau84084a32011-07-22 14:54:00 -07003420 append_skb_frag(chan->sdu, skb,
3421 &chan->sdu_last_frag);
3422 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003423
Mat Martineau84084a32011-07-22 14:54:00 -07003424 if (chan->sdu->len >= chan->sdu_len)
3425 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003426
Mat Martineau84084a32011-07-22 14:54:00 -07003427 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003428 break;
3429
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003430 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003431 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003432 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003433
Mat Martineau84084a32011-07-22 14:54:00 -07003434 append_skb_frag(chan->sdu, skb,
3435 &chan->sdu_last_frag);
3436 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003437
Mat Martineau84084a32011-07-22 14:54:00 -07003438 if (chan->sdu->len != chan->sdu_len)
3439 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003440
Mat Martineau84084a32011-07-22 14:54:00 -07003441 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003442
Mat Martineau84084a32011-07-22 14:54:00 -07003443 if (!err) {
3444 /* Reassembly complete */
3445 chan->sdu = NULL;
3446 chan->sdu_last_frag = NULL;
3447 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003448 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003449 break;
3450 }
3451
Mat Martineau84084a32011-07-22 14:54:00 -07003452 if (err) {
3453 kfree_skb(skb);
3454 kfree_skb(chan->sdu);
3455 chan->sdu = NULL;
3456 chan->sdu_last_frag = NULL;
3457 chan->sdu_len = 0;
3458 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003459
Mat Martineau84084a32011-07-22 14:54:00 -07003460 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003461}
3462
Mat Martineau26f880d2011-07-07 09:39:01 -07003463static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003464{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003465 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003466
Mat Martineau26f880d2011-07-07 09:39:01 -07003467 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003468
Mat Martineau26f880d2011-07-07 09:39:01 -07003469 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3470
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003471 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003472 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Mat Martineau26f880d2011-07-07 09:39:01 -07003473 l2cap_send_sframe(chan, control);
3474
3475 set_bit(CONN_RNR_SENT, &chan->conn_state);
3476
3477 __clear_ack_timer(chan);
3478}
3479
3480static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3481{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003482 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003483
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003484 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003485 goto done;
3486
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003487 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003488 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003489 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003490 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003491 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003492
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003493 __clear_retrans_timer(chan);
3494 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003495
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003496 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003497
3498done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003499 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3500 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003501
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003502 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003503}
3504
Mat Martineaue3281402011-07-07 09:39:02 -07003505void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003506{
Mat Martineaue3281402011-07-07 09:39:02 -07003507 if (chan->mode == L2CAP_MODE_ERTM) {
3508 if (busy)
3509 l2cap_ertm_enter_local_busy(chan);
3510 else
3511 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003512 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003513}
3514
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003515static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003516{
3517 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003518 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003519
Mat Martineaue3281402011-07-07 09:39:02 -07003520 while ((skb = skb_peek(&chan->srej_q)) &&
3521 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3522 int err;
3523
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003524 if (bt_cb(skb)->tx_seq != tx_seq)
3525 break;
3526
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003527 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003528 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003529 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003530
3531 if (err < 0) {
3532 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3533 break;
3534 }
3535
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003536 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
3537 tx_seq = __next_seq(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003538 }
3539}
3540
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003541static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003542{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003543 struct srej_list *l, *tmp;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003544 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003545
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003546 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003547 if (l->tx_seq == tx_seq) {
3548 list_del(&l->list);
3549 kfree(l);
3550 return;
3551 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003552 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003553 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003554 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003555 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003556 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003557 }
3558}
3559
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003560static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003561{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003562 struct srej_list *new;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003563 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003564
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003565 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003566 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003567 control |= __set_reqseq(chan, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003568 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003569
3570 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003571 new->tx_seq = chan->expected_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003572
3573 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
3574
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003575 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003576 }
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003577
3578 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003579}
3580
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003581static 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 -03003582{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003583 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003584 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003585 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003586 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003587 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003588 int err = 0;
3589
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003590 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 -03003591 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003592
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003593 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003594 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003595 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003596 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003597 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003598 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003599 }
3600
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003601 chan->expected_ack_seq = req_seq;
3602 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003603
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003604 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003605
3606 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003607 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003608 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003609 goto drop;
3610 }
3611
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003612 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003613 goto drop;
3614
Mat Martineau02f1b642011-06-29 14:35:19 -07003615 if (tx_seq == chan->expected_tx_seq)
3616 goto expected;
3617
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003618 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003619 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003620
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003621 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003622 struct srej_list, list);
3623 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003624 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003625 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003626
3627 list_del(&first->list);
3628 kfree(first);
3629
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003630 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003631 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003632 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003633 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003634 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003635 }
3636 } else {
3637 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003638
3639 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003640 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003641 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003642
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003643 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003644 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003645 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003646 return 0;
3647 }
3648 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003649 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003650 }
3651 } else {
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003652 expected_tx_seq_offset = __seq_offset(chan,
3653 chan->expected_tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003654
3655 /* duplicated tx_seq */
3656 if (tx_seq_offset < expected_tx_seq_offset)
3657 goto drop;
3658
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003659 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003660
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003661 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003662
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003663 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003664 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003665
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003666 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003667 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003668
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003669 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003670
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003671 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003672
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003673 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003674 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003675 return 0;
3676
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003677expected:
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003678 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003679
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003680 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003681 bt_cb(skb)->tx_seq = tx_seq;
3682 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003683 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003684 return 0;
3685 }
3686
Mat Martineau84084a32011-07-22 14:54:00 -07003687 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003688 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
3689
Mat Martineaue3281402011-07-07 09:39:02 -07003690 if (err < 0) {
3691 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3692 return err;
3693 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003694
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003695 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003696 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003697 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003698 }
3699
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003700 __set_ack_timer(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003701
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003702 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3703 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003704 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003705
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003706 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003707
3708drop:
3709 kfree_skb(skb);
3710 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003711}
3712
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003713static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003714{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003715 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003716 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003717
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003718 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003719 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003720
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003721 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003722 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3723 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3724 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003725 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003726 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003727
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003728 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003729 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003730 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003731 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003732 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003733
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003734 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003735 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003736
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003737 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003738 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003739
3740 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003741 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003742 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003743 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003744
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003745 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3746 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003747 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003748 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003749 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003750 }
3751}
3752
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003753static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003754{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003755 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003756
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003757 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003758
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003759 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003760
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003761 chan->expected_ack_seq = tx_seq;
3762 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003763
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003764 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003765 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003766 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003767 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003768 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003769
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003770 if (test_bit(CONN_WAIT_F, &chan->conn_state))
3771 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003772 }
3773}
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003774static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003775{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003776 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003777
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003778 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003779
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003780 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003781
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003782 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003783 chan->expected_ack_seq = tx_seq;
3784 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003785
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003786 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003787 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003788
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003789 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003790
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003791 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003792 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003793 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003794 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003795 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003796 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003797 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003798 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003799 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003800 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003801 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003802 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003803 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003804 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003805 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003806 }
3807 }
3808}
3809
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003810static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003811{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003812 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003813
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003814 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003815
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003816 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003817 chan->expected_ack_seq = tx_seq;
3818 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003819
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003820 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003821 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003822
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003823 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003824 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003825 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003826 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003827 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003828 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003829
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003830 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003831 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003832 } else {
3833 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
3834 l2cap_send_sframe(chan, rx_control);
3835 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003836}
3837
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003838static 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 -03003839{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003840 BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003841
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003842 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003843 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003844 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003845 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003846 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003847 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003848 }
3849
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003850 switch (__get_ctrl_super(chan, rx_control)) {
3851 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003852 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003853 break;
3854
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003855 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003856 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003857 break;
3858
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003859 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003860 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003861 break;
3862
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003863 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003864 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003865 break;
3866 }
3867
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003868 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003869 return 0;
3870}
3871
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003872static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3873{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003874 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003875 u32 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003876 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003877 int len, next_tx_seq_offset, req_seq_offset;
3878
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003879 control = __get_control(chan, skb->data);
3880 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003881 len = skb->len;
3882
3883 /*
3884 * We can just drop the corrupted I-frame here.
3885 * Receiver will miss it and start proper recovery
3886 * procedures and ask retransmission.
3887 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003888 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003889 goto drop;
3890
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03003891 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003892 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003893
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003894 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003895 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003896
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003897 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003898 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003899 goto drop;
3900 }
3901
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003902 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003903
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003904 req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
3905
3906 next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
3907 chan->expected_ack_seq);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003908
3909 /* check for invalid req-seq */
3910 if (req_seq_offset > next_tx_seq_offset) {
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 Emeltchenko793c2f12011-10-11 13:37:48 +03003915 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003916 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003917 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003918 goto drop;
3919 }
3920
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003921 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003922 } else {
3923 if (len != 0) {
3924 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003925 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003926 goto drop;
3927 }
3928
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003929 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003930 }
3931
3932 return 0;
3933
3934drop:
3935 kfree_skb(skb);
3936 return 0;
3937}
3938
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3940{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003941 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003942 struct sock *sk = NULL;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003943 u32 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003944 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003945 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003947 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003948 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949 BT_DBG("unknown cid 0x%4.4x", cid);
3950 goto drop;
3951 }
3952
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003953 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003954
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003955 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003957 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 goto drop;
3959
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003960 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003961 case L2CAP_MODE_BASIC:
3962 /* If socket recv buffers overflows we drop data here
3963 * which is *bad* because L2CAP has to be reliable.
3964 * But we don't have any other choice. L2CAP doesn't
3965 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003967 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003968 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003970 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003971 goto done;
3972 break;
3973
3974 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003975 if (!sock_owned_by_user(sk)) {
3976 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003977 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003978 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003979 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003980 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003981
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003982 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003983
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003984 case L2CAP_MODE_STREAMING:
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003985 control = __get_control(chan, skb->data);
3986 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003987 len = skb->len;
3988
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003989 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003990 goto drop;
3991
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003992 if (__is_sar_start(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003993 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003994
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003995 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003996 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003997
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03003998 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003999 goto drop;
4000
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004001 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004002
Mat Martineau84084a32011-07-22 14:54:00 -07004003 if (chan->expected_tx_seq != tx_seq) {
4004 /* Frame(s) missing - must discard partial SDU */
4005 kfree_skb(chan->sdu);
4006 chan->sdu = NULL;
4007 chan->sdu_last_frag = NULL;
4008 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004009
Mat Martineau84084a32011-07-22 14:54:00 -07004010 /* TODO: Notify userland of missing data */
4011 }
4012
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004013 chan->expected_tx_seq = __next_seq(chan, tx_seq);
Mat Martineau84084a32011-07-22 14:54:00 -07004014
4015 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
4016 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004017
4018 goto done;
4019
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004020 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004021 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004022 break;
4023 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024
4025drop:
4026 kfree_skb(skb);
4027
4028done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004029 if (sk)
4030 bh_unlock_sock(sk);
4031
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032 return 0;
4033}
4034
Al Viro8e036fc2007-07-29 00:16:36 -07004035static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004037 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004038 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004040 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
4041 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042 goto drop;
4043
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004044 sk = chan->sk;
4045
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00004046 bh_lock_sock(sk);
4047
Linus Torvalds1da177e2005-04-16 15:20:36 -07004048 BT_DBG("sk %p, len %d", sk, skb->len);
4049
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004050 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051 goto drop;
4052
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004053 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054 goto drop;
4055
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004056 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057 goto done;
4058
4059drop:
4060 kfree_skb(skb);
4061
4062done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004063 if (sk)
4064 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065 return 0;
4066}
4067
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004068static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
4069{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004070 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004071 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004072
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004073 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
4074 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004075 goto drop;
4076
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004077 sk = chan->sk;
4078
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004079 bh_lock_sock(sk);
4080
4081 BT_DBG("sk %p, len %d", sk, skb->len);
4082
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004083 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004084 goto drop;
4085
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004086 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004087 goto drop;
4088
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004089 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004090 goto done;
4091
4092drop:
4093 kfree_skb(skb);
4094
4095done:
4096 if (sk)
4097 bh_unlock_sock(sk);
4098 return 0;
4099}
4100
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4102{
4103 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004104 u16 cid, len;
4105 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106
4107 skb_pull(skb, L2CAP_HDR_SIZE);
4108 cid = __le16_to_cpu(lh->cid);
4109 len = __le16_to_cpu(lh->len);
4110
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004111 if (len != skb->len) {
4112 kfree_skb(skb);
4113 return;
4114 }
4115
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4117
4118 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004119 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004120 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004121 l2cap_sig_channel(conn, skb);
4122 break;
4123
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004124 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004125 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126 skb_pull(skb, 2);
4127 l2cap_conless_channel(conn, psm, skb);
4128 break;
4129
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004130 case L2CAP_CID_LE_DATA:
4131 l2cap_att_channel(conn, cid, skb);
4132 break;
4133
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004134 case L2CAP_CID_SMP:
4135 if (smp_sig_channel(conn, skb))
4136 l2cap_conn_del(conn->hcon, EACCES);
4137 break;
4138
Linus Torvalds1da177e2005-04-16 15:20:36 -07004139 default:
4140 l2cap_data_channel(conn, cid, skb);
4141 break;
4142 }
4143}
4144
4145/* ---- L2CAP interface with lower layer (HCI) ---- */
4146
4147static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4148{
4149 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004150 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151
4152 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004153 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154
4155 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4156
4157 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004158 read_lock(&chan_list_lock);
4159 list_for_each_entry(c, &chan_list, global_l) {
4160 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004161
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004162 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004163 continue;
4164
4165 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004166 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004167 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004168 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004170 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4171 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004172 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004173 lm2 |= HCI_LM_MASTER;
4174 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004176 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177
4178 return exact ? lm1 : lm2;
4179}
4180
4181static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4182{
Marcel Holtmann01394182006-07-03 10:02:46 +02004183 struct l2cap_conn *conn;
4184
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4186
Ville Tervoacd7d372011-02-10 22:38:49 -03004187 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004188 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189
4190 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191 conn = l2cap_conn_add(hcon, status);
4192 if (conn)
4193 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004194 } else
Joe Perchese1750722011-06-29 18:18:29 -07004195 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004196
4197 return 0;
4198}
4199
Marcel Holtmann2950f212009-02-12 14:02:50 +01004200static int l2cap_disconn_ind(struct hci_conn *hcon)
4201{
4202 struct l2cap_conn *conn = hcon->l2cap_data;
4203
4204 BT_DBG("hcon %p", hcon);
4205
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03004206 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004207 return 0x13;
4208
4209 return conn->disc_reason;
4210}
4211
4212static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213{
4214 BT_DBG("hcon %p reason %d", hcon, reason);
4215
Ville Tervoacd7d372011-02-10 22:38:49 -03004216 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004217 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004218
Joe Perchese1750722011-06-29 18:18:29 -07004219 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004220
Linus Torvalds1da177e2005-04-16 15:20:36 -07004221 return 0;
4222}
4223
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004224static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004225{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004226 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004227 return;
4228
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004229 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004230 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004231 __clear_chan_timer(chan);
4232 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004233 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004234 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004235 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004236 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004237 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004238 }
4239}
4240
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004241static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004243 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004244 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245
Marcel Holtmann01394182006-07-03 10:02:46 +02004246 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004248
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249 BT_DBG("conn %p", conn);
4250
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004251 if (hcon->type == LE_LINK) {
4252 smp_distribute_keys(conn, 0);
4253 del_timer(&conn->security_timer);
4254 }
4255
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004256 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004258 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004259 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004260
Linus Torvalds1da177e2005-04-16 15:20:36 -07004261 bh_lock_sock(sk);
4262
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004263 BT_DBG("chan->scid %d", chan->scid);
4264
4265 if (chan->scid == L2CAP_CID_LE_DATA) {
4266 if (!status && encrypt) {
4267 chan->sec_level = hcon->sec_level;
4268 l2cap_chan_ready(sk);
4269 }
4270
4271 bh_unlock_sock(sk);
4272 continue;
4273 }
4274
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004275 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004276 bh_unlock_sock(sk);
4277 continue;
4278 }
4279
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004280 if (!status && (chan->state == BT_CONNECTED ||
4281 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004282 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004283 bh_unlock_sock(sk);
4284 continue;
4285 }
4286
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004287 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004288 if (!status) {
4289 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004290 req.scid = cpu_to_le16(chan->scid);
4291 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004292
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004293 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004294 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004295
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004296 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004297 L2CAP_CONN_REQ, sizeof(req), &req);
4298 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004299 __clear_chan_timer(chan);
4300 __set_chan_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004301 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004302 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004303 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004304 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004305
4306 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004307 if (bt_sk(sk)->defer_setup) {
4308 struct sock *parent = bt_sk(sk)->parent;
4309 res = L2CAP_CR_PEND;
4310 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004311 if (parent)
4312 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004313 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004314 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004315 res = L2CAP_CR_SUCCESS;
4316 stat = L2CAP_CS_NO_INFO;
4317 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004318 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004319 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004320 __set_chan_timer(chan, HZ / 10);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004321 res = L2CAP_CR_SEC_BLOCK;
4322 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004323 }
4324
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004325 rsp.scid = cpu_to_le16(chan->dcid);
4326 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004327 rsp.result = cpu_to_le16(res);
4328 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004329 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4330 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004331 }
4332
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333 bh_unlock_sock(sk);
4334 }
4335
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004336 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004337
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338 return 0;
4339}
4340
4341static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4342{
4343 struct l2cap_conn *conn = hcon->l2cap_data;
4344
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004345 if (!conn)
4346 conn = l2cap_conn_add(hcon, 0);
4347
4348 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349 goto drop;
4350
4351 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4352
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004353 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004355 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004356 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357 int len;
4358
4359 if (conn->rx_len) {
4360 BT_ERR("Unexpected start frame (len %d)", skb->len);
4361 kfree_skb(conn->rx_skb);
4362 conn->rx_skb = NULL;
4363 conn->rx_len = 0;
4364 l2cap_conn_unreliable(conn, ECOMM);
4365 }
4366
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004367 /* Start fragment always begin with Basic L2CAP header */
4368 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369 BT_ERR("Frame is too short (len %d)", skb->len);
4370 l2cap_conn_unreliable(conn, ECOMM);
4371 goto drop;
4372 }
4373
4374 hdr = (struct l2cap_hdr *) skb->data;
4375 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004376 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377
4378 if (len == skb->len) {
4379 /* Complete frame received */
4380 l2cap_recv_frame(conn, skb);
4381 return 0;
4382 }
4383
4384 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4385
4386 if (skb->len > len) {
4387 BT_ERR("Frame is too long (len %d, expected len %d)",
4388 skb->len, len);
4389 l2cap_conn_unreliable(conn, ECOMM);
4390 goto drop;
4391 }
4392
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004393 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004394
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004395 if (chan && chan->sk) {
4396 struct sock *sk = chan->sk;
4397
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004398 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004399 BT_ERR("Frame exceeding recv MTU (len %d, "
4400 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004401 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004402 bh_unlock_sock(sk);
4403 l2cap_conn_unreliable(conn, ECOMM);
4404 goto drop;
4405 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004406 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004407 }
4408
Linus Torvalds1da177e2005-04-16 15:20:36 -07004409 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004410 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4411 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412 goto drop;
4413
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004414 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004415 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004416 conn->rx_len = len - skb->len;
4417 } else {
4418 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4419
4420 if (!conn->rx_len) {
4421 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4422 l2cap_conn_unreliable(conn, ECOMM);
4423 goto drop;
4424 }
4425
4426 if (skb->len > conn->rx_len) {
4427 BT_ERR("Fragment is too long (len %d, expected %d)",
4428 skb->len, conn->rx_len);
4429 kfree_skb(conn->rx_skb);
4430 conn->rx_skb = NULL;
4431 conn->rx_len = 0;
4432 l2cap_conn_unreliable(conn, ECOMM);
4433 goto drop;
4434 }
4435
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004436 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004437 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438 conn->rx_len -= skb->len;
4439
4440 if (!conn->rx_len) {
4441 /* Complete frame received */
4442 l2cap_recv_frame(conn, conn->rx_skb);
4443 conn->rx_skb = NULL;
4444 }
4445 }
4446
4447drop:
4448 kfree_skb(skb);
4449 return 0;
4450}
4451
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004452static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004454 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004455
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004456 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004457
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004458 list_for_each_entry(c, &chan_list, global_l) {
4459 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004460
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004461 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 +01004462 batostr(&bt_sk(sk)->src),
4463 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004464 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004465 c->scid, c->dcid, c->imtu, c->omtu,
4466 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004467}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004468
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004469 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004470
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004471 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004472}
4473
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004474static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4475{
4476 return single_open(file, l2cap_debugfs_show, inode->i_private);
4477}
4478
4479static const struct file_operations l2cap_debugfs_fops = {
4480 .open = l2cap_debugfs_open,
4481 .read = seq_read,
4482 .llseek = seq_lseek,
4483 .release = single_release,
4484};
4485
4486static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004487
Linus Torvalds1da177e2005-04-16 15:20:36 -07004488static struct hci_proto l2cap_hci_proto = {
4489 .name = "L2CAP",
4490 .id = HCI_PROTO_L2CAP,
4491 .connect_ind = l2cap_connect_ind,
4492 .connect_cfm = l2cap_connect_cfm,
4493 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004494 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004495 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004496 .recv_acldata = l2cap_recv_acldata
4497};
4498
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004499int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004500{
4501 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004502
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004503 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004504 if (err < 0)
4505 return err;
4506
Linus Torvalds1da177e2005-04-16 15:20:36 -07004507 err = hci_register_proto(&l2cap_hci_proto);
4508 if (err < 0) {
4509 BT_ERR("L2CAP protocol registration failed");
4510 bt_sock_unregister(BTPROTO_L2CAP);
4511 goto error;
4512 }
4513
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004514 if (bt_debugfs) {
4515 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4516 bt_debugfs, NULL, &l2cap_debugfs_fops);
4517 if (!l2cap_debugfs)
4518 BT_ERR("Failed to create L2CAP debug file");
4519 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004520
Linus Torvalds1da177e2005-04-16 15:20:36 -07004521 return 0;
4522
4523error:
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004524 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004525 return err;
4526}
4527
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004528void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004529{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004530 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004531
Linus Torvalds1da177e2005-04-16 15:20:36 -07004532 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4533 BT_ERR("L2CAP protocol unregistration failed");
4534
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004535 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004536}
4537
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004538module_param(disable_ertm, bool, 0644);
4539MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03004540
4541module_param(enable_hs, bool, 0644);
4542MODULE_PARM_DESC(enable_hs, "Enable High Speed");