blob: 8efac7884ffb275b22d9cbf2a7a8b6154ec07baa [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.
Gustavo F. Padovan590051d2011-12-18 13:39:33 -02006 Copyright (C) 2011 ProFUSION Embedded Systems
Linus Torvalds1da177e2005-04-16 15:20:36 -07007
8 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License version 2 as
12 published by the Free Software Foundation;
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
17 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090018 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090023 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
24 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070025 SOFTWARE IS DISCLAIMED.
26*/
27
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020028/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070029
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/module.h>
31
32#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080033#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/errno.h>
35#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/sched.h>
37#include <linux/slab.h>
38#include <linux/poll.h>
39#include <linux/fcntl.h>
40#include <linux/init.h>
41#include <linux/interrupt.h>
42#include <linux/socket.h>
43#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080045#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010046#include <linux/debugfs.h>
47#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030048#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030049#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#include <net/sock.h>
51
52#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070053#include <asm/unaligned.h>
54
55#include <net/bluetooth/bluetooth.h>
56#include <net/bluetooth/hci_core.h>
57#include <net/bluetooth/l2cap.h>
Anderson Brigliab501d6a2011-06-07 18:46:31 -030058#include <net/bluetooth/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
Rusty Russelleb939922011-12-19 14:08:01 +000060bool disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020061
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070062static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Mat Martineau50a147c2011-11-02 16:18:34 -070063static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Johannes Bergb5ad8b72011-06-01 08:54:45 +020065static LIST_HEAD(chan_list);
66static DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Linus Torvalds1da177e2005-04-16 15:20:36 -070068static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
69 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030070static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
71 void *data);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -030072static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030073static void l2cap_send_disconn_req(struct l2cap_conn *conn,
74 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
Marcel Holtmann01394182006-07-03 10:02:46 +020076/* ---- L2CAP channels ---- */
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -030077
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030078static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020079{
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -020080 struct l2cap_chan *c, *r = NULL;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030081
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -020082 rcu_read_lock();
83
84 list_for_each_entry_rcu(c, &conn->chan_l, list) {
85 if (c->dcid == cid) {
86 r = c;
87 break;
88 }
Marcel Holtmann01394182006-07-03 10:02:46 +020089 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -020090
91 rcu_read_unlock();
92 return r;
Marcel Holtmann01394182006-07-03 10:02:46 +020093}
94
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030095static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020096{
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -020097 struct l2cap_chan *c, *r = NULL;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030098
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -020099 rcu_read_lock();
100
101 list_for_each_entry_rcu(c, &conn->chan_l, list) {
102 if (c->scid == cid) {
103 r = c;
104 break;
105 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200106 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200107
108 rcu_read_unlock();
109 return r;
Marcel Holtmann01394182006-07-03 10:02:46 +0200110}
111
112/* Find channel with given SCID.
113 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300114static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200115{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300116 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300117
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300118 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300119 if (c)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300120 lock_sock(c->sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300121 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200122}
123
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300124static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200125{
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200126 struct l2cap_chan *c, *r = NULL;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300127
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200128 rcu_read_lock();
129
130 list_for_each_entry_rcu(c, &conn->chan_l, list) {
131 if (c->ident == ident) {
132 r = c;
133 break;
134 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200135 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200136
137 rcu_read_unlock();
138 return r;
Marcel Holtmann01394182006-07-03 10:02:46 +0200139}
140
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300141static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200142{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300143 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300144
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300145 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300146 if (c)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300147 lock_sock(c->sk);
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))
Szymon Janc250938c2011-11-16 09:32:22 +0100157 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300158 }
Szymon Janc250938c2011-11-16 09:32:22 +0100159 return NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300160}
161
162int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
163{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300164 int err;
165
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200166 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300167
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300168 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300169 err = -EADDRINUSE;
170 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300171 }
172
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300173 if (psm) {
174 chan->psm = psm;
175 chan->sport = psm;
176 err = 0;
177 } else {
178 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300179
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300180 err = -EINVAL;
181 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300182 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300183 chan->psm = cpu_to_le16(p);
184 chan->sport = cpu_to_le16(p);
185 err = 0;
186 break;
187 }
188 }
189
190done:
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200191 write_unlock(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300192 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300193}
194
195int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
196{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200197 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300198
199 chan->scid = scid;
200
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200201 write_unlock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300202
203 return 0;
204}
205
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300206static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200207{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300208 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200209
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300210 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300211 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200212 return cid;
213 }
214
215 return 0;
216}
217
Gustavo F. Padovanbadaaa02011-11-23 20:11:46 -0200218static char *state_to_string(int state)
219{
220 switch(state) {
221 case BT_CONNECTED:
222 return "BT_CONNECTED";
223 case BT_OPEN:
224 return "BT_OPEN";
225 case BT_BOUND:
226 return "BT_BOUND";
227 case BT_LISTEN:
228 return "BT_LISTEN";
229 case BT_CONNECT:
230 return "BT_CONNECT";
231 case BT_CONNECT2:
232 return "BT_CONNECT2";
233 case BT_CONFIG:
234 return "BT_CONFIG";
235 case BT_DISCONN:
236 return "BT_DISCONN";
237 case BT_CLOSED:
238 return "BT_CLOSED";
239 }
240
241 return "invalid state";
242}
243
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300244static void l2cap_state_change(struct l2cap_chan *chan, int state)
245{
Gustavo F. Padovanbadaaa02011-11-23 20:11:46 -0200246 BT_DBG("%p %s -> %s", chan, state_to_string(chan->state),
247 state_to_string(state));
248
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300249 chan->state = state;
250 chan->ops->state_change(chan->data, state);
251}
252
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300253static void l2cap_chan_timeout(struct work_struct *work)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300254{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300255 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
256 chan_timer.work);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300257 struct sock *sk = chan->sk;
258 int reason;
259
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300260 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300261
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300262 lock_sock(sk);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300263
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300264 if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300265 reason = ECONNREFUSED;
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300266 else if (chan->state == BT_CONNECT &&
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300267 chan->sec_level != BT_SECURITY_SDP)
268 reason = ECONNREFUSED;
269 else
270 reason = ETIMEDOUT;
271
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300272 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300273
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300274 release_sock(sk);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300275
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300276 chan->ops->close(chan->data);
Ulisses Furquim371fd832011-12-21 20:02:36 -0200277 l2cap_chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300278}
279
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300280struct l2cap_chan *l2cap_chan_create(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200281{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300282 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200283
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300284 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
285 if (!chan)
286 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200287
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300288 chan->sk = sk;
289
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200290 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300291 list_add(&chan->global_l, &chan_list);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200292 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300293
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300294 INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300295
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300296 chan->state = BT_OPEN;
297
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300298 atomic_set(&chan->refcnt, 1);
299
Szymon Jancabc545b2011-11-03 16:05:44 +0100300 BT_DBG("sk %p chan %p", sk, chan);
301
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300302 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200303}
304
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300305void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300306{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200307 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300308 list_del(&chan->global_l);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200309 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300310
Ulisses Furquim371fd832011-12-21 20:02:36 -0200311 l2cap_chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300312}
313
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200314static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200315{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300316 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300317 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200318
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +0200319 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +0100320
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300321 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200322
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200323 switch (chan->chan_type) {
324 case L2CAP_CHAN_CONN_ORIENTED:
Ville Tervob62f3282011-02-10 22:38:50 -0300325 if (conn->hcon->type == LE_LINK) {
326 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300327 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300328 chan->scid = L2CAP_CID_LE_DATA;
329 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300330 } else {
331 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300332 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300333 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300334 }
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200335 break;
336
337 case L2CAP_CHAN_CONN_LESS:
Marcel Holtmann01394182006-07-03 10:02:46 +0200338 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300339 chan->scid = L2CAP_CID_CONN_LESS;
340 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300341 chan->omtu = L2CAP_DEFAULT_MTU;
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200342 break;
343
344 default:
Marcel Holtmann01394182006-07-03 10:02:46 +0200345 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300346 chan->scid = L2CAP_CID_SIGNALING;
347 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300348 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200349 }
350
Andrei Emeltchenko8f7975b2011-10-13 16:18:54 +0300351 chan->local_id = L2CAP_BESTEFFORT_ID;
352 chan->local_stype = L2CAP_SERV_BESTEFFORT;
353 chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
354 chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
355 chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
356 chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
357
Ulisses Furquim371fd832011-12-21 20:02:36 -0200358 l2cap_chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300359
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200360 list_add_rcu(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200361}
362
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900363/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200364 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300365static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200366{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300367 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300368 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200369 struct sock *parent = bt_sk(sk)->parent;
370
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300371 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200372
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300373 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200374
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900375 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300376 /* Delete from channel list */
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200377 list_del_rcu(&chan->list);
378 synchronize_rcu();
379
Ulisses Furquim371fd832011-12-21 20:02:36 -0200380 l2cap_chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300381
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300382 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200383 hci_conn_put(conn->hcon);
384 }
385
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300386 l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200387 sock_set_flag(sk, SOCK_ZAPPED);
388
389 if (err)
390 sk->sk_err = err;
391
392 if (parent) {
393 bt_accept_unlink(sk);
394 parent->sk_data_ready(parent, 0);
395 } else
396 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300397
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300398 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
399 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300400 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300401
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300402 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300403
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300404 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300405 struct srej_list *l, *tmp;
406
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300407 __clear_retrans_timer(chan);
408 __clear_monitor_timer(chan);
409 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300410
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300411 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300412
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300413 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300414 list_del(&l->list);
415 kfree(l);
416 }
417 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200418}
419
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300420static void l2cap_chan_cleanup_listen(struct sock *parent)
421{
422 struct sock *sk;
423
424 BT_DBG("parent %p", parent);
425
426 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300427 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300428 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300429 __clear_chan_timer(chan);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300430 lock_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300431 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300432 release_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300433 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300434 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300435}
436
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300437void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300438{
439 struct l2cap_conn *conn = chan->conn;
440 struct sock *sk = chan->sk;
441
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300442 BT_DBG("chan %p state %d socket %p", chan, chan->state, sk->sk_socket);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300443
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300444 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300445 case BT_LISTEN:
446 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300447
448 l2cap_state_change(chan, BT_CLOSED);
449 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300450 break;
451
452 case BT_CONNECTED:
453 case BT_CONFIG:
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) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300456 __clear_chan_timer(chan);
457 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300458 l2cap_send_disconn_req(conn, chan, reason);
459 } else
460 l2cap_chan_del(chan, reason);
461 break;
462
463 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300464 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300465 conn->hcon->type == ACL_LINK) {
466 struct l2cap_conn_rsp rsp;
467 __u16 result;
468
469 if (bt_sk(sk)->defer_setup)
470 result = L2CAP_CR_SEC_BLOCK;
471 else
472 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300473 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300474
475 rsp.scid = cpu_to_le16(chan->dcid);
476 rsp.dcid = cpu_to_le16(chan->scid);
477 rsp.result = cpu_to_le16(result);
478 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
479 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
480 sizeof(rsp), &rsp);
481 }
482
483 l2cap_chan_del(chan, reason);
484 break;
485
486 case BT_CONNECT:
487 case BT_DISCONN:
488 l2cap_chan_del(chan, reason);
489 break;
490
491 default:
492 sock_set_flag(sk, SOCK_ZAPPED);
493 break;
494 }
495}
496
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300497static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530498{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300499 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300500 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530501 case BT_SECURITY_HIGH:
502 return HCI_AT_DEDICATED_BONDING_MITM;
503 case BT_SECURITY_MEDIUM:
504 return HCI_AT_DEDICATED_BONDING;
505 default:
506 return HCI_AT_NO_BONDING;
507 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300508 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300509 if (chan->sec_level == BT_SECURITY_LOW)
510 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530511
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300512 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530513 return HCI_AT_NO_BONDING_MITM;
514 else
515 return HCI_AT_NO_BONDING;
516 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300517 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530518 case BT_SECURITY_HIGH:
519 return HCI_AT_GENERAL_BONDING_MITM;
520 case BT_SECURITY_MEDIUM:
521 return HCI_AT_GENERAL_BONDING;
522 default:
523 return HCI_AT_NO_BONDING;
524 }
525 }
526}
527
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200528/* Service level security */
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200529int l2cap_chan_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200530{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300531 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100532 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200533
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300534 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100535
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300536 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200537}
538
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200539static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200540{
541 u8 id;
542
543 /* Get next available identificator.
544 * 1 - 128 are used by kernel.
545 * 129 - 199 are reserved.
546 * 200 - 254 are used by utilities like l2ping, etc.
547 */
548
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200549 spin_lock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200550
551 if (++conn->tx_ident > 128)
552 conn->tx_ident = 1;
553
554 id = conn->tx_ident;
555
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200556 spin_unlock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200557
558 return id;
559}
560
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300561static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200562{
563 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200564 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200565
566 BT_DBG("code 0x%2.2x", code);
567
568 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300569 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200570
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200571 if (lmp_no_flush_capable(conn->hcon->hdev))
572 flags = ACL_START_NO_FLUSH;
573 else
574 flags = ACL_START;
575
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700576 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +0200577 skb->priority = HCI_PRIO_MAX;
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700578
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200579 hci_send_acl(conn->hchan, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200580}
581
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200582static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
583{
584 struct hci_conn *hcon = chan->conn->hcon;
585 u16 flags;
586
587 BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
588 skb->priority);
589
590 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
591 lmp_no_flush_capable(hcon->hdev))
592 flags = ACL_START_NO_FLUSH;
593 else
594 flags = ACL_START;
595
596 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
597 hci_send_acl(chan->conn->hchan, skb, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598}
599
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300600static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300601{
602 struct sk_buff *skb;
603 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300604 struct l2cap_conn *conn = chan->conn;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300605 int count, hlen;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300606
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300607 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300608 return;
609
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300610 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
611 hlen = L2CAP_EXT_HDR_SIZE;
612 else
613 hlen = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300614
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300615 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300616 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300617
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300618 BT_DBG("chan %p, control 0x%8.8x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300619
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300620 count = min_t(unsigned int, conn->mtu, hlen);
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +0300621
622 control |= __set_sframe(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300623
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300624 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +0300625 control |= __set_ctrl_final(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300626
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300627 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +0300628 control |= __set_ctrl_poll(chan);
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300629
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300630 skb = bt_skb_alloc(count, GFP_ATOMIC);
631 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300632 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300633
634 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300635 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300636 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300637
638 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300639
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300640 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300641 u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
642 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300643 }
644
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200645 skb->priority = HCI_PRIO_MAX;
646 l2cap_do_send(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300647}
648
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300649static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300650{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300651 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300652 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300653 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300654 } else
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300655 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300656
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300657 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300658
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300659 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300660}
661
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300662static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300663{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300664 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300665}
666
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300667static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200668{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300669 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200670
671 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100672 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
673 return;
674
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200675 if (l2cap_chan_check_security(chan) &&
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300676 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200677 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300678 req.scid = cpu_to_le16(chan->scid);
679 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200680
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300681 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300682 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200683
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300684 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
685 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200686 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200687 } else {
688 struct l2cap_info_req req;
689 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
690
691 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
692 conn->info_ident = l2cap_get_ident(conn);
693
Gustavo F. Padovan030013d2011-12-20 10:57:28 -0200694 schedule_delayed_work(&conn->info_timer,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200695 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
696
697 l2cap_send_cmd(conn, conn->info_ident,
698 L2CAP_INFO_REQ, sizeof(req), &req);
699 }
700}
701
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300702static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
703{
704 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300705 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300706 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
707
708 switch (mode) {
709 case L2CAP_MODE_ERTM:
710 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
711 case L2CAP_MODE_STREAMING:
712 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
713 default:
714 return 0x00;
715 }
716}
717
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300718static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300719{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300720 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300721 struct l2cap_disconn_req req;
722
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300723 if (!conn)
724 return;
725
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300726 sk = chan->sk;
727
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300728 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300729 __clear_retrans_timer(chan);
730 __clear_monitor_timer(chan);
731 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300732 }
733
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300734 req.dcid = cpu_to_le16(chan->dcid);
735 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300736 l2cap_send_cmd(conn, l2cap_get_ident(conn),
737 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300738
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300739 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300740 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300741}
742
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200744static void l2cap_conn_start(struct l2cap_conn *conn)
745{
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200746 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200747
748 BT_DBG("conn %p", conn);
749
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200750 rcu_read_lock();
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200751
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200752 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300753 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300754
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200755 bh_lock_sock(sk);
756
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300757 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200758 bh_unlock_sock(sk);
759 continue;
760 }
761
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300762 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300763 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300764
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200765 if (!l2cap_chan_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300766 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300767 bh_unlock_sock(sk);
768 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200769 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300770
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300771 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
772 && test_bit(CONF_STATE2_DEVICE,
773 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300774 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300775 * so release the lock */
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300776 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300777 bh_unlock_sock(sk);
778 continue;
779 }
780
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300781 req.scid = cpu_to_le16(chan->scid);
782 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300783
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300784 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300785 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300786
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300787 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
788 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300789
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300790 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200791 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300792 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300793 rsp.scid = cpu_to_le16(chan->dcid);
794 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200795
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200796 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100797 if (bt_sk(sk)->defer_setup) {
798 struct sock *parent = bt_sk(sk)->parent;
799 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
800 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +0000801 if (parent)
802 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100803
804 } else {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300805 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100806 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
807 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
808 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200809 } else {
810 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
811 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
812 }
813
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300814 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
815 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300816
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300817 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300818 rsp.result != L2CAP_CR_SUCCESS) {
819 bh_unlock_sock(sk);
820 continue;
821 }
822
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300823 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300824 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300825 l2cap_build_conf_req(chan, buf), buf);
826 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200827 }
828
829 bh_unlock_sock(sk);
830 }
831
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200832 rcu_read_unlock();
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200833}
834
Ville Tervob62f3282011-02-10 22:38:50 -0300835/* Find socket with cid and source bdaddr.
836 * Returns closest match, locked.
837 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300838static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300839{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300840 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300841
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300842 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300843
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300844 list_for_each_entry(c, &chan_list, global_l) {
845 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300846
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300847 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300848 continue;
849
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300850 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300851 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300852 if (!bacmp(&bt_sk(sk)->src, src)) {
853 read_unlock(&chan_list_lock);
854 return c;
855 }
Ville Tervob62f3282011-02-10 22:38:50 -0300856
857 /* Closest match */
858 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300859 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300860 }
861 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300862
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300863 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300864
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300865 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300866}
867
868static void l2cap_le_conn_ready(struct l2cap_conn *conn)
869{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300870 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300871 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300872
873 BT_DBG("");
874
875 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300876 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300877 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300878 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300879 return;
880
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300881 parent = pchan->sk;
882
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300883 lock_sock(parent);
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300884
Ville Tervob62f3282011-02-10 22:38:50 -0300885 /* Check for backlog size */
886 if (sk_acceptq_is_full(parent)) {
887 BT_DBG("backlog full %d", parent->sk_ack_backlog);
888 goto clean;
889 }
890
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300891 chan = pchan->ops->new_connection(pchan->data);
892 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300893 goto clean;
894
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300895 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300896
Ville Tervob62f3282011-02-10 22:38:50 -0300897 hci_conn_hold(conn->hcon);
898
Ville Tervob62f3282011-02-10 22:38:50 -0300899 bacpy(&bt_sk(sk)->src, conn->src);
900 bacpy(&bt_sk(sk)->dst, conn->dst);
901
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300902 bt_accept_enqueue(parent, sk);
903
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200904 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300905
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300906 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300907
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300908 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300909 parent->sk_data_ready(parent, 0);
910
Ville Tervob62f3282011-02-10 22:38:50 -0300911clean:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300912 release_sock(parent);
Ville Tervob62f3282011-02-10 22:38:50 -0300913}
914
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +0200915static void l2cap_chan_ready(struct l2cap_chan *chan)
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300916{
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +0200917 struct sock *sk = chan->sk;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300918 struct sock *parent = bt_sk(sk)->parent;
919
920 BT_DBG("sk %p, parent %p", sk, parent);
921
922 chan->conf_state = 0;
923 __clear_chan_timer(chan);
924
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300925 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300926 sk->sk_state_change(sk);
927
928 if (parent)
929 parent->sk_data_ready(parent, 0);
930}
931
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200932static void l2cap_conn_ready(struct l2cap_conn *conn)
933{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300934 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200935
936 BT_DBG("conn %p", conn);
937
Ville Tervob62f3282011-02-10 22:38:50 -0300938 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
939 l2cap_le_conn_ready(conn);
940
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -0300941 if (conn->hcon->out && conn->hcon->type == LE_LINK)
942 smp_conn_security(conn, conn->hcon->pending_sec_level);
943
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200944 rcu_read_lock();
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200945
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200946 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300947 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300948
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200949 bh_lock_sock(sk);
950
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300951 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300952 if (smp_conn_security(conn, chan->sec_level))
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +0200953 l2cap_chan_ready(chan);
Ville Tervoacd7d372011-02-10 22:38:49 -0300954
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300955 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300956 __clear_chan_timer(chan);
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300957 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200958 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300959
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300960 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300961 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200962
963 bh_unlock_sock(sk);
964 }
965
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200966 rcu_read_unlock();
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200967}
968
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200969/* Notify sockets that we cannot guaranty reliability anymore */
970static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
971{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300972 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200973
974 BT_DBG("conn %p", conn);
975
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200976 rcu_read_lock();
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200977
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200978 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300979 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300980
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +0300981 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200982 sk->sk_err = err;
983 }
984
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200985 rcu_read_unlock();
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200986}
987
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -0200988static void l2cap_info_timeout(struct work_struct *work)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200989{
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -0200990 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
Gustavo F. Padovan030013d2011-12-20 10:57:28 -0200991 info_timer.work);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200992
Marcel Holtmann984947d2009-02-06 23:35:19 +0100993 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100994 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100995
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200996 l2cap_conn_start(conn);
997}
998
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300999static void l2cap_conn_del(struct hci_conn *hcon, int err)
1000{
1001 struct l2cap_conn *conn = hcon->l2cap_data;
1002 struct l2cap_chan *chan, *l;
1003 struct sock *sk;
1004
1005 if (!conn)
1006 return;
1007
1008 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
1009
1010 kfree_skb(conn->rx_skb);
1011
1012 /* Kill channels */
1013 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
1014 sk = chan->sk;
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001015 lock_sock(sk);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001016 l2cap_chan_del(chan, err);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001017 release_sock(sk);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001018 chan->ops->close(chan->data);
1019 }
1020
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001021 hci_chan_del(conn->hchan);
1022
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001023 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
Ulisses Furquim127074b2012-01-30 18:26:29 -02001024 cancel_delayed_work_sync(&conn->info_timer);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001025
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001026 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
Ulisses Furquim127074b2012-01-30 18:26:29 -02001027 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001028 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001029 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001030
1031 hcon->l2cap_data = NULL;
1032 kfree(conn);
1033}
1034
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001035static void security_timeout(struct work_struct *work)
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001036{
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001037 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1038 security_timer.work);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001039
1040 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1041}
1042
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1044{
Marcel Holtmann01394182006-07-03 10:02:46 +02001045 struct l2cap_conn *conn = hcon->l2cap_data;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001046 struct hci_chan *hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
Marcel Holtmann01394182006-07-03 10:02:46 +02001048 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 return conn;
1050
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001051 hchan = hci_chan_create(hcon);
1052 if (!hchan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001055 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1056 if (!conn) {
1057 hci_chan_del(hchan);
1058 return NULL;
1059 }
1060
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 hcon->l2cap_data = conn;
1062 conn->hcon = hcon;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001063 conn->hchan = hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001065 BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
Marcel Holtmann01394182006-07-03 10:02:46 +02001066
Ville Tervoacd7d372011-02-10 22:38:49 -03001067 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1068 conn->mtu = hcon->hdev->le_mtu;
1069 else
1070 conn->mtu = hcon->hdev->acl_mtu;
1071
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 conn->src = &hcon->hdev->bdaddr;
1073 conn->dst = &hcon->dst;
1074
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001075 conn->feat_mask = 0;
1076
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001078
1079 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001081 if (hcon->type == LE_LINK)
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001082 INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001083 else
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02001084 INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
Dave Young45054dc2009-10-18 20:28:30 +00001085
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001086 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01001087
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 return conn;
1089}
1090
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092
1093/* Find socket with psm and source bdaddr.
1094 * Returns closest match.
1095 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001096static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001098 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001100 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001101
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001102 list_for_each_entry(c, &chan_list, global_l) {
1103 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001104
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03001105 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 continue;
1107
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001108 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001110 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001111 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001112 return c;
1113 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114
1115 /* Closest match */
1116 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001117 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 }
1119 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001121 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001122
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001123 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124}
1125
Johan Hedbergcbe8fed2012-01-08 22:51:16 +02001126int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001128 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 bdaddr_t *src = &bt_sk(sk)->src;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 struct l2cap_conn *conn;
1131 struct hci_conn *hcon;
1132 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001133 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001134 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001136 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001137 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001139 hdev = hci_get_route(dst, src);
1140 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 return -EHOSTUNREACH;
1142
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001143 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001145 lock_sock(sk);
1146
1147 /* PSM must be odd and lsb of upper byte must be 0 */
1148 if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
1149 chan->chan_type != L2CAP_CHAN_RAW) {
1150 err = -EINVAL;
1151 goto done;
1152 }
1153
1154 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
1155 err = -EINVAL;
1156 goto done;
1157 }
1158
1159 switch (chan->mode) {
1160 case L2CAP_MODE_BASIC:
1161 break;
1162 case L2CAP_MODE_ERTM:
1163 case L2CAP_MODE_STREAMING:
1164 if (!disable_ertm)
1165 break;
1166 /* fall through */
1167 default:
1168 err = -ENOTSUPP;
1169 goto done;
1170 }
1171
1172 switch (sk->sk_state) {
1173 case BT_CONNECT:
1174 case BT_CONNECT2:
1175 case BT_CONFIG:
1176 /* Already connecting */
1177 err = 0;
1178 goto done;
1179
1180 case BT_CONNECTED:
1181 /* Already connected */
1182 err = -EISCONN;
1183 goto done;
1184
1185 case BT_OPEN:
1186 case BT_BOUND:
1187 /* Can connect */
1188 break;
1189
1190 default:
1191 err = -EBADFD;
1192 goto done;
1193 }
1194
1195 /* Set destination address and psm */
Gustavo F. Padovan9219b2a2012-01-02 20:08:04 -02001196 bacpy(&bt_sk(sk)->dst, dst);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001197 chan->psm = psm;
1198 chan->dcid = cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001200 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001201
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001202 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001203 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001204 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001205 else
1206 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001207 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001208
Ville Tervo30e76272011-02-22 16:10:53 -03001209 if (IS_ERR(hcon)) {
1210 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001212 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213
1214 conn = l2cap_conn_add(hcon, 0);
1215 if (!conn) {
1216 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001217 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 goto done;
1219 }
1220
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 /* Update source addr of the socket */
1222 bacpy(src, conn->src);
1223
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001224 l2cap_chan_add(conn, chan);
1225
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03001226 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001227 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228
1229 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001230 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001231 __clear_chan_timer(chan);
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001232 if (l2cap_chan_check_security(chan))
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03001233 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001234 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001235 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 }
1237
Ville Tervo30e76272011-02-22 16:10:53 -03001238 err = 0;
1239
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001241 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 hci_dev_put(hdev);
1243 return err;
1244}
1245
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001246int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001247{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001248 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001249 DECLARE_WAITQUEUE(wait, current);
1250 int err = 0;
1251 int timeo = HZ/5;
1252
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001253 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001254 set_current_state(TASK_INTERRUPTIBLE);
1255 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001256 if (!timeo)
1257 timeo = HZ/5;
1258
1259 if (signal_pending(current)) {
1260 err = sock_intr_errno(timeo);
1261 break;
1262 }
1263
1264 release_sock(sk);
1265 timeo = schedule_timeout(timeo);
1266 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001267 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001268
1269 err = sock_error(sk);
1270 if (err)
1271 break;
1272 }
1273 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001274 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001275 return err;
1276}
1277
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001278static void l2cap_monitor_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001279{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001280 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1281 monitor_timer.work);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001282 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001283
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001284 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001285
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001286 lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001287 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001288 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001289 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001290 return;
1291 }
1292
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001293 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001294 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001295
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001296 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001297 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001298}
1299
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001300static void l2cap_retrans_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001301{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001302 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1303 retrans_timer.work);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001304 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001305
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001306 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001307
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001308 lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001309 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001310 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001311
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001312 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001313
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001314 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001315 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001316}
1317
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001318static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001319{
1320 struct sk_buff *skb;
1321
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001322 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001323 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001324 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001325 break;
1326
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001327 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001328 kfree_skb(skb);
1329
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001330 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001331 }
1332
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001333 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001334 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001335}
1336
Szymon Janc67c9e842011-07-28 16:24:33 +02001337static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001338{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001339 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001340 u32 control;
1341 u16 fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001342
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001343 while ((skb = skb_dequeue(&chan->tx_q))) {
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001344 control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001345 control |= __set_txseq(chan, chan->next_tx_seq);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001346 __put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001347
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001348 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001349 fcs = crc16(0, (u8 *)skb->data,
1350 skb->len - L2CAP_FCS_SIZE);
1351 put_unaligned_le16(fcs,
1352 skb->data + skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001353 }
1354
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001355 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001356
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001357 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001358 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001359}
1360
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001361static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001362{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001363 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001364 u16 fcs;
1365 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001366
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001367 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001368 if (!skb)
1369 return;
1370
Szymon Jancd1726b62011-11-16 09:32:20 +01001371 while (bt_cb(skb)->tx_seq != tx_seq) {
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001372 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001373 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001374
Szymon Jancd1726b62011-11-16 09:32:20 +01001375 skb = skb_queue_next(&chan->tx_q, skb);
1376 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001377
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001378 if (chan->remote_max_tx &&
1379 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001380 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001381 return;
1382 }
1383
1384 tx_skb = skb_clone(skb, GFP_ATOMIC);
1385 bt_cb(skb)->retries++;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001386
1387 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001388 control &= __get_sar_mask(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001389
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001390 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001391 control |= __set_ctrl_final(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001392
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001393 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001394 control |= __set_txseq(chan, tx_seq);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001395
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001396 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001397
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001398 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001399 fcs = crc16(0, (u8 *)tx_skb->data,
1400 tx_skb->len - L2CAP_FCS_SIZE);
1401 put_unaligned_le16(fcs,
1402 tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001403 }
1404
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001405 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001406}
1407
Szymon Janc67c9e842011-07-28 16:24:33 +02001408static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001409{
1410 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001411 u16 fcs;
1412 u32 control;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001413 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001414
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03001415 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001416 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001417
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001418 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001419
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001420 if (chan->remote_max_tx &&
1421 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001422 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001423 break;
1424 }
1425
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001426 tx_skb = skb_clone(skb, GFP_ATOMIC);
1427
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001428 bt_cb(skb)->retries++;
1429
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001430 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001431 control &= __get_sar_mask(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001432
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001433 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001434 control |= __set_ctrl_final(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001435
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001436 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001437 control |= __set_txseq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001438
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001439 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001440
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001441 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001442 fcs = crc16(0, (u8 *)skb->data,
1443 tx_skb->len - L2CAP_FCS_SIZE);
1444 put_unaligned_le16(fcs, skb->data +
1445 tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001446 }
1447
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001448 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001449
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001450 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001451
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001452 bt_cb(skb)->tx_seq = chan->next_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001453
1454 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001455
Szymon Janc8ed7a0a2012-02-07 15:43:01 +01001456 if (bt_cb(skb)->retries == 1) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001457 chan->unacked_frames++;
Szymon Janc930fa4ae2012-02-07 15:43:02 +01001458
1459 if (!nsent++)
1460 __clear_ack_timer(chan);
Szymon Janc8ed7a0a2012-02-07 15:43:01 +01001461 }
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301462
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001463 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001464
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001465 if (skb_queue_is_last(&chan->tx_q, skb))
1466 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001467 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001468 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001469 }
1470
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001471 return nsent;
1472}
1473
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001474static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001475{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001476 int ret;
1477
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001478 if (!skb_queue_empty(&chan->tx_q))
1479 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001480
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001481 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001482 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001483 return ret;
1484}
1485
Szymon Jancb17e73b2012-01-11 10:59:47 +01001486static void __l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001487{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001488 u32 control = 0;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001489
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001490 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001491
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001492 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001493 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001494 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001495 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001496 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001497 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001498
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001499 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001500 return;
1501
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001502 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001503 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001504}
1505
Szymon Jancb17e73b2012-01-11 10:59:47 +01001506static void l2cap_send_ack(struct l2cap_chan *chan)
1507{
1508 __clear_ack_timer(chan);
1509 __l2cap_send_ack(chan);
1510}
1511
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001512static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001513{
1514 struct srej_list *tail;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001515 u32 control;
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001516
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001517 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001518 control |= __set_ctrl_final(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001519
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001520 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001521 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001522
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001523 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001524}
1525
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001526static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, struct msghdr *msg, int len, int count, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527{
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001528 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001529 struct sk_buff **frag;
1530 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001532 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001533 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534
1535 sent += count;
1536 len -= count;
1537
1538 /* Continuation fragments (no L2CAP header) */
1539 frag = &skb_shinfo(skb)->frag_list;
1540 while (len) {
1541 count = min_t(unsigned int, conn->mtu, len);
1542
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001543 *frag = chan->ops->alloc_skb(chan, count,
1544 msg->msg_flags & MSG_DONTWAIT, &err);
1545
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001547 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001548 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1549 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001551 (*frag)->priority = skb->priority;
1552
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 sent += count;
1554 len -= count;
1555
1556 frag = &(*frag)->next;
1557 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558
1559 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001560}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001562static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
1563 struct msghdr *msg, size_t len,
1564 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001565{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001566 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001567 struct sk_buff *skb;
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001568 int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001569 struct l2cap_hdr *lh;
1570
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001571 BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001572
1573 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001574
1575 skb = chan->ops->alloc_skb(chan, count + hlen,
1576 msg->msg_flags & MSG_DONTWAIT, &err);
1577
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001578 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001579 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001580
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001581 skb->priority = priority;
1582
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001583 /* Create L2CAP header */
1584 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001585 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001586 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001587 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001588
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001589 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001590 if (unlikely(err < 0)) {
1591 kfree_skb(skb);
1592 return ERR_PTR(err);
1593 }
1594 return skb;
1595}
1596
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001597static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
1598 struct msghdr *msg, size_t len,
1599 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001600{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001601 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001602 struct sk_buff *skb;
1603 int err, count, hlen = L2CAP_HDR_SIZE;
1604 struct l2cap_hdr *lh;
1605
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001606 BT_DBG("chan %p len %d", chan, (int)len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001607
1608 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001609
1610 skb = chan->ops->alloc_skb(chan, count + hlen,
1611 msg->msg_flags & MSG_DONTWAIT, &err);
1612
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001613 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001614 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001615
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001616 skb->priority = priority;
1617
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001618 /* Create L2CAP header */
1619 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001620 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001621 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1622
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001623 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001624 if (unlikely(err < 0)) {
1625 kfree_skb(skb);
1626 return ERR_PTR(err);
1627 }
1628 return skb;
1629}
1630
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001631static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1632 struct msghdr *msg, size_t len,
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001633 u32 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001634{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001635 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001636 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001637 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001638 struct l2cap_hdr *lh;
1639
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001640 BT_DBG("chan %p len %d", chan, (int)len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001641
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001642 if (!conn)
1643 return ERR_PTR(-ENOTCONN);
1644
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001645 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1646 hlen = L2CAP_EXT_HDR_SIZE;
1647 else
1648 hlen = L2CAP_ENH_HDR_SIZE;
1649
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001650 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001651 hlen += L2CAP_SDULEN_SIZE;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001652
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001653 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001654 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001655
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001656 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001657
1658 skb = chan->ops->alloc_skb(chan, count + hlen,
1659 msg->msg_flags & MSG_DONTWAIT, &err);
1660
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001661 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001662 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001663
1664 /* Create L2CAP header */
1665 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001666 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001667 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001668
1669 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
1670
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001671 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001672 put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001673
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001674 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001675 if (unlikely(err < 0)) {
1676 kfree_skb(skb);
1677 return ERR_PTR(err);
1678 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001679
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001680 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001681 put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001682
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001683 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001684 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685}
1686
Szymon Janc67c9e842011-07-28 16:24:33 +02001687static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001688{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001689 struct sk_buff *skb;
1690 struct sk_buff_head sar_queue;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001691 u32 control;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001692 size_t size = 0;
1693
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001694 skb_queue_head_init(&sar_queue);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001695 control = __set_ctrl_sar(chan, L2CAP_SAR_START);
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001696 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001697 if (IS_ERR(skb))
1698 return PTR_ERR(skb);
1699
1700 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001701 len -= chan->remote_mps;
1702 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001703
1704 while (len > 0) {
1705 size_t buflen;
1706
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001707 if (len > chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001708 control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001709 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001710 } else {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001711 control = __set_ctrl_sar(chan, L2CAP_SAR_END);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001712 buflen = len;
1713 }
1714
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001715 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001716 if (IS_ERR(skb)) {
1717 skb_queue_purge(&sar_queue);
1718 return PTR_ERR(skb);
1719 }
1720
1721 __skb_queue_tail(&sar_queue, skb);
1722 len -= buflen;
1723 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001724 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001725 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1726 if (chan->tx_send_head == NULL)
1727 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001728
1729 return size;
1730}
1731
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001732int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
1733 u32 priority)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001734{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001735 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001736 u32 control;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001737 int err;
1738
1739 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001740 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001741 skb = l2cap_create_connless_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001742 if (IS_ERR(skb))
1743 return PTR_ERR(skb);
1744
1745 l2cap_do_send(chan, skb);
1746 return len;
1747 }
1748
1749 switch (chan->mode) {
1750 case L2CAP_MODE_BASIC:
1751 /* Check outgoing MTU */
1752 if (len > chan->omtu)
1753 return -EMSGSIZE;
1754
1755 /* Create a basic PDU */
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001756 skb = l2cap_create_basic_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001757 if (IS_ERR(skb))
1758 return PTR_ERR(skb);
1759
1760 l2cap_do_send(chan, skb);
1761 err = len;
1762 break;
1763
1764 case L2CAP_MODE_ERTM:
1765 case L2CAP_MODE_STREAMING:
1766 /* Entire SDU fits into one PDU */
1767 if (len <= chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001768 control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001769 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1770 0);
1771 if (IS_ERR(skb))
1772 return PTR_ERR(skb);
1773
1774 __skb_queue_tail(&chan->tx_q, skb);
1775
1776 if (chan->tx_send_head == NULL)
1777 chan->tx_send_head = skb;
1778
1779 } else {
1780 /* Segment SDU into multiples PDUs */
1781 err = l2cap_sar_segment_sdu(chan, msg, len);
1782 if (err < 0)
1783 return err;
1784 }
1785
1786 if (chan->mode == L2CAP_MODE_STREAMING) {
1787 l2cap_streaming_send(chan);
1788 err = len;
1789 break;
1790 }
1791
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001792 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1793 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001794 err = len;
1795 break;
1796 }
1797
1798 err = l2cap_ertm_send(chan);
1799 if (err >= 0)
1800 err = len;
1801
1802 break;
1803
1804 default:
1805 BT_DBG("bad state %1.1x", chan->mode);
1806 err = -EBADFD;
1807 }
1808
1809 return err;
1810}
1811
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812/* Copy frame to all raw sockets on that connection */
1813static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1814{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001816 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817
1818 BT_DBG("conn %p", conn);
1819
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001820 rcu_read_lock();
1821
1822 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001823 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001824 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825 continue;
1826
1827 /* Don't send frame to the socket it came from */
1828 if (skb->sk == sk)
1829 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001830 nskb = skb_clone(skb, GFP_ATOMIC);
1831 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 continue;
1833
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001834 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835 kfree_skb(nskb);
1836 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001837
1838 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839}
1840
1841/* ---- L2CAP signalling commands ---- */
1842static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1843 u8 code, u8 ident, u16 dlen, void *data)
1844{
1845 struct sk_buff *skb, **frag;
1846 struct l2cap_cmd_hdr *cmd;
1847 struct l2cap_hdr *lh;
1848 int len, count;
1849
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001850 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1851 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852
1853 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1854 count = min_t(unsigned int, conn->mtu, len);
1855
1856 skb = bt_skb_alloc(count, GFP_ATOMIC);
1857 if (!skb)
1858 return NULL;
1859
1860 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001861 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001862
1863 if (conn->hcon->type == LE_LINK)
1864 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1865 else
1866 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867
1868 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1869 cmd->code = code;
1870 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001871 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872
1873 if (dlen) {
1874 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1875 memcpy(skb_put(skb, count), data, count);
1876 data += count;
1877 }
1878
1879 len -= skb->len;
1880
1881 /* Continuation fragments (no L2CAP header) */
1882 frag = &skb_shinfo(skb)->frag_list;
1883 while (len) {
1884 count = min_t(unsigned int, conn->mtu, len);
1885
1886 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1887 if (!*frag)
1888 goto fail;
1889
1890 memcpy(skb_put(*frag, count), data, count);
1891
1892 len -= count;
1893 data += count;
1894
1895 frag = &(*frag)->next;
1896 }
1897
1898 return skb;
1899
1900fail:
1901 kfree_skb(skb);
1902 return NULL;
1903}
1904
1905static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1906{
1907 struct l2cap_conf_opt *opt = *ptr;
1908 int len;
1909
1910 len = L2CAP_CONF_OPT_SIZE + opt->len;
1911 *ptr += len;
1912
1913 *type = opt->type;
1914 *olen = opt->len;
1915
1916 switch (opt->len) {
1917 case 1:
1918 *val = *((u8 *) opt->val);
1919 break;
1920
1921 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001922 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 break;
1924
1925 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001926 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927 break;
1928
1929 default:
1930 *val = (unsigned long) opt->val;
1931 break;
1932 }
1933
1934 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1935 return len;
1936}
1937
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1939{
1940 struct l2cap_conf_opt *opt = *ptr;
1941
1942 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1943
1944 opt->type = type;
1945 opt->len = len;
1946
1947 switch (len) {
1948 case 1:
1949 *((u8 *) opt->val) = val;
1950 break;
1951
1952 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001953 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954 break;
1955
1956 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001957 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 break;
1959
1960 default:
1961 memcpy(opt->val, (void *) val, len);
1962 break;
1963 }
1964
1965 *ptr += L2CAP_CONF_OPT_SIZE + len;
1966}
1967
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001968static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
1969{
1970 struct l2cap_conf_efs efs;
1971
Szymon Janc1ec918c2011-11-16 09:32:21 +01001972 switch (chan->mode) {
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001973 case L2CAP_MODE_ERTM:
1974 efs.id = chan->local_id;
1975 efs.stype = chan->local_stype;
1976 efs.msdu = cpu_to_le16(chan->local_msdu);
1977 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1978 efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
1979 efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
1980 break;
1981
1982 case L2CAP_MODE_STREAMING:
1983 efs.id = 1;
1984 efs.stype = L2CAP_SERV_BESTEFFORT;
1985 efs.msdu = cpu_to_le16(chan->local_msdu);
1986 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1987 efs.acc_lat = 0;
1988 efs.flush_to = 0;
1989 break;
1990
1991 default:
1992 return;
1993 }
1994
1995 l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
1996 (unsigned long) &efs);
1997}
1998
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001999static void l2cap_ack_timeout(struct work_struct *work)
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002000{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002001 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2002 ack_timer.work);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002003
Gustavo F. Padovan2fb9b3d2011-12-22 16:56:05 -02002004 BT_DBG("chan %p", chan);
2005
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002006 lock_sock(chan->sk);
Szymon Jancb17e73b2012-01-11 10:59:47 +01002007 __l2cap_send_ack(chan);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002008 release_sock(chan->sk);
Szymon Janc09bfb2e2012-01-11 10:59:49 +01002009
2010 l2cap_chan_put(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002011}
2012
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002013static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002014{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002015 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002016 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002017 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002018 chan->num_acked = 0;
2019 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002020
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002021 INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2022 INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2023 INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002024
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002025 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002026
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03002027 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002028}
2029
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002030static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2031{
2032 switch (mode) {
2033 case L2CAP_MODE_STREAMING:
2034 case L2CAP_MODE_ERTM:
2035 if (l2cap_mode_supported(mode, remote_feat_mask))
2036 return mode;
2037 /* fall through */
2038 default:
2039 return L2CAP_MODE_BASIC;
2040 }
2041}
2042
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002043static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
2044{
2045 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
2046}
2047
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002048static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2049{
2050 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2051}
2052
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002053static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
2054{
2055 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002056 __l2cap_ews_supported(chan)) {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002057 /* use extended control field */
2058 set_bit(FLAG_EXT_CTRL, &chan->flags);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002059 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2060 } else {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002061 chan->tx_win = min_t(u16, chan->tx_win,
2062 L2CAP_DEFAULT_TX_WINDOW);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002063 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2064 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002065}
2066
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002067static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002070 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071 void *ptr = req->data;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002072 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002074 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002076 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002077 goto done;
2078
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002079 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002080 case L2CAP_MODE_STREAMING:
2081 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002082 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002083 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002084
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002085 if (__l2cap_efs_supported(chan))
2086 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2087
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002088 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002089 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002090 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002091 break;
2092 }
2093
2094done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002095 if (chan->imtu != L2CAP_DEFAULT_MTU)
2096 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002097
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002098 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002099 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002100 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2101 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002102 break;
2103
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002104 rfc.mode = L2CAP_MODE_BASIC;
2105 rfc.txwin_size = 0;
2106 rfc.max_transmit = 0;
2107 rfc.retrans_timeout = 0;
2108 rfc.monitor_timeout = 0;
2109 rfc.max_pdu_size = 0;
2110
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002111 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2112 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002113 break;
2114
2115 case L2CAP_MODE_ERTM:
2116 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002117 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002118 rfc.retrans_timeout = 0;
2119 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002120
2121 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2122 L2CAP_EXT_HDR_SIZE -
2123 L2CAP_SDULEN_SIZE -
2124 L2CAP_FCS_SIZE);
2125 rfc.max_pdu_size = cpu_to_le16(size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002126
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002127 l2cap_txwin_setup(chan);
2128
2129 rfc.txwin_size = min_t(u16, chan->tx_win,
2130 L2CAP_DEFAULT_TX_WINDOW);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002131
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002132 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2133 (unsigned long) &rfc);
2134
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002135 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2136 l2cap_add_opt_efs(&ptr, chan);
2137
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002138 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002139 break;
2140
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002141 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002142 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002143 chan->fcs = L2CAP_FCS_NONE;
2144 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002145 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002146
2147 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2148 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2149 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002150 break;
2151
2152 case L2CAP_MODE_STREAMING:
2153 rfc.mode = L2CAP_MODE_STREAMING;
2154 rfc.txwin_size = 0;
2155 rfc.max_transmit = 0;
2156 rfc.retrans_timeout = 0;
2157 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002158
2159 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2160 L2CAP_EXT_HDR_SIZE -
2161 L2CAP_SDULEN_SIZE -
2162 L2CAP_FCS_SIZE);
2163 rfc.max_pdu_size = cpu_to_le16(size);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002164
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002165 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2166 (unsigned long) &rfc);
2167
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002168 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2169 l2cap_add_opt_efs(&ptr, chan);
2170
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002171 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002172 break;
2173
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002174 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002175 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002176 chan->fcs = L2CAP_FCS_NONE;
2177 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002178 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002179 break;
2180 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002182 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002183 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184
2185 return ptr - data;
2186}
2187
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002188static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002190 struct l2cap_conf_rsp *rsp = data;
2191 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002192 void *req = chan->conf_req;
2193 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002194 int type, hint, olen;
2195 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002196 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002197 struct l2cap_conf_efs efs;
2198 u8 remote_efs = 0;
Marcel Holtmann861d6882007-10-20 13:37:06 +02002199 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002200 u16 result = L2CAP_CONF_SUCCESS;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002201 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002203 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002204
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002205 while (len >= L2CAP_CONF_OPT_SIZE) {
2206 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002208 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002209 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002210
2211 switch (type) {
2212 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002213 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002214 break;
2215
2216 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002217 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002218 break;
2219
2220 case L2CAP_CONF_QOS:
2221 break;
2222
Marcel Holtmann6464f352007-10-20 13:39:51 +02002223 case L2CAP_CONF_RFC:
2224 if (olen == sizeof(rfc))
2225 memcpy(&rfc, (void *) val, olen);
2226 break;
2227
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002228 case L2CAP_CONF_FCS:
2229 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002230 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002231 break;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002232
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002233 case L2CAP_CONF_EFS:
2234 remote_efs = 1;
2235 if (olen == sizeof(efs))
2236 memcpy(&efs, (void *) val, olen);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002237 break;
2238
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002239 case L2CAP_CONF_EWS:
2240 if (!enable_hs)
2241 return -ECONNREFUSED;
2242
2243 set_bit(FLAG_EXT_CTRL, &chan->flags);
2244 set_bit(CONF_EWS_RECV, &chan->conf_state);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002245 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002246 chan->remote_tx_win = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002247 break;
2248
2249 default:
2250 if (hint)
2251 break;
2252
2253 result = L2CAP_CONF_UNKNOWN;
2254 *((u8 *) ptr++) = type;
2255 break;
2256 }
2257 }
2258
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002259 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002260 goto done;
2261
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002262 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002263 case L2CAP_MODE_STREAMING:
2264 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002265 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002266 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002267 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002268 break;
2269 }
2270
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002271 if (remote_efs) {
2272 if (__l2cap_efs_supported(chan))
2273 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2274 else
2275 return -ECONNREFUSED;
2276 }
2277
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002278 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002279 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002280
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002281 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002282 }
2283
2284done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002285 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002286 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002287 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002288
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002289 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002290 return -ECONNREFUSED;
2291
2292 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2293 sizeof(rfc), (unsigned long) &rfc);
2294 }
2295
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002296 if (result == L2CAP_CONF_SUCCESS) {
2297 /* Configure output options and let the other side know
2298 * which ones we don't like. */
2299
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002300 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2301 result = L2CAP_CONF_UNACCEPT;
2302 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002303 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002304 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002305 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002306 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002307
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002308 if (remote_efs) {
2309 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2310 efs.stype != L2CAP_SERV_NOTRAFIC &&
2311 efs.stype != chan->local_stype) {
2312
2313 result = L2CAP_CONF_UNACCEPT;
2314
2315 if (chan->num_conf_req >= 1)
2316 return -ECONNREFUSED;
2317
2318 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002319 sizeof(efs),
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002320 (unsigned long) &efs);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002321 } else {
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002322 /* Send PENDING Conf Rsp */
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002323 result = L2CAP_CONF_PENDING;
2324 set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002325 }
2326 }
2327
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002328 switch (rfc.mode) {
2329 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002330 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002331 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002332 break;
2333
2334 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002335 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2336 chan->remote_tx_win = rfc.txwin_size;
2337 else
2338 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2339
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002340 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002341
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002342 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2343 chan->conn->mtu -
2344 L2CAP_EXT_HDR_SIZE -
2345 L2CAP_SDULEN_SIZE -
2346 L2CAP_FCS_SIZE);
2347 rfc.max_pdu_size = cpu_to_le16(size);
2348 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002349
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002350 rfc.retrans_timeout =
2351 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2352 rfc.monitor_timeout =
2353 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002354
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002355 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002356
2357 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2358 sizeof(rfc), (unsigned long) &rfc);
2359
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002360 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2361 chan->remote_id = efs.id;
2362 chan->remote_stype = efs.stype;
2363 chan->remote_msdu = le16_to_cpu(efs.msdu);
2364 chan->remote_flush_to =
2365 le32_to_cpu(efs.flush_to);
2366 chan->remote_acc_lat =
2367 le32_to_cpu(efs.acc_lat);
2368 chan->remote_sdu_itime =
2369 le32_to_cpu(efs.sdu_itime);
2370 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2371 sizeof(efs), (unsigned long) &efs);
2372 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002373 break;
2374
2375 case L2CAP_MODE_STREAMING:
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002376 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2377 chan->conn->mtu -
2378 L2CAP_EXT_HDR_SIZE -
2379 L2CAP_SDULEN_SIZE -
2380 L2CAP_FCS_SIZE);
2381 rfc.max_pdu_size = cpu_to_le16(size);
2382 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002383
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002384 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002385
2386 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2387 sizeof(rfc), (unsigned long) &rfc);
2388
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002389 break;
2390
2391 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002392 result = L2CAP_CONF_UNACCEPT;
2393
2394 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002395 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002396 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002397
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002398 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002399 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002400 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002401 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002402 rsp->result = cpu_to_le16(result);
2403 rsp->flags = cpu_to_le16(0x0000);
2404
2405 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406}
2407
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002408static 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 -03002409{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002410 struct l2cap_conf_req *req = data;
2411 void *ptr = req->data;
2412 int type, olen;
2413 unsigned long val;
Mat Martineau36e999a2011-12-08 17:23:21 -08002414 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002415 struct l2cap_conf_efs efs;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002416
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002417 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002418
2419 while (len >= L2CAP_CONF_OPT_SIZE) {
2420 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2421
2422 switch (type) {
2423 case L2CAP_CONF_MTU:
2424 if (val < L2CAP_DEFAULT_MIN_MTU) {
2425 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002426 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002427 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002428 chan->imtu = val;
2429 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002430 break;
2431
2432 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002433 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002434 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002435 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002436 break;
2437
2438 case L2CAP_CONF_RFC:
2439 if (olen == sizeof(rfc))
2440 memcpy(&rfc, (void *)val, olen);
2441
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002442 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002443 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002444 return -ECONNREFUSED;
2445
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002446 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002447
2448 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2449 sizeof(rfc), (unsigned long) &rfc);
2450 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002451
2452 case L2CAP_CONF_EWS:
2453 chan->tx_win = min_t(u16, val,
2454 L2CAP_DEFAULT_EXT_WINDOW);
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002455 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2456 chan->tx_win);
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002457 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002458
2459 case L2CAP_CONF_EFS:
2460 if (olen == sizeof(efs))
2461 memcpy(&efs, (void *)val, olen);
2462
2463 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2464 efs.stype != L2CAP_SERV_NOTRAFIC &&
2465 efs.stype != chan->local_stype)
2466 return -ECONNREFUSED;
2467
2468 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2469 sizeof(efs), (unsigned long) &efs);
2470 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002471 }
2472 }
2473
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002474 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002475 return -ECONNREFUSED;
2476
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002477 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002478
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002479 if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002480 switch (rfc.mode) {
2481 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002482 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2483 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2484 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002485
2486 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2487 chan->local_msdu = le16_to_cpu(efs.msdu);
2488 chan->local_sdu_itime =
2489 le32_to_cpu(efs.sdu_itime);
2490 chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
2491 chan->local_flush_to =
2492 le32_to_cpu(efs.flush_to);
2493 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002494 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002495
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002496 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002497 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002498 }
2499 }
2500
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002501 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002502 req->flags = cpu_to_le16(0x0000);
2503
2504 return ptr - data;
2505}
2506
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002507static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508{
2509 struct l2cap_conf_rsp *rsp = data;
2510 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002512 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002514 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002515 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002516 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517
2518 return ptr - data;
2519}
2520
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002521void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002522{
2523 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002524 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002525 u8 buf[128];
2526
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002527 rsp.scid = cpu_to_le16(chan->dcid);
2528 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002529 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2530 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2531 l2cap_send_cmd(conn, chan->ident,
2532 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2533
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002534 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002535 return;
2536
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002537 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2538 l2cap_build_conf_req(chan, buf), buf);
2539 chan->num_conf_req++;
2540}
2541
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002542static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002543{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002544 int type, olen;
2545 unsigned long val;
2546 struct l2cap_conf_rfc rfc;
2547
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002548 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002549
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002550 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002551 return;
2552
2553 while (len >= L2CAP_CONF_OPT_SIZE) {
2554 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2555
2556 switch (type) {
2557 case L2CAP_CONF_RFC:
2558 if (olen == sizeof(rfc))
2559 memcpy(&rfc, (void *)val, olen);
2560 goto done;
2561 }
2562 }
2563
Mat Martineau36e999a2011-12-08 17:23:21 -08002564 /* Use sane default values in case a misbehaving remote device
2565 * did not send an RFC option.
2566 */
2567 rfc.mode = chan->mode;
2568 rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
2569 rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
2570 rfc.max_pdu_size = cpu_to_le16(chan->imtu);
2571
2572 BT_ERR("Expected RFC option was not found, using defaults");
2573
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002574done:
2575 switch (rfc.mode) {
2576 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002577 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2578 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2579 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002580 break;
2581 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002582 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002583 }
2584}
2585
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002586static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2587{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002588 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002589
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002590 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002591 return 0;
2592
2593 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2594 cmd->ident == conn->info_ident) {
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02002595 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002596
2597 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002598 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002599
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002600 l2cap_conn_start(conn);
2601 }
2602
2603 return 0;
2604}
2605
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2607{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2609 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002610 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002611 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002612 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613
2614 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002615 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616
2617 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2618
2619 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002620 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2621 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 result = L2CAP_CR_BAD_PSM;
2623 goto sendresp;
2624 }
2625
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002626 parent = pchan->sk;
2627
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002628 lock_sock(parent);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002629
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002630 /* Check if the ACL is secure enough (if not SDP) */
2631 if (psm != cpu_to_le16(0x0001) &&
2632 !hci_conn_check_link_mode(conn->hcon)) {
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002633 conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002634 result = L2CAP_CR_SEC_BLOCK;
2635 goto response;
2636 }
2637
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638 result = L2CAP_CR_NO_MEM;
2639
2640 /* Check for backlog size */
2641 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002642 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643 goto response;
2644 }
2645
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002646 chan = pchan->ops->new_connection(pchan->data);
2647 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648 goto response;
2649
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002650 sk = chan->sk;
2651
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002653 if (__l2cap_get_chan_by_dcid(conn, scid)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002655 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 goto response;
2657 }
2658
2659 hci_conn_hold(conn->hcon);
2660
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661 bacpy(&bt_sk(sk)->src, conn->src);
2662 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002663 chan->psm = psm;
2664 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002666 bt_accept_enqueue(parent, sk);
2667
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02002668 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002669
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002670 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002672 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002674 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675
Marcel Holtmann984947d2009-02-06 23:35:19 +01002676 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02002677 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002678 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002679 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002680 result = L2CAP_CR_PEND;
2681 status = L2CAP_CS_AUTHOR_PEND;
2682 parent->sk_data_ready(parent, 0);
2683 } else {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002684 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002685 result = L2CAP_CR_SUCCESS;
2686 status = L2CAP_CS_NO_INFO;
2687 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002688 } else {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002689 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002690 result = L2CAP_CR_PEND;
2691 status = L2CAP_CS_AUTHEN_PEND;
2692 }
2693 } else {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002694 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002695 result = L2CAP_CR_PEND;
2696 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697 }
2698
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699response:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002700 release_sock(parent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701
2702sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002703 rsp.scid = cpu_to_le16(scid);
2704 rsp.dcid = cpu_to_le16(dcid);
2705 rsp.result = cpu_to_le16(result);
2706 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002708
2709 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2710 struct l2cap_info_req info;
2711 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2712
2713 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2714 conn->info_ident = l2cap_get_ident(conn);
2715
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02002716 schedule_delayed_work(&conn->info_timer,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002717 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2718
2719 l2cap_send_cmd(conn, conn->info_ident,
2720 L2CAP_INFO_REQ, sizeof(info), &info);
2721 }
2722
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002723 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002724 result == L2CAP_CR_SUCCESS) {
2725 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002726 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002727 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002728 l2cap_build_conf_req(chan, buf), buf);
2729 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002730 }
2731
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732 return 0;
2733}
2734
2735static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2736{
2737 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2738 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002739 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 struct sock *sk;
2741 u8 req[128];
2742
2743 scid = __le16_to_cpu(rsp->scid);
2744 dcid = __le16_to_cpu(rsp->dcid);
2745 result = __le16_to_cpu(rsp->result);
2746 status = __le16_to_cpu(rsp->status);
2747
2748 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2749
2750 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002751 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002752 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002753 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002755 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002756 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002757 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758 }
2759
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002760 sk = chan->sk;
2761
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 switch (result) {
2763 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002764 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002765 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002766 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002767 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002768
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002769 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002770 break;
2771
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002773 l2cap_build_conf_req(chan, req), req);
2774 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775 break;
2776
2777 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002778 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779 break;
2780
2781 default:
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002782 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783 break;
2784 }
2785
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002786 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787 return 0;
2788}
2789
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002790static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002791{
2792 /* FCS is enabled only in ERTM or streaming mode, if one or both
2793 * sides request it.
2794 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002795 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002796 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002797 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002798 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002799}
2800
Al Viro88219a02007-07-29 00:17:25 -07002801static 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 -07002802{
2803 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2804 u16 dcid, flags;
2805 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002806 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002808 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809
2810 dcid = __le16_to_cpu(req->dcid);
2811 flags = __le16_to_cpu(req->flags);
2812
2813 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2814
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002815 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002816 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817 return -ENOENT;
2818
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002819 sk = chan->sk;
2820
David S. Miller033b1142011-07-21 13:38:42 -07002821 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002822 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002823
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002824 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2825 rej.scid = cpu_to_le16(chan->scid);
2826 rej.dcid = cpu_to_le16(chan->dcid);
2827
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002828 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2829 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002830 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002831 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002832
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002833 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002834 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002835 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002836 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002837 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002838 L2CAP_CONF_REJECT, flags), rsp);
2839 goto unlock;
2840 }
2841
2842 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002843 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2844 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845
2846 if (flags & 0x0001) {
2847 /* Incomplete config. Send empty response. */
2848 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002849 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002850 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851 goto unlock;
2852 }
2853
2854 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002855 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002856 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002857 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002859 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002861 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002862 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002863
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002864 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002865 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002866
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002867 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002868 goto unlock;
2869
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002870 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002871 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002872
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002873 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002874
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002875 chan->next_tx_seq = 0;
2876 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002877 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002878 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002879 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002880
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02002881 l2cap_chan_ready(chan);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002882 goto unlock;
2883 }
2884
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002885 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002886 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002888 l2cap_build_conf_req(chan, buf), buf);
2889 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002890 }
2891
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002892 /* Got Conf Rsp PENDING from remote side and asume we sent
2893 Conf Rsp PENDING in the code above */
2894 if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
2895 test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2896
2897 /* check compatibility */
2898
2899 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2900 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2901
2902 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002903 l2cap_build_conf_rsp(chan, rsp,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002904 L2CAP_CONF_SUCCESS, 0x0000), rsp);
2905 }
2906
Linus Torvalds1da177e2005-04-16 15:20:36 -07002907unlock:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002908 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002909 return 0;
2910}
2911
2912static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2913{
2914 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2915 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002916 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002918 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002919
2920 scid = __le16_to_cpu(rsp->scid);
2921 flags = __le16_to_cpu(rsp->flags);
2922 result = __le16_to_cpu(rsp->result);
2923
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002924 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2925 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002927 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002928 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929 return 0;
2930
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002931 sk = chan->sk;
2932
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933 switch (result) {
2934 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002935 l2cap_conf_rfc_get(chan, rsp->data, len);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002936 clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002937 break;
2938
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002939 case L2CAP_CONF_PENDING:
2940 set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
2941
2942 if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2943 char buf[64];
2944
2945 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2946 buf, &result);
2947 if (len < 0) {
2948 l2cap_send_disconn_req(conn, chan, ECONNRESET);
2949 goto done;
2950 }
2951
2952 /* check compatibility */
2953
2954 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2955 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2956
2957 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002958 l2cap_build_conf_rsp(chan, buf,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002959 L2CAP_CONF_SUCCESS, 0x0000), buf);
2960 }
2961 goto done;
2962
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002964 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002965 char req[64];
2966
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002967 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002968 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002969 goto done;
2970 }
2971
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002972 /* throw out any old stored conf requests */
2973 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002974 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2975 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002976 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002977 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002978 goto done;
2979 }
2980
2981 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2982 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002983 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002984 if (result != L2CAP_CONF_SUCCESS)
2985 goto done;
2986 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987 }
2988
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002989 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002990 sk->sk_err = ECONNRESET;
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01002991 __set_chan_timer(chan,
2992 msecs_to_jiffies(L2CAP_DISC_REJ_TIMEOUT));
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002993 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994 goto done;
2995 }
2996
2997 if (flags & 0x01)
2998 goto done;
2999
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003000 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003002 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003003 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003004
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03003005 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003006 chan->next_tx_seq = 0;
3007 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03003008 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003009 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003010 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003011
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02003012 l2cap_chan_ready(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013 }
3014
3015done:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003016 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017 return 0;
3018}
3019
3020static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3021{
3022 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3023 struct l2cap_disconn_rsp rsp;
3024 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003025 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026 struct sock *sk;
3027
3028 scid = __le16_to_cpu(req->scid);
3029 dcid = __le16_to_cpu(req->dcid);
3030
3031 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3032
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003033 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003034 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035 return 0;
3036
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003037 sk = chan->sk;
3038
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003039 rsp.dcid = cpu_to_le16(chan->scid);
3040 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3042
3043 sk->sk_shutdown = SHUTDOWN_MASK;
3044
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003045 l2cap_chan_del(chan, ECONNRESET);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003046 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003048 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003049 return 0;
3050}
3051
3052static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3053{
3054 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3055 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003056 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057 struct sock *sk;
3058
3059 scid = __le16_to_cpu(rsp->scid);
3060 dcid = __le16_to_cpu(rsp->dcid);
3061
3062 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3063
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003064 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003065 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066 return 0;
3067
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003068 sk = chan->sk;
3069
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003070 l2cap_chan_del(chan, 0);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003071 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003073 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074 return 0;
3075}
3076
3077static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3078{
3079 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080 u16 type;
3081
3082 type = __le16_to_cpu(req->type);
3083
3084 BT_DBG("type 0x%4.4x", type);
3085
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003086 if (type == L2CAP_IT_FEAT_MASK) {
3087 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003088 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003089 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3090 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3091 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003092 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003093 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3094 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003095 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003096 feat_mask |= L2CAP_FEAT_EXT_FLOW
3097 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003098
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003099 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003100 l2cap_send_cmd(conn, cmd->ident,
3101 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003102 } else if (type == L2CAP_IT_FIXED_CHAN) {
3103 u8 buf[12];
3104 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
Mat Martineau50a147c2011-11-02 16:18:34 -07003105
3106 if (enable_hs)
3107 l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
3108 else
3109 l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
3110
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003111 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3112 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003113 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003114 l2cap_send_cmd(conn, cmd->ident,
3115 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003116 } else {
3117 struct l2cap_info_rsp rsp;
3118 rsp.type = cpu_to_le16(type);
3119 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3120 l2cap_send_cmd(conn, cmd->ident,
3121 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3122 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003123
3124 return 0;
3125}
3126
3127static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3128{
3129 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3130 u16 type, result;
3131
3132 type = __le16_to_cpu(rsp->type);
3133 result = __le16_to_cpu(rsp->result);
3134
3135 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3136
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003137 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3138 if (cmd->ident != conn->info_ident ||
3139 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3140 return 0;
3141
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02003142 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003143
Ville Tervoadb08ed2010-08-04 09:43:33 +03003144 if (result != L2CAP_IR_SUCCESS) {
3145 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3146 conn->info_ident = 0;
3147
3148 l2cap_conn_start(conn);
3149
3150 return 0;
3151 }
3152
Marcel Holtmann984947d2009-02-06 23:35:19 +01003153 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003154 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003155
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003156 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003157 struct l2cap_info_req req;
3158 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3159
3160 conn->info_ident = l2cap_get_ident(conn);
3161
3162 l2cap_send_cmd(conn, conn->info_ident,
3163 L2CAP_INFO_REQ, sizeof(req), &req);
3164 } else {
3165 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3166 conn->info_ident = 0;
3167
3168 l2cap_conn_start(conn);
3169 }
3170 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003171 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003172 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003173
3174 l2cap_conn_start(conn);
3175 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003176
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177 return 0;
3178}
3179
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003180static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3181 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3182 void *data)
3183{
3184 struct l2cap_create_chan_req *req = data;
3185 struct l2cap_create_chan_rsp rsp;
3186 u16 psm, scid;
3187
3188 if (cmd_len != sizeof(*req))
3189 return -EPROTO;
3190
3191 if (!enable_hs)
3192 return -EINVAL;
3193
3194 psm = le16_to_cpu(req->psm);
3195 scid = le16_to_cpu(req->scid);
3196
3197 BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3198
3199 /* Placeholder: Always reject */
3200 rsp.dcid = 0;
3201 rsp.scid = cpu_to_le16(scid);
3202 rsp.result = L2CAP_CR_NO_MEM;
3203 rsp.status = L2CAP_CS_NO_INFO;
3204
3205 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3206 sizeof(rsp), &rsp);
3207
3208 return 0;
3209}
3210
3211static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3212 struct l2cap_cmd_hdr *cmd, void *data)
3213{
3214 BT_DBG("conn %p", conn);
3215
3216 return l2cap_connect_rsp(conn, cmd, data);
3217}
3218
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003219static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
3220 u16 icid, u16 result)
3221{
3222 struct l2cap_move_chan_rsp rsp;
3223
3224 BT_DBG("icid %d, result %d", icid, result);
3225
3226 rsp.icid = cpu_to_le16(icid);
3227 rsp.result = cpu_to_le16(result);
3228
3229 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
3230}
3231
3232static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
3233 struct l2cap_chan *chan, u16 icid, u16 result)
3234{
3235 struct l2cap_move_chan_cfm cfm;
3236 u8 ident;
3237
3238 BT_DBG("icid %d, result %d", icid, result);
3239
3240 ident = l2cap_get_ident(conn);
3241 if (chan)
3242 chan->ident = ident;
3243
3244 cfm.icid = cpu_to_le16(icid);
3245 cfm.result = cpu_to_le16(result);
3246
3247 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
3248}
3249
3250static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
3251 u16 icid)
3252{
3253 struct l2cap_move_chan_cfm_rsp rsp;
3254
3255 BT_DBG("icid %d", icid);
3256
3257 rsp.icid = cpu_to_le16(icid);
3258 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
3259}
3260
3261static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
3262 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3263{
3264 struct l2cap_move_chan_req *req = data;
3265 u16 icid = 0;
3266 u16 result = L2CAP_MR_NOT_ALLOWED;
3267
3268 if (cmd_len != sizeof(*req))
3269 return -EPROTO;
3270
3271 icid = le16_to_cpu(req->icid);
3272
3273 BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
3274
3275 if (!enable_hs)
3276 return -EINVAL;
3277
3278 /* Placeholder: Always refuse */
3279 l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
3280
3281 return 0;
3282}
3283
3284static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
3285 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3286{
3287 struct l2cap_move_chan_rsp *rsp = data;
3288 u16 icid, result;
3289
3290 if (cmd_len != sizeof(*rsp))
3291 return -EPROTO;
3292
3293 icid = le16_to_cpu(rsp->icid);
3294 result = le16_to_cpu(rsp->result);
3295
3296 BT_DBG("icid %d, result %d", icid, result);
3297
3298 /* Placeholder: Always unconfirmed */
3299 l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
3300
3301 return 0;
3302}
3303
3304static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
3305 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3306{
3307 struct l2cap_move_chan_cfm *cfm = data;
3308 u16 icid, result;
3309
3310 if (cmd_len != sizeof(*cfm))
3311 return -EPROTO;
3312
3313 icid = le16_to_cpu(cfm->icid);
3314 result = le16_to_cpu(cfm->result);
3315
3316 BT_DBG("icid %d, result %d", icid, result);
3317
3318 l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
3319
3320 return 0;
3321}
3322
3323static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
3324 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3325{
3326 struct l2cap_move_chan_cfm_rsp *rsp = data;
3327 u16 icid;
3328
3329 if (cmd_len != sizeof(*rsp))
3330 return -EPROTO;
3331
3332 icid = le16_to_cpu(rsp->icid);
3333
3334 BT_DBG("icid %d", icid);
3335
3336 return 0;
3337}
3338
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003339static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02003340 u16 to_multiplier)
3341{
3342 u16 max_latency;
3343
3344 if (min > max || min < 6 || max > 3200)
3345 return -EINVAL;
3346
3347 if (to_multiplier < 10 || to_multiplier > 3200)
3348 return -EINVAL;
3349
3350 if (max >= to_multiplier * 8)
3351 return -EINVAL;
3352
3353 max_latency = (to_multiplier * 8 / max) - 1;
3354 if (latency > 499 || latency > max_latency)
3355 return -EINVAL;
3356
3357 return 0;
3358}
3359
3360static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3361 struct l2cap_cmd_hdr *cmd, u8 *data)
3362{
3363 struct hci_conn *hcon = conn->hcon;
3364 struct l2cap_conn_param_update_req *req;
3365 struct l2cap_conn_param_update_rsp rsp;
3366 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003367 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02003368
3369 if (!(hcon->link_mode & HCI_LM_MASTER))
3370 return -EINVAL;
3371
3372 cmd_len = __le16_to_cpu(cmd->len);
3373 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3374 return -EPROTO;
3375
3376 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003377 min = __le16_to_cpu(req->min);
3378 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02003379 latency = __le16_to_cpu(req->latency);
3380 to_multiplier = __le16_to_cpu(req->to_multiplier);
3381
3382 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3383 min, max, latency, to_multiplier);
3384
3385 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003386
3387 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
3388 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02003389 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3390 else
3391 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3392
3393 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3394 sizeof(rsp), &rsp);
3395
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003396 if (!err)
3397 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
3398
Claudio Takahaside731152011-02-11 19:28:55 -02003399 return 0;
3400}
3401
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003402static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
3403 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
3404{
3405 int err = 0;
3406
3407 switch (cmd->code) {
3408 case L2CAP_COMMAND_REJ:
3409 l2cap_command_rej(conn, cmd, data);
3410 break;
3411
3412 case L2CAP_CONN_REQ:
3413 err = l2cap_connect_req(conn, cmd, data);
3414 break;
3415
3416 case L2CAP_CONN_RSP:
3417 err = l2cap_connect_rsp(conn, cmd, data);
3418 break;
3419
3420 case L2CAP_CONF_REQ:
3421 err = l2cap_config_req(conn, cmd, cmd_len, data);
3422 break;
3423
3424 case L2CAP_CONF_RSP:
3425 err = l2cap_config_rsp(conn, cmd, data);
3426 break;
3427
3428 case L2CAP_DISCONN_REQ:
3429 err = l2cap_disconnect_req(conn, cmd, data);
3430 break;
3431
3432 case L2CAP_DISCONN_RSP:
3433 err = l2cap_disconnect_rsp(conn, cmd, data);
3434 break;
3435
3436 case L2CAP_ECHO_REQ:
3437 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3438 break;
3439
3440 case L2CAP_ECHO_RSP:
3441 break;
3442
3443 case L2CAP_INFO_REQ:
3444 err = l2cap_information_req(conn, cmd, data);
3445 break;
3446
3447 case L2CAP_INFO_RSP:
3448 err = l2cap_information_rsp(conn, cmd, data);
3449 break;
3450
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003451 case L2CAP_CREATE_CHAN_REQ:
3452 err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3453 break;
3454
3455 case L2CAP_CREATE_CHAN_RSP:
3456 err = l2cap_create_channel_rsp(conn, cmd, data);
3457 break;
3458
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003459 case L2CAP_MOVE_CHAN_REQ:
3460 err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
3461 break;
3462
3463 case L2CAP_MOVE_CHAN_RSP:
3464 err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
3465 break;
3466
3467 case L2CAP_MOVE_CHAN_CFM:
3468 err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
3469 break;
3470
3471 case L2CAP_MOVE_CHAN_CFM_RSP:
3472 err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
3473 break;
3474
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003475 default:
3476 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3477 err = -EINVAL;
3478 break;
3479 }
3480
3481 return err;
3482}
3483
3484static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3485 struct l2cap_cmd_hdr *cmd, u8 *data)
3486{
3487 switch (cmd->code) {
3488 case L2CAP_COMMAND_REJ:
3489 return 0;
3490
3491 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003492 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003493
3494 case L2CAP_CONN_PARAM_UPDATE_RSP:
3495 return 0;
3496
3497 default:
3498 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3499 return -EINVAL;
3500 }
3501}
3502
3503static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3504 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003505{
3506 u8 *data = skb->data;
3507 int len = skb->len;
3508 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003509 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003510
3511 l2cap_raw_recv(conn, skb);
3512
3513 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003514 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003515 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3516 data += L2CAP_CMD_HDR_SIZE;
3517 len -= L2CAP_CMD_HDR_SIZE;
3518
Al Viro88219a02007-07-29 00:17:25 -07003519 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520
Al Viro88219a02007-07-29 00:17:25 -07003521 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 -07003522
Al Viro88219a02007-07-29 00:17:25 -07003523 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524 BT_DBG("corrupted command");
3525 break;
3526 }
3527
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003528 if (conn->hcon->type == LE_LINK)
3529 err = l2cap_le_sig_cmd(conn, &cmd, data);
3530 else
3531 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003532
3533 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003534 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003535
3536 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537
3538 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003539 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003540 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3541 }
3542
Al Viro88219a02007-07-29 00:17:25 -07003543 data += cmd_len;
3544 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003545 }
3546
3547 kfree_skb(skb);
3548}
3549
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003550static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003551{
3552 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003553 int hdr_size;
3554
3555 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3556 hdr_size = L2CAP_EXT_HDR_SIZE;
3557 else
3558 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003559
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003560 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003561 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003562 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3563 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3564
3565 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003566 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003567 }
3568 return 0;
3569}
3570
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003571static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003572{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003573 u32 control = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003574
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003575 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003576
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003577 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003578
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003579 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003580 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003581 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003582 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003583 }
3584
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003585 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003586 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003587
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003588 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003589
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003590 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003591 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003592 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003593 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003594 }
3595}
3596
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003597static 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 -03003598{
3599 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003600 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003601
3602 bt_cb(skb)->tx_seq = tx_seq;
3603 bt_cb(skb)->sar = sar;
3604
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003605 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003606
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003607 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003608
Szymon Janc039d9572011-11-16 09:32:19 +01003609 while (next_skb) {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003610 if (bt_cb(next_skb)->tx_seq == tx_seq)
3611 return -EINVAL;
3612
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003613 next_tx_seq_offset = __seq_offset(chan,
3614 bt_cb(next_skb)->tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003615
3616 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003617 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003618 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003619 }
3620
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003621 if (skb_queue_is_last(&chan->srej_q, next_skb))
Szymon Janc039d9572011-11-16 09:32:19 +01003622 next_skb = NULL;
3623 else
3624 next_skb = skb_queue_next(&chan->srej_q, next_skb);
3625 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003626
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003627 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003628
3629 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003630}
3631
Mat Martineau84084a32011-07-22 14:54:00 -07003632static void append_skb_frag(struct sk_buff *skb,
3633 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003634{
Mat Martineau84084a32011-07-22 14:54:00 -07003635 /* skb->len reflects data in skb as well as all fragments
3636 * skb->data_len reflects only data in fragments
3637 */
3638 if (!skb_has_frag_list(skb))
3639 skb_shinfo(skb)->frag_list = new_frag;
3640
3641 new_frag->next = NULL;
3642
3643 (*last_frag)->next = new_frag;
3644 *last_frag = new_frag;
3645
3646 skb->len += new_frag->len;
3647 skb->data_len += new_frag->len;
3648 skb->truesize += new_frag->truesize;
3649}
3650
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003651static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
Mat Martineau84084a32011-07-22 14:54:00 -07003652{
3653 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003654
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003655 switch (__get_ctrl_sar(chan, control)) {
3656 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003657 if (chan->sdu)
3658 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003659
Mat Martineau84084a32011-07-22 14:54:00 -07003660 err = chan->ops->recv(chan->data, skb);
3661 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003662
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003663 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003664 if (chan->sdu)
3665 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003666
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003667 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003668 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003669
Mat Martineau84084a32011-07-22 14:54:00 -07003670 if (chan->sdu_len > chan->imtu) {
3671 err = -EMSGSIZE;
3672 break;
3673 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003674
Mat Martineau84084a32011-07-22 14:54:00 -07003675 if (skb->len >= chan->sdu_len)
3676 break;
3677
3678 chan->sdu = skb;
3679 chan->sdu_last_frag = skb;
3680
3681 skb = NULL;
3682 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003683 break;
3684
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003685 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003686 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003687 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003688
Mat Martineau84084a32011-07-22 14:54:00 -07003689 append_skb_frag(chan->sdu, skb,
3690 &chan->sdu_last_frag);
3691 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003692
Mat Martineau84084a32011-07-22 14:54:00 -07003693 if (chan->sdu->len >= chan->sdu_len)
3694 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003695
Mat Martineau84084a32011-07-22 14:54:00 -07003696 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003697 break;
3698
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003699 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003700 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003701 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003702
Mat Martineau84084a32011-07-22 14:54:00 -07003703 append_skb_frag(chan->sdu, skb,
3704 &chan->sdu_last_frag);
3705 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003706
Mat Martineau84084a32011-07-22 14:54:00 -07003707 if (chan->sdu->len != chan->sdu_len)
3708 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003709
Mat Martineau84084a32011-07-22 14:54:00 -07003710 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003711
Mat Martineau84084a32011-07-22 14:54:00 -07003712 if (!err) {
3713 /* Reassembly complete */
3714 chan->sdu = NULL;
3715 chan->sdu_last_frag = NULL;
3716 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003717 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003718 break;
3719 }
3720
Mat Martineau84084a32011-07-22 14:54:00 -07003721 if (err) {
3722 kfree_skb(skb);
3723 kfree_skb(chan->sdu);
3724 chan->sdu = NULL;
3725 chan->sdu_last_frag = NULL;
3726 chan->sdu_len = 0;
3727 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003728
Mat Martineau84084a32011-07-22 14:54:00 -07003729 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003730}
3731
Mat Martineau26f880d2011-07-07 09:39:01 -07003732static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003733{
Mat Martineau26f880d2011-07-07 09:39:01 -07003734 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003735
Mat Martineau26f880d2011-07-07 09:39:01 -07003736 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3737
Szymon Janc77f918b2012-01-11 10:59:48 +01003738 __set_ack_timer(chan);
Mat Martineau26f880d2011-07-07 09:39:01 -07003739}
3740
3741static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3742{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003743 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003744
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003745 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003746 goto done;
3747
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003748 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003749 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003750 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003751 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003752 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003753
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003754 __clear_retrans_timer(chan);
3755 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003756
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003757 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003758
3759done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003760 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3761 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003762
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003763 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003764}
3765
Mat Martineaue3281402011-07-07 09:39:02 -07003766void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003767{
Mat Martineaue3281402011-07-07 09:39:02 -07003768 if (chan->mode == L2CAP_MODE_ERTM) {
3769 if (busy)
3770 l2cap_ertm_enter_local_busy(chan);
3771 else
3772 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003773 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003774}
3775
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003776static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003777{
3778 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003779 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003780
Mat Martineaue3281402011-07-07 09:39:02 -07003781 while ((skb = skb_peek(&chan->srej_q)) &&
3782 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3783 int err;
3784
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003785 if (bt_cb(skb)->tx_seq != tx_seq)
3786 break;
3787
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003788 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003789 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003790 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003791
3792 if (err < 0) {
3793 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3794 break;
3795 }
3796
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003797 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
3798 tx_seq = __next_seq(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003799 }
3800}
3801
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003802static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003803{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003804 struct srej_list *l, *tmp;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003805 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003806
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003807 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003808 if (l->tx_seq == tx_seq) {
3809 list_del(&l->list);
3810 kfree(l);
3811 return;
3812 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003813 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003814 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003815 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003816 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003817 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003818 }
3819}
3820
Szymon Jancaef89f22011-11-16 09:32:18 +01003821static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003822{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003823 struct srej_list *new;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003824 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003825
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003826 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003827 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003828 control |= __set_reqseq(chan, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003829 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003830
3831 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Szymon Jancaef89f22011-11-16 09:32:18 +01003832 if (!new)
3833 return -ENOMEM;
3834
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003835 new->tx_seq = chan->expected_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003836
3837 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
3838
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003839 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003840 }
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003841
3842 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Szymon Jancaef89f22011-11-16 09:32:18 +01003843
3844 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003845}
3846
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003847static 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 -03003848{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003849 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003850 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003851 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003852 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003853 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003854 int err = 0;
3855
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003856 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 -03003857 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003858
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003859 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003860 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003861 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003862 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003863 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003864 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003865 }
3866
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003867 chan->expected_ack_seq = req_seq;
3868 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003869
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003870 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003871
3872 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003873 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003874 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003875 goto drop;
3876 }
3877
Szymon Janc77f918b2012-01-11 10:59:48 +01003878 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3879 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
3880 l2cap_send_ack(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003881 goto drop;
Szymon Janc77f918b2012-01-11 10:59:48 +01003882 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003883
Mat Martineau02f1b642011-06-29 14:35:19 -07003884 if (tx_seq == chan->expected_tx_seq)
3885 goto expected;
3886
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003887 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003888 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003889
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003890 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003891 struct srej_list, list);
3892 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003893 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003894 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003895
3896 list_del(&first->list);
3897 kfree(first);
3898
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003899 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003900 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003901 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003902 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003903 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003904 }
3905 } else {
3906 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003907
3908 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003909 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003910 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003911
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003912 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003913 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003914 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003915 return 0;
3916 }
3917 }
Szymon Jancaef89f22011-11-16 09:32:18 +01003918
3919 err = l2cap_send_srejframe(chan, tx_seq);
3920 if (err < 0) {
3921 l2cap_send_disconn_req(chan->conn, chan, -err);
3922 return err;
3923 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003924 }
3925 } else {
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003926 expected_tx_seq_offset = __seq_offset(chan,
3927 chan->expected_tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003928
3929 /* duplicated tx_seq */
3930 if (tx_seq_offset < expected_tx_seq_offset)
3931 goto drop;
3932
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003933 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003934
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003935 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003936
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003937 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003938 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003939
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003940 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003941 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003942
Szymon Janc0ef3ef02012-01-11 10:59:46 +01003943 /* Set P-bit only if there are some I-frames to ack. */
3944 if (__clear_ack_timer(chan))
3945 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003946
Szymon Jancaef89f22011-11-16 09:32:18 +01003947 err = l2cap_send_srejframe(chan, tx_seq);
3948 if (err < 0) {
3949 l2cap_send_disconn_req(chan->conn, chan, -err);
3950 return err;
3951 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003952 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003953 return 0;
3954
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003955expected:
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003956 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003957
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003958 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003959 bt_cb(skb)->tx_seq = tx_seq;
3960 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003961 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003962 return 0;
3963 }
3964
Mat Martineau84084a32011-07-22 14:54:00 -07003965 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003966 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
3967
Mat Martineaue3281402011-07-07 09:39:02 -07003968 if (err < 0) {
3969 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3970 return err;
3971 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003972
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003973 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003974 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003975 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003976 }
3977
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003978
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003979 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3980 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003981 l2cap_send_ack(chan);
Gustavo F. Padovan4d611e42011-06-23 19:30:48 -03003982 else
3983 __set_ack_timer(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003984
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003985 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003986
3987drop:
3988 kfree_skb(skb);
3989 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003990}
3991
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003992static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003993{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003994 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003995 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003996
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003997 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003998 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003999
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004000 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004001 set_bit(CONN_SEND_FBIT, &chan->conn_state);
4002 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
4003 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004004 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004005 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004006
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004007 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004008 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004009 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004010 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004011 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004012
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004013 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004014 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004015
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004016 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004017 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004018
4019 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004020 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004021 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004022 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004023
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004024 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4025 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004026 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02004027 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004028 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004029 }
4030}
4031
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004032static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004033{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004034 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004035
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004036 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004037
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004038 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004039
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004040 chan->expected_ack_seq = tx_seq;
4041 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004042
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004043 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004044 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004045 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004046 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004047 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004048
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004049 if (test_bit(CONN_WAIT_F, &chan->conn_state))
4050 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004051 }
4052}
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004053static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004054{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004055 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004056
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004057 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004058
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004059 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004060
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004061 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004062 chan->expected_ack_seq = tx_seq;
4063 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004064
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004065 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004066 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004067
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004068 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004069
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004070 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004071 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004072 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004073 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004074 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004075 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004076 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004077 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004078 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004079 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004080 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004081 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004082 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004083 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004084 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004085 }
4086 }
4087}
4088
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004089static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004090{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004091 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004092
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004093 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004094
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004095 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004096 chan->expected_ack_seq = tx_seq;
4097 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004098
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004099 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004100 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004101
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004102 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004103 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004104 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004105 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004106 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004107 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004108
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004109 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004110 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004111 } else {
4112 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4113 l2cap_send_sframe(chan, rx_control);
4114 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004115}
4116
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004117static 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 -03004118{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004119 BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004120
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004121 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004122 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004123 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004124 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004125 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004126 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004127 }
4128
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004129 switch (__get_ctrl_super(chan, rx_control)) {
4130 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004131 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004132 break;
4133
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004134 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004135 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004136 break;
4137
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004138 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004139 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004140 break;
4141
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004142 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004143 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004144 break;
4145 }
4146
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004147 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004148 return 0;
4149}
4150
Szymon Janccad8f1d02012-01-23 10:06:05 +01004151static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004152{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004153 u32 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004154 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004155 int len, next_tx_seq_offset, req_seq_offset;
4156
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004157 control = __get_control(chan, skb->data);
4158 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004159 len = skb->len;
4160
4161 /*
4162 * We can just drop the corrupted I-frame here.
4163 * Receiver will miss it and start proper recovery
4164 * procedures and ask retransmission.
4165 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004166 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004167 goto drop;
4168
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004169 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004170 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004171
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004172 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004173 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004174
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004175 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004176 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004177 goto drop;
4178 }
4179
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004180 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004181
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004182 req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4183
4184 next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4185 chan->expected_ack_seq);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004186
4187 /* check for invalid req-seq */
4188 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004189 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004190 goto drop;
4191 }
4192
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004193 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004194 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004195 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004196 goto drop;
4197 }
4198
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004199 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004200 } else {
4201 if (len != 0) {
4202 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004203 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004204 goto drop;
4205 }
4206
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004207 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004208 }
4209
4210 return 0;
4211
4212drop:
4213 kfree_skb(skb);
4214 return 0;
4215}
4216
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4218{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004219 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07004220 struct sock *sk = NULL;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004221 u32 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004222 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004223 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004224
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004225 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004226 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227 BT_DBG("unknown cid 0x%4.4x", cid);
4228 goto drop;
4229 }
4230
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004231 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004232
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004233 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004234
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004235 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236 goto drop;
4237
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004238 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004239 case L2CAP_MODE_BASIC:
4240 /* If socket recv buffers overflows we drop data here
4241 * which is *bad* because L2CAP has to be reliable.
4242 * But we don't have any other choice. L2CAP doesn't
4243 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004245 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004246 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004248 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004249 goto done;
4250 break;
4251
4252 case L2CAP_MODE_ERTM:
Andrei Emeltchenko5ef8cb92012-01-13 17:21:42 +02004253 l2cap_ertm_data_rcv(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004254
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004255 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004256
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004257 case L2CAP_MODE_STREAMING:
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004258 control = __get_control(chan, skb->data);
4259 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004260 len = skb->len;
4261
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004262 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004263 goto drop;
4264
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004265 if (__is_sar_start(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004266 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004267
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004268 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004269 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004270
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004271 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004272 goto drop;
4273
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004274 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004275
Mat Martineau84084a32011-07-22 14:54:00 -07004276 if (chan->expected_tx_seq != tx_seq) {
4277 /* Frame(s) missing - must discard partial SDU */
4278 kfree_skb(chan->sdu);
4279 chan->sdu = NULL;
4280 chan->sdu_last_frag = NULL;
4281 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004282
Mat Martineau84084a32011-07-22 14:54:00 -07004283 /* TODO: Notify userland of missing data */
4284 }
4285
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004286 chan->expected_tx_seq = __next_seq(chan, tx_seq);
Mat Martineau84084a32011-07-22 14:54:00 -07004287
4288 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
4289 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004290
4291 goto done;
4292
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004293 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004294 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004295 break;
4296 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297
4298drop:
4299 kfree_skb(skb);
4300
4301done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004302 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004303 release_sock(sk);
Marcel Holtmann01394182006-07-03 10:02:46 +02004304
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305 return 0;
4306}
4307
Al Viro8e036fc2007-07-29 00:16:36 -07004308static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004310 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004311 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004313 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
4314 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004315 goto drop;
4316
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004317 sk = chan->sk;
4318
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004319 lock_sock(sk);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00004320
Linus Torvalds1da177e2005-04-16 15:20:36 -07004321 BT_DBG("sk %p, len %d", sk, skb->len);
4322
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004323 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324 goto drop;
4325
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004326 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004327 goto drop;
4328
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004329 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330 goto done;
4331
4332drop:
4333 kfree_skb(skb);
4334
4335done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004336 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004337 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338 return 0;
4339}
4340
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004341static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
4342{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004343 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004344 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004345
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004346 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
4347 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004348 goto drop;
4349
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004350 sk = chan->sk;
4351
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004352 lock_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004353
4354 BT_DBG("sk %p, len %d", sk, skb->len);
4355
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004356 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004357 goto drop;
4358
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004359 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004360 goto drop;
4361
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004362 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004363 goto done;
4364
4365drop:
4366 kfree_skb(skb);
4367
4368done:
4369 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004370 release_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004371 return 0;
4372}
4373
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4375{
4376 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004377 u16 cid, len;
4378 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004379
4380 skb_pull(skb, L2CAP_HDR_SIZE);
4381 cid = __le16_to_cpu(lh->cid);
4382 len = __le16_to_cpu(lh->len);
4383
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004384 if (len != skb->len) {
4385 kfree_skb(skb);
4386 return;
4387 }
4388
Linus Torvalds1da177e2005-04-16 15:20:36 -07004389 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4390
4391 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004392 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004393 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394 l2cap_sig_channel(conn, skb);
4395 break;
4396
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004397 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004398 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004399 skb_pull(skb, 2);
4400 l2cap_conless_channel(conn, psm, skb);
4401 break;
4402
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004403 case L2CAP_CID_LE_DATA:
4404 l2cap_att_channel(conn, cid, skb);
4405 break;
4406
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004407 case L2CAP_CID_SMP:
4408 if (smp_sig_channel(conn, skb))
4409 l2cap_conn_del(conn->hcon, EACCES);
4410 break;
4411
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412 default:
4413 l2cap_data_channel(conn, cid, skb);
4414 break;
4415 }
4416}
4417
4418/* ---- L2CAP interface with lower layer (HCI) ---- */
4419
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004420int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421{
4422 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004423 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424
Linus Torvalds1da177e2005-04-16 15:20:36 -07004425 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4426
4427 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004428 read_lock(&chan_list_lock);
4429 list_for_each_entry(c, &chan_list, global_l) {
4430 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004431
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004432 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004433 continue;
4434
4435 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004436 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004437 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004438 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004440 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4441 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004442 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004443 lm2 |= HCI_LM_MASTER;
4444 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004445 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004446 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004447
4448 return exact ? lm1 : lm2;
4449}
4450
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004451int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452{
Marcel Holtmann01394182006-07-03 10:02:46 +02004453 struct l2cap_conn *conn;
4454
Linus Torvalds1da177e2005-04-16 15:20:36 -07004455 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4456
Linus Torvalds1da177e2005-04-16 15:20:36 -07004457 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004458 conn = l2cap_conn_add(hcon, status);
4459 if (conn)
4460 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004461 } else
Joe Perchese1750722011-06-29 18:18:29 -07004462 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004463
4464 return 0;
4465}
4466
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004467int l2cap_disconn_ind(struct hci_conn *hcon)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004468{
4469 struct l2cap_conn *conn = hcon->l2cap_data;
4470
4471 BT_DBG("hcon %p", hcon);
4472
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004473 if (!conn)
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02004474 return HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01004475 return conn->disc_reason;
4476}
4477
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004478int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004479{
4480 BT_DBG("hcon %p reason %d", hcon, reason);
4481
Joe Perchese1750722011-06-29 18:18:29 -07004482 l2cap_conn_del(hcon, bt_to_errno(reason));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004483 return 0;
4484}
4485
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004486static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004487{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004488 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004489 return;
4490
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004491 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004492 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004493 __clear_chan_timer(chan);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004494 __set_chan_timer(chan,
4495 msecs_to_jiffies(L2CAP_ENC_TIMEOUT));
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004496 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004497 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004498 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004499 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004500 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004501 }
4502}
4503
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004504int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004505{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004506 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004507 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004508
Marcel Holtmann01394182006-07-03 10:02:46 +02004509 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004510 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004511
Linus Torvalds1da177e2005-04-16 15:20:36 -07004512 BT_DBG("conn %p", conn);
4513
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004514 if (hcon->type == LE_LINK) {
4515 smp_distribute_keys(conn, 0);
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02004516 cancel_delayed_work(&conn->security_timer);
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004517 }
4518
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02004519 rcu_read_lock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004520
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02004521 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004522 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004523
Linus Torvalds1da177e2005-04-16 15:20:36 -07004524 bh_lock_sock(sk);
4525
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004526 BT_DBG("chan->scid %d", chan->scid);
4527
4528 if (chan->scid == L2CAP_CID_LE_DATA) {
4529 if (!status && encrypt) {
4530 chan->sec_level = hcon->sec_level;
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02004531 l2cap_chan_ready(chan);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004532 }
4533
4534 bh_unlock_sock(sk);
4535 continue;
4536 }
4537
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004538 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004539 bh_unlock_sock(sk);
4540 continue;
4541 }
4542
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004543 if (!status && (chan->state == BT_CONNECTED ||
4544 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004545 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004546 bh_unlock_sock(sk);
4547 continue;
4548 }
4549
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004550 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004551 if (!status) {
4552 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004553 req.scid = cpu_to_le16(chan->scid);
4554 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004555
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004556 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004557 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004558
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004559 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004560 L2CAP_CONN_REQ, sizeof(req), &req);
4561 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004562 __clear_chan_timer(chan);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004563 __set_chan_timer(chan,
4564 msecs_to_jiffies(L2CAP_DISC_TIMEOUT));
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004565 }
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004566 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004567 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004568 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004569
4570 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004571 if (bt_sk(sk)->defer_setup) {
4572 struct sock *parent = bt_sk(sk)->parent;
4573 res = L2CAP_CR_PEND;
4574 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004575 if (parent)
4576 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004577 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004578 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004579 res = L2CAP_CR_SUCCESS;
4580 stat = L2CAP_CS_NO_INFO;
4581 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004582 } else {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004583 l2cap_state_change(chan, BT_DISCONN);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004584 __set_chan_timer(chan,
4585 msecs_to_jiffies(L2CAP_DISC_TIMEOUT));
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004586 res = L2CAP_CR_SEC_BLOCK;
4587 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004588 }
4589
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004590 rsp.scid = cpu_to_le16(chan->dcid);
4591 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004592 rsp.result = cpu_to_le16(res);
4593 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004594 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4595 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004596 }
4597
Linus Torvalds1da177e2005-04-16 15:20:36 -07004598 bh_unlock_sock(sk);
4599 }
4600
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02004601 rcu_read_unlock();
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004602
Linus Torvalds1da177e2005-04-16 15:20:36 -07004603 return 0;
4604}
4605
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004606int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004607{
4608 struct l2cap_conn *conn = hcon->l2cap_data;
4609
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004610 if (!conn)
4611 conn = l2cap_conn_add(hcon, 0);
4612
4613 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004614 goto drop;
4615
4616 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4617
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004618 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004619 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004620 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004621 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004622 int len;
4623
4624 if (conn->rx_len) {
4625 BT_ERR("Unexpected start frame (len %d)", skb->len);
4626 kfree_skb(conn->rx_skb);
4627 conn->rx_skb = NULL;
4628 conn->rx_len = 0;
4629 l2cap_conn_unreliable(conn, ECOMM);
4630 }
4631
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004632 /* Start fragment always begin with Basic L2CAP header */
4633 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004634 BT_ERR("Frame is too short (len %d)", skb->len);
4635 l2cap_conn_unreliable(conn, ECOMM);
4636 goto drop;
4637 }
4638
4639 hdr = (struct l2cap_hdr *) skb->data;
4640 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004641 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004642
4643 if (len == skb->len) {
4644 /* Complete frame received */
4645 l2cap_recv_frame(conn, skb);
4646 return 0;
4647 }
4648
4649 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4650
4651 if (skb->len > len) {
4652 BT_ERR("Frame is too long (len %d, expected len %d)",
4653 skb->len, len);
4654 l2cap_conn_unreliable(conn, ECOMM);
4655 goto drop;
4656 }
4657
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004658 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004659
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004660 if (chan && chan->sk) {
4661 struct sock *sk = chan->sk;
4662
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004663 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004664 BT_ERR("Frame exceeding recv MTU (len %d, "
4665 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004666 chan->imtu);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004667 release_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004668 l2cap_conn_unreliable(conn, ECOMM);
4669 goto drop;
4670 }
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004671 release_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004672 }
4673
Linus Torvalds1da177e2005-04-16 15:20:36 -07004674 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004675 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4676 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004677 goto drop;
4678
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004679 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004680 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004681 conn->rx_len = len - skb->len;
4682 } else {
4683 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4684
4685 if (!conn->rx_len) {
4686 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4687 l2cap_conn_unreliable(conn, ECOMM);
4688 goto drop;
4689 }
4690
4691 if (skb->len > conn->rx_len) {
4692 BT_ERR("Fragment is too long (len %d, expected %d)",
4693 skb->len, conn->rx_len);
4694 kfree_skb(conn->rx_skb);
4695 conn->rx_skb = NULL;
4696 conn->rx_len = 0;
4697 l2cap_conn_unreliable(conn, ECOMM);
4698 goto drop;
4699 }
4700
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004701 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004702 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004703 conn->rx_len -= skb->len;
4704
4705 if (!conn->rx_len) {
4706 /* Complete frame received */
4707 l2cap_recv_frame(conn, conn->rx_skb);
4708 conn->rx_skb = NULL;
4709 }
4710 }
4711
4712drop:
4713 kfree_skb(skb);
4714 return 0;
4715}
4716
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004717static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004718{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004719 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004720
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02004721 read_lock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004722
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004723 list_for_each_entry(c, &chan_list, global_l) {
4724 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004725
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004726 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 +01004727 batostr(&bt_sk(sk)->src),
4728 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004729 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004730 c->scid, c->dcid, c->imtu, c->omtu,
4731 c->sec_level, c->mode);
Andrei Emeltchenko61e1b4b2012-01-19 11:19:50 +02004732 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004733
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02004734 read_unlock(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004735
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004736 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004737}
4738
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004739static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4740{
4741 return single_open(file, l2cap_debugfs_show, inode->i_private);
4742}
4743
4744static const struct file_operations l2cap_debugfs_fops = {
4745 .open = l2cap_debugfs_open,
4746 .read = seq_read,
4747 .llseek = seq_lseek,
4748 .release = single_release,
4749};
4750
4751static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004752
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004753int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004754{
4755 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004756
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004757 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004758 if (err < 0)
4759 return err;
4760
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004761 if (bt_debugfs) {
4762 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4763 bt_debugfs, NULL, &l2cap_debugfs_fops);
4764 if (!l2cap_debugfs)
4765 BT_ERR("Failed to create L2CAP debug file");
4766 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004767
Linus Torvalds1da177e2005-04-16 15:20:36 -07004768 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004769}
4770
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004771void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004772{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004773 debugfs_remove(l2cap_debugfs);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004774 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004775}
4776
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004777module_param(disable_ertm, bool, 0644);
4778MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");