blob: 3b9e2813f1fcff98fbbad1274f8a06129d3991c9 [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
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030076static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
77
Marcel Holtmann01394182006-07-03 10:02:46 +020078/* ---- L2CAP channels ---- */
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -030079
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030080static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020081{
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -020082 struct l2cap_chan *c, *r = NULL;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030083
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -020084 rcu_read_lock();
85
86 list_for_each_entry_rcu(c, &conn->chan_l, list) {
87 if (c->dcid == cid) {
88 r = c;
89 break;
90 }
Marcel Holtmann01394182006-07-03 10:02:46 +020091 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -020092
93 rcu_read_unlock();
94 return r;
Marcel Holtmann01394182006-07-03 10:02:46 +020095}
96
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030097static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020098{
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -020099 struct l2cap_chan *c, *r = NULL;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300100
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200101 rcu_read_lock();
102
103 list_for_each_entry_rcu(c, &conn->chan_l, list) {
104 if (c->scid == cid) {
105 r = c;
106 break;
107 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200108 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200109
110 rcu_read_unlock();
111 return r;
Marcel Holtmann01394182006-07-03 10:02:46 +0200112}
113
114/* Find channel with given SCID.
115 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300116static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200117{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300118 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300119
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300120 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300121 if (c)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300122 lock_sock(c->sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300123 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200124}
125
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300126static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200127{
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200128 struct l2cap_chan *c, *r = NULL;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300129
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200130 rcu_read_lock();
131
132 list_for_each_entry_rcu(c, &conn->chan_l, list) {
133 if (c->ident == ident) {
134 r = c;
135 break;
136 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200137 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200138
139 rcu_read_unlock();
140 return r;
Marcel Holtmann01394182006-07-03 10:02:46 +0200141}
142
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300143static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200144{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300145 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300146
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300147 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300148 if (c)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300149 lock_sock(c->sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300150 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200151}
152
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300153static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300154{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300155 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300156
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300157 list_for_each_entry(c, &chan_list, global_l) {
158 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Szymon Janc250938c2011-11-16 09:32:22 +0100159 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300160 }
Szymon Janc250938c2011-11-16 09:32:22 +0100161 return NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300162}
163
164int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
165{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300166 int err;
167
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200168 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300169
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300170 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300171 err = -EADDRINUSE;
172 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300173 }
174
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300175 if (psm) {
176 chan->psm = psm;
177 chan->sport = psm;
178 err = 0;
179 } else {
180 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300181
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300182 err = -EINVAL;
183 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300184 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300185 chan->psm = cpu_to_le16(p);
186 chan->sport = cpu_to_le16(p);
187 err = 0;
188 break;
189 }
190 }
191
192done:
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200193 write_unlock(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300194 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300195}
196
197int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
198{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200199 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300200
201 chan->scid = scid;
202
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200203 write_unlock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300204
205 return 0;
206}
207
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300208static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200209{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300210 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200211
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300212 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300213 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200214 return cid;
215 }
216
217 return 0;
218}
219
Gustavo F. Padovanbadaaa02011-11-23 20:11:46 -0200220static char *state_to_string(int state)
221{
222 switch(state) {
223 case BT_CONNECTED:
224 return "BT_CONNECTED";
225 case BT_OPEN:
226 return "BT_OPEN";
227 case BT_BOUND:
228 return "BT_BOUND";
229 case BT_LISTEN:
230 return "BT_LISTEN";
231 case BT_CONNECT:
232 return "BT_CONNECT";
233 case BT_CONNECT2:
234 return "BT_CONNECT2";
235 case BT_CONFIG:
236 return "BT_CONFIG";
237 case BT_DISCONN:
238 return "BT_DISCONN";
239 case BT_CLOSED:
240 return "BT_CLOSED";
241 }
242
243 return "invalid state";
244}
245
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300246static void l2cap_state_change(struct l2cap_chan *chan, int state)
247{
Gustavo F. Padovanbadaaa02011-11-23 20:11:46 -0200248 BT_DBG("%p %s -> %s", chan, state_to_string(chan->state),
249 state_to_string(state));
250
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300251 chan->state = state;
252 chan->ops->state_change(chan->data, state);
253}
254
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300255static void l2cap_chan_timeout(struct work_struct *work)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300256{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300257 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
258 chan_timer.work);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300259 struct sock *sk = chan->sk;
260 int reason;
261
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300262 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300263
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300264 lock_sock(sk);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300265
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300266 if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300267 reason = ECONNREFUSED;
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300268 else if (chan->state == BT_CONNECT &&
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300269 chan->sec_level != BT_SECURITY_SDP)
270 reason = ECONNREFUSED;
271 else
272 reason = ETIMEDOUT;
273
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300274 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300275
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300276 release_sock(sk);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300277
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300278 chan->ops->close(chan->data);
Ulisses Furquim371fd832011-12-21 20:02:36 -0200279 l2cap_chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300280}
281
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300282struct l2cap_chan *l2cap_chan_create(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200283{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300284 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200285
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300286 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
287 if (!chan)
288 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200289
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300290 chan->sk = sk;
291
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200292 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300293 list_add(&chan->global_l, &chan_list);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200294 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300295
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300296 INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300297
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300298 chan->state = BT_OPEN;
299
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300300 atomic_set(&chan->refcnt, 1);
301
Szymon Jancabc545b2011-11-03 16:05:44 +0100302 BT_DBG("sk %p chan %p", sk, chan);
303
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300304 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200305}
306
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300307void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300308{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200309 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300310 list_del(&chan->global_l);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200311 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300312
Ulisses Furquim371fd832011-12-21 20:02:36 -0200313 l2cap_chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300314}
315
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200316static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200317{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300318 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300319 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200320
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +0200321 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +0100322
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300323 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200324
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300325 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
Ville Tervob62f3282011-02-10 22:38:50 -0300326 if (conn->hcon->type == LE_LINK) {
327 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300328 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300329 chan->scid = L2CAP_CID_LE_DATA;
330 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300331 } else {
332 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300333 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300334 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300335 }
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300336 } else if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200337 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300338 chan->scid = L2CAP_CID_CONN_LESS;
339 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300340 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200341 } else {
342 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300343 chan->scid = L2CAP_CID_SIGNALING;
344 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300345 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200346 }
347
Andrei Emeltchenko8f7975b2011-10-13 16:18:54 +0300348 chan->local_id = L2CAP_BESTEFFORT_ID;
349 chan->local_stype = L2CAP_SERV_BESTEFFORT;
350 chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
351 chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
352 chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
353 chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
354
Ulisses Furquim371fd832011-12-21 20:02:36 -0200355 l2cap_chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300356
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200357 list_add_rcu(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200358}
359
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900360/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200361 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300362static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200363{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300364 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300365 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200366 struct sock *parent = bt_sk(sk)->parent;
367
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300368 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200369
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300370 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200371
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900372 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300373 /* Delete from channel list */
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200374 list_del_rcu(&chan->list);
375 synchronize_rcu();
376
Ulisses Furquim371fd832011-12-21 20:02:36 -0200377 l2cap_chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300378
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300379 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200380 hci_conn_put(conn->hcon);
381 }
382
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300383 l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200384 sock_set_flag(sk, SOCK_ZAPPED);
385
386 if (err)
387 sk->sk_err = err;
388
389 if (parent) {
390 bt_accept_unlink(sk);
391 parent->sk_data_ready(parent, 0);
392 } else
393 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300394
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300395 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
396 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300397 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300398
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300399 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300400
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300401 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300402 struct srej_list *l, *tmp;
403
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300404 __clear_retrans_timer(chan);
405 __clear_monitor_timer(chan);
406 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300407
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300408 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300409
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300410 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300411 list_del(&l->list);
412 kfree(l);
413 }
414 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200415}
416
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300417static void l2cap_chan_cleanup_listen(struct sock *parent)
418{
419 struct sock *sk;
420
421 BT_DBG("parent %p", parent);
422
423 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300424 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300425 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300426 __clear_chan_timer(chan);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300427 lock_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300428 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300429 release_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300430 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300431 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300432}
433
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300434void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300435{
436 struct l2cap_conn *conn = chan->conn;
437 struct sock *sk = chan->sk;
438
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300439 BT_DBG("chan %p state %d socket %p", chan, chan->state, sk->sk_socket);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300440
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300441 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300442 case BT_LISTEN:
443 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300444
445 l2cap_state_change(chan, BT_CLOSED);
446 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300447 break;
448
449 case BT_CONNECTED:
450 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300451 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300452 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300453 __clear_chan_timer(chan);
454 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300455 l2cap_send_disconn_req(conn, chan, reason);
456 } else
457 l2cap_chan_del(chan, reason);
458 break;
459
460 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300461 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300462 conn->hcon->type == ACL_LINK) {
463 struct l2cap_conn_rsp rsp;
464 __u16 result;
465
466 if (bt_sk(sk)->defer_setup)
467 result = L2CAP_CR_SEC_BLOCK;
468 else
469 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300470 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300471
472 rsp.scid = cpu_to_le16(chan->dcid);
473 rsp.dcid = cpu_to_le16(chan->scid);
474 rsp.result = cpu_to_le16(result);
475 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
476 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
477 sizeof(rsp), &rsp);
478 }
479
480 l2cap_chan_del(chan, reason);
481 break;
482
483 case BT_CONNECT:
484 case BT_DISCONN:
485 l2cap_chan_del(chan, reason);
486 break;
487
488 default:
489 sock_set_flag(sk, SOCK_ZAPPED);
490 break;
491 }
492}
493
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300494static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530495{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300496 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300497 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530498 case BT_SECURITY_HIGH:
499 return HCI_AT_DEDICATED_BONDING_MITM;
500 case BT_SECURITY_MEDIUM:
501 return HCI_AT_DEDICATED_BONDING;
502 default:
503 return HCI_AT_NO_BONDING;
504 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300505 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300506 if (chan->sec_level == BT_SECURITY_LOW)
507 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530508
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300509 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530510 return HCI_AT_NO_BONDING_MITM;
511 else
512 return HCI_AT_NO_BONDING;
513 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300514 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530515 case BT_SECURITY_HIGH:
516 return HCI_AT_GENERAL_BONDING_MITM;
517 case BT_SECURITY_MEDIUM:
518 return HCI_AT_GENERAL_BONDING;
519 default:
520 return HCI_AT_NO_BONDING;
521 }
522 }
523}
524
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200525/* Service level security */
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200526int l2cap_chan_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200527{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300528 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100529 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200530
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300531 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100532
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300533 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200534}
535
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200536static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200537{
538 u8 id;
539
540 /* Get next available identificator.
541 * 1 - 128 are used by kernel.
542 * 129 - 199 are reserved.
543 * 200 - 254 are used by utilities like l2ping, etc.
544 */
545
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200546 spin_lock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200547
548 if (++conn->tx_ident > 128)
549 conn->tx_ident = 1;
550
551 id = conn->tx_ident;
552
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200553 spin_unlock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200554
555 return id;
556}
557
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300558static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200559{
560 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200561 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200562
563 BT_DBG("code 0x%2.2x", code);
564
565 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300566 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200567
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200568 if (lmp_no_flush_capable(conn->hcon->hdev))
569 flags = ACL_START_NO_FLUSH;
570 else
571 flags = ACL_START;
572
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700573 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +0200574 skb->priority = HCI_PRIO_MAX;
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700575
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200576 hci_send_acl(conn->hchan, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200577}
578
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200579static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
580{
581 struct hci_conn *hcon = chan->conn->hcon;
582 u16 flags;
583
584 BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
585 skb->priority);
586
587 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
588 lmp_no_flush_capable(hcon->hdev))
589 flags = ACL_START_NO_FLUSH;
590 else
591 flags = ACL_START;
592
593 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
594 hci_send_acl(chan->conn->hchan, skb, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595}
596
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300597static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300598{
599 struct sk_buff *skb;
600 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300601 struct l2cap_conn *conn = chan->conn;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300602 int count, hlen;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300603
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300604 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300605 return;
606
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300607 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
608 hlen = L2CAP_EXT_HDR_SIZE;
609 else
610 hlen = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300611
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300612 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300613 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300614
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300615 BT_DBG("chan %p, control 0x%8.8x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300616
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300617 count = min_t(unsigned int, conn->mtu, hlen);
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +0300618
619 control |= __set_sframe(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300620
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300621 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +0300622 control |= __set_ctrl_final(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300623
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300624 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +0300625 control |= __set_ctrl_poll(chan);
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300626
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300627 skb = bt_skb_alloc(count, GFP_ATOMIC);
628 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300629 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300630
631 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300632 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300633 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300634
635 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300636
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300637 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300638 u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
639 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300640 }
641
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200642 skb->priority = HCI_PRIO_MAX;
643 l2cap_do_send(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300644}
645
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300646static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300647{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300648 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300649 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300650 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300651 } else
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300652 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300653
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300654 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300655
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300656 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300657}
658
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300659static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300660{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300661 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300662}
663
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300664static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200665{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300666 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200667
668 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100669 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
670 return;
671
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200672 if (l2cap_chan_check_security(chan) &&
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300673 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200674 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300675 req.scid = cpu_to_le16(chan->scid);
676 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200677
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300678 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300679 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200680
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300681 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
682 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200683 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200684 } else {
685 struct l2cap_info_req req;
686 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
687
688 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
689 conn->info_ident = l2cap_get_ident(conn);
690
Gustavo F. Padovan030013d2011-12-20 10:57:28 -0200691 schedule_delayed_work(&conn->info_timer,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200692 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
693
694 l2cap_send_cmd(conn, conn->info_ident,
695 L2CAP_INFO_REQ, sizeof(req), &req);
696 }
697}
698
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300699static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
700{
701 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300702 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300703 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
704
705 switch (mode) {
706 case L2CAP_MODE_ERTM:
707 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
708 case L2CAP_MODE_STREAMING:
709 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
710 default:
711 return 0x00;
712 }
713}
714
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300715static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300716{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300717 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300718 struct l2cap_disconn_req req;
719
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300720 if (!conn)
721 return;
722
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300723 sk = chan->sk;
724
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300725 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300726 __clear_retrans_timer(chan);
727 __clear_monitor_timer(chan);
728 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300729 }
730
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300731 req.dcid = cpu_to_le16(chan->dcid);
732 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300733 l2cap_send_cmd(conn, l2cap_get_ident(conn),
734 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300735
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300736 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300737 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300738}
739
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200741static void l2cap_conn_start(struct l2cap_conn *conn)
742{
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200743 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200744
745 BT_DBG("conn %p", conn);
746
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200747 rcu_read_lock();
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200748
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200749 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300750 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300751
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200752 bh_lock_sock(sk);
753
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300754 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200755 bh_unlock_sock(sk);
756 continue;
757 }
758
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300759 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300760 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300761
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200762 if (!l2cap_chan_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300763 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300764 bh_unlock_sock(sk);
765 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200766 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300767
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300768 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
769 && test_bit(CONF_STATE2_DEVICE,
770 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300771 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300772 * so release the lock */
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300773 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300774 bh_unlock_sock(sk);
775 continue;
776 }
777
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300778 req.scid = cpu_to_le16(chan->scid);
779 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300780
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300781 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300782 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300783
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300784 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
785 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300786
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300787 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200788 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300789 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300790 rsp.scid = cpu_to_le16(chan->dcid);
791 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200792
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200793 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100794 if (bt_sk(sk)->defer_setup) {
795 struct sock *parent = bt_sk(sk)->parent;
796 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
797 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +0000798 if (parent)
799 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100800
801 } else {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300802 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100803 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
804 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
805 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200806 } else {
807 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
808 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
809 }
810
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300811 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
812 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300813
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300814 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300815 rsp.result != L2CAP_CR_SUCCESS) {
816 bh_unlock_sock(sk);
817 continue;
818 }
819
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300820 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300821 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300822 l2cap_build_conf_req(chan, buf), buf);
823 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200824 }
825
826 bh_unlock_sock(sk);
827 }
828
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200829 rcu_read_unlock();
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200830}
831
Ville Tervob62f3282011-02-10 22:38:50 -0300832/* Find socket with cid and source bdaddr.
833 * Returns closest match, locked.
834 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300835static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300836{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300837 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300838
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300839 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300840
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300841 list_for_each_entry(c, &chan_list, global_l) {
842 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300843
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300844 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300845 continue;
846
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300847 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300848 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300849 if (!bacmp(&bt_sk(sk)->src, src)) {
850 read_unlock(&chan_list_lock);
851 return c;
852 }
Ville Tervob62f3282011-02-10 22:38:50 -0300853
854 /* Closest match */
855 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300856 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300857 }
858 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300859
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300860 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300861
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300862 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300863}
864
865static void l2cap_le_conn_ready(struct l2cap_conn *conn)
866{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300867 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300868 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300869
870 BT_DBG("");
871
872 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300873 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300874 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300875 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300876 return;
877
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300878 parent = pchan->sk;
879
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300880 lock_sock(parent);
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300881
Ville Tervob62f3282011-02-10 22:38:50 -0300882 /* Check for backlog size */
883 if (sk_acceptq_is_full(parent)) {
884 BT_DBG("backlog full %d", parent->sk_ack_backlog);
885 goto clean;
886 }
887
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300888 chan = pchan->ops->new_connection(pchan->data);
889 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300890 goto clean;
891
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300892 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300893
Ville Tervob62f3282011-02-10 22:38:50 -0300894 hci_conn_hold(conn->hcon);
895
Ville Tervob62f3282011-02-10 22:38:50 -0300896 bacpy(&bt_sk(sk)->src, conn->src);
897 bacpy(&bt_sk(sk)->dst, conn->dst);
898
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300899 bt_accept_enqueue(parent, sk);
900
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200901 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300902
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300903 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300904
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300905 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300906 parent->sk_data_ready(parent, 0);
907
Ville Tervob62f3282011-02-10 22:38:50 -0300908clean:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300909 release_sock(parent);
Ville Tervob62f3282011-02-10 22:38:50 -0300910}
911
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300912static void l2cap_chan_ready(struct sock *sk)
913{
914 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
915 struct sock *parent = bt_sk(sk)->parent;
916
917 BT_DBG("sk %p, parent %p", sk, parent);
918
919 chan->conf_state = 0;
920 __clear_chan_timer(chan);
921
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300922 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300923 sk->sk_state_change(sk);
924
925 if (parent)
926 parent->sk_data_ready(parent, 0);
927}
928
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200929static void l2cap_conn_ready(struct l2cap_conn *conn)
930{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300931 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200932
933 BT_DBG("conn %p", conn);
934
Ville Tervob62f3282011-02-10 22:38:50 -0300935 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
936 l2cap_le_conn_ready(conn);
937
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -0300938 if (conn->hcon->out && conn->hcon->type == LE_LINK)
939 smp_conn_security(conn, conn->hcon->pending_sec_level);
940
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200941 rcu_read_lock();
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200942
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200943 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300944 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300945
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200946 bh_lock_sock(sk);
947
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300948 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300949 if (smp_conn_security(conn, chan->sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300950 l2cap_chan_ready(sk);
Ville Tervoacd7d372011-02-10 22:38:49 -0300951
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300952 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300953 __clear_chan_timer(chan);
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300954 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200955 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300956
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300957 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300958 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200959
960 bh_unlock_sock(sk);
961 }
962
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200963 rcu_read_unlock();
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200964}
965
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200966/* Notify sockets that we cannot guaranty reliability anymore */
967static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
968{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300969 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200970
971 BT_DBG("conn %p", conn);
972
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200973 rcu_read_lock();
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200974
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200975 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300976 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300977
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +0300978 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200979 sk->sk_err = err;
980 }
981
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200982 rcu_read_unlock();
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200983}
984
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -0200985static void l2cap_info_timeout(struct work_struct *work)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200986{
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -0200987 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
Gustavo F. Padovan030013d2011-12-20 10:57:28 -0200988 info_timer.work);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200989
Marcel Holtmann984947d2009-02-06 23:35:19 +0100990 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100991 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100992
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200993 l2cap_conn_start(conn);
994}
995
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300996static void l2cap_conn_del(struct hci_conn *hcon, int err)
997{
998 struct l2cap_conn *conn = hcon->l2cap_data;
999 struct l2cap_chan *chan, *l;
1000 struct sock *sk;
1001
1002 if (!conn)
1003 return;
1004
1005 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
1006
1007 kfree_skb(conn->rx_skb);
1008
1009 /* Kill channels */
1010 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
1011 sk = chan->sk;
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001012 lock_sock(sk);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001013 l2cap_chan_del(chan, err);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001014 release_sock(sk);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001015 chan->ops->close(chan->data);
1016 }
1017
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001018 hci_chan_del(conn->hchan);
1019
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001020 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
Ulisses Furquim371fd832011-12-21 20:02:36 -02001021 __cancel_delayed_work(&conn->info_timer);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001022
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001023 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) {
Ulisses Furquim371fd832011-12-21 20:02:36 -02001024 __cancel_delayed_work(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001025 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001026 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001027
1028 hcon->l2cap_data = NULL;
1029 kfree(conn);
1030}
1031
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001032static void security_timeout(struct work_struct *work)
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001033{
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001034 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1035 security_timer.work);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001036
1037 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1038}
1039
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1041{
Marcel Holtmann01394182006-07-03 10:02:46 +02001042 struct l2cap_conn *conn = hcon->l2cap_data;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001043 struct hci_chan *hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044
Marcel Holtmann01394182006-07-03 10:02:46 +02001045 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 return conn;
1047
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001048 hchan = hci_chan_create(hcon);
1049 if (!hchan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001052 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1053 if (!conn) {
1054 hci_chan_del(hchan);
1055 return NULL;
1056 }
1057
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 hcon->l2cap_data = conn;
1059 conn->hcon = hcon;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001060 conn->hchan = hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001062 BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
Marcel Holtmann01394182006-07-03 10:02:46 +02001063
Ville Tervoacd7d372011-02-10 22:38:49 -03001064 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1065 conn->mtu = hcon->hdev->le_mtu;
1066 else
1067 conn->mtu = hcon->hdev->acl_mtu;
1068
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 conn->src = &hcon->hdev->bdaddr;
1070 conn->dst = &hcon->dst;
1071
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001072 conn->feat_mask = 0;
1073
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001075
1076 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001078 if (hcon->type == LE_LINK)
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001079 INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001080 else
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02001081 INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
Dave Young45054dc2009-10-18 20:28:30 +00001082
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001083 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01001084
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 return conn;
1086}
1087
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089
1090/* Find socket with psm and source bdaddr.
1091 * Returns closest match.
1092 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001093static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001095 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001097 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001098
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001099 list_for_each_entry(c, &chan_list, global_l) {
1100 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001101
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03001102 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 continue;
1104
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001105 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001107 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001108 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001109 return c;
1110 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111
1112 /* Closest match */
1113 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001114 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 }
1116 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001118 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001119
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001120 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121}
1122
Johan Hedbergcbe8fed2012-01-08 22:51:16 +02001123int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001125 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 bdaddr_t *src = &bt_sk(sk)->src;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 struct l2cap_conn *conn;
1128 struct hci_conn *hcon;
1129 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001130 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001131 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001133 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001134 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001136 hdev = hci_get_route(dst, src);
1137 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 return -EHOSTUNREACH;
1139
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001140 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001142 lock_sock(sk);
1143
1144 /* PSM must be odd and lsb of upper byte must be 0 */
1145 if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
1146 chan->chan_type != L2CAP_CHAN_RAW) {
1147 err = -EINVAL;
1148 goto done;
1149 }
1150
1151 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
1152 err = -EINVAL;
1153 goto done;
1154 }
1155
1156 switch (chan->mode) {
1157 case L2CAP_MODE_BASIC:
1158 break;
1159 case L2CAP_MODE_ERTM:
1160 case L2CAP_MODE_STREAMING:
1161 if (!disable_ertm)
1162 break;
1163 /* fall through */
1164 default:
1165 err = -ENOTSUPP;
1166 goto done;
1167 }
1168
1169 switch (sk->sk_state) {
1170 case BT_CONNECT:
1171 case BT_CONNECT2:
1172 case BT_CONFIG:
1173 /* Already connecting */
1174 err = 0;
1175 goto done;
1176
1177 case BT_CONNECTED:
1178 /* Already connected */
1179 err = -EISCONN;
1180 goto done;
1181
1182 case BT_OPEN:
1183 case BT_BOUND:
1184 /* Can connect */
1185 break;
1186
1187 default:
1188 err = -EBADFD;
1189 goto done;
1190 }
1191
1192 /* Set destination address and psm */
Gustavo F. Padovan9219b2a2012-01-02 20:08:04 -02001193 bacpy(&bt_sk(sk)->dst, dst);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001194 chan->psm = psm;
1195 chan->dcid = cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001197 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001198
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001199 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001200 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001201 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001202 else
1203 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001204 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001205
Ville Tervo30e76272011-02-22 16:10:53 -03001206 if (IS_ERR(hcon)) {
1207 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001209 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
1211 conn = l2cap_conn_add(hcon, 0);
1212 if (!conn) {
1213 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001214 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 goto done;
1216 }
1217
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 /* Update source addr of the socket */
1219 bacpy(src, conn->src);
1220
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001221 l2cap_chan_add(conn, chan);
1222
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03001223 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001224 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225
1226 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001227 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001228 __clear_chan_timer(chan);
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001229 if (l2cap_chan_check_security(chan))
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03001230 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001231 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001232 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 }
1234
Ville Tervo30e76272011-02-22 16:10:53 -03001235 err = 0;
1236
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001238 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 hci_dev_put(hdev);
1240 return err;
1241}
1242
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001243int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001244{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001245 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001246 DECLARE_WAITQUEUE(wait, current);
1247 int err = 0;
1248 int timeo = HZ/5;
1249
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001250 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001251 set_current_state(TASK_INTERRUPTIBLE);
1252 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001253 if (!timeo)
1254 timeo = HZ/5;
1255
1256 if (signal_pending(current)) {
1257 err = sock_intr_errno(timeo);
1258 break;
1259 }
1260
1261 release_sock(sk);
1262 timeo = schedule_timeout(timeo);
1263 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001264 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001265
1266 err = sock_error(sk);
1267 if (err)
1268 break;
1269 }
1270 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001271 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001272 return err;
1273}
1274
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001275static void l2cap_monitor_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001276{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001277 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1278 monitor_timer.work);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001279 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001280
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001281 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001282
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001283 lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001284 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001285 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001286 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001287 return;
1288 }
1289
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001290 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001291 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001292
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001293 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001294 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001295}
1296
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001297static void l2cap_retrans_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001298{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001299 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1300 retrans_timer.work);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001301 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001302
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001303 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001304
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001305 lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001306 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001307 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001308
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001309 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001310
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001311 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001312 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001313}
1314
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001315static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001316{
1317 struct sk_buff *skb;
1318
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001319 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001320 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001321 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001322 break;
1323
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001324 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001325 kfree_skb(skb);
1326
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001327 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001328 }
1329
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001330 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001331 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001332}
1333
Szymon Janc67c9e842011-07-28 16:24:33 +02001334static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001335{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001336 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001337 u32 control;
1338 u16 fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001339
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001340 while ((skb = skb_dequeue(&chan->tx_q))) {
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001341 control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001342 control |= __set_txseq(chan, chan->next_tx_seq);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001343 __put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001344
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001345 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001346 fcs = crc16(0, (u8 *)skb->data,
1347 skb->len - L2CAP_FCS_SIZE);
1348 put_unaligned_le16(fcs,
1349 skb->data + skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001350 }
1351
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001352 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001353
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001354 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001355 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001356}
1357
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001358static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001359{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001360 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001361 u16 fcs;
1362 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001363
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001364 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001365 if (!skb)
1366 return;
1367
Szymon Jancd1726b62011-11-16 09:32:20 +01001368 while (bt_cb(skb)->tx_seq != tx_seq) {
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001369 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001370 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001371
Szymon Jancd1726b62011-11-16 09:32:20 +01001372 skb = skb_queue_next(&chan->tx_q, skb);
1373 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001374
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001375 if (chan->remote_max_tx &&
1376 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001377 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001378 return;
1379 }
1380
1381 tx_skb = skb_clone(skb, GFP_ATOMIC);
1382 bt_cb(skb)->retries++;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001383
1384 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001385 control &= __get_sar_mask(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001386
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001387 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001388 control |= __set_ctrl_final(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001389
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001390 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001391 control |= __set_txseq(chan, tx_seq);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001392
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001393 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001394
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001395 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001396 fcs = crc16(0, (u8 *)tx_skb->data,
1397 tx_skb->len - L2CAP_FCS_SIZE);
1398 put_unaligned_le16(fcs,
1399 tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001400 }
1401
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001402 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001403}
1404
Szymon Janc67c9e842011-07-28 16:24:33 +02001405static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001406{
1407 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001408 u16 fcs;
1409 u32 control;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001410 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001411
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03001412 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001413 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001414
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001415 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001416
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001417 if (chan->remote_max_tx &&
1418 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001419 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001420 break;
1421 }
1422
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001423 tx_skb = skb_clone(skb, GFP_ATOMIC);
1424
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001425 bt_cb(skb)->retries++;
1426
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001427 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001428 control &= __get_sar_mask(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001429
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001430 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001431 control |= __set_ctrl_final(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001432
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001433 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001434 control |= __set_txseq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001435
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001436 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001437
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001438 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001439 fcs = crc16(0, (u8 *)skb->data,
1440 tx_skb->len - L2CAP_FCS_SIZE);
1441 put_unaligned_le16(fcs, skb->data +
1442 tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001443 }
1444
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001445 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001446
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001447 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001448
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001449 bt_cb(skb)->tx_seq = chan->next_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001450
1451 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001452
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301453 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001454 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301455
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001456 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001457
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001458 if (skb_queue_is_last(&chan->tx_q, skb))
1459 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001460 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001461 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001462
1463 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001464 }
1465
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001466 return nsent;
1467}
1468
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001469static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001470{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001471 int ret;
1472
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001473 if (!skb_queue_empty(&chan->tx_q))
1474 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001475
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001476 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001477 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001478 return ret;
1479}
1480
Szymon Jancb17e73b2012-01-11 10:59:47 +01001481static void __l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001482{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001483 u32 control = 0;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001484
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001485 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001486
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001487 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001488 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001489 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001490 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001491 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001492 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001493
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001494 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001495 return;
1496
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001497 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001498 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001499}
1500
Szymon Jancb17e73b2012-01-11 10:59:47 +01001501static void l2cap_send_ack(struct l2cap_chan *chan)
1502{
1503 __clear_ack_timer(chan);
1504 __l2cap_send_ack(chan);
1505}
1506
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001507static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001508{
1509 struct srej_list *tail;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001510 u32 control;
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001511
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001512 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001513 control |= __set_ctrl_final(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001514
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001515 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001516 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001517
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001518 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001519}
1520
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001521static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001523 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001524 struct sk_buff **frag;
1525 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001527 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001528 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529
1530 sent += count;
1531 len -= count;
1532
1533 /* Continuation fragments (no L2CAP header) */
1534 frag = &skb_shinfo(skb)->frag_list;
1535 while (len) {
1536 count = min_t(unsigned int, conn->mtu, len);
1537
1538 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1539 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001540 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001541 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1542 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001544 (*frag)->priority = skb->priority;
1545
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 sent += count;
1547 len -= count;
1548
1549 frag = &(*frag)->next;
1550 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551
1552 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001553}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001555static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
1556 struct msghdr *msg, size_t len,
1557 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001558{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001559 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001560 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001561 struct sk_buff *skb;
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001562 int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001563 struct l2cap_hdr *lh;
1564
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001565 BT_DBG("sk %p len %d priority %u", sk, (int)len, priority);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001566
1567 count = min_t(unsigned int, (conn->mtu - hlen), len);
1568 skb = bt_skb_send_alloc(sk, count + hlen,
1569 msg->msg_flags & MSG_DONTWAIT, &err);
1570 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001571 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001572
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001573 skb->priority = priority;
1574
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001575 /* Create L2CAP header */
1576 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001577 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001578 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001579 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001580
1581 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1582 if (unlikely(err < 0)) {
1583 kfree_skb(skb);
1584 return ERR_PTR(err);
1585 }
1586 return skb;
1587}
1588
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001589static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
1590 struct msghdr *msg, size_t len,
1591 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001592{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001593 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001594 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001595 struct sk_buff *skb;
1596 int err, count, hlen = L2CAP_HDR_SIZE;
1597 struct l2cap_hdr *lh;
1598
1599 BT_DBG("sk %p len %d", sk, (int)len);
1600
1601 count = min_t(unsigned int, (conn->mtu - hlen), len);
1602 skb = bt_skb_send_alloc(sk, count + hlen,
1603 msg->msg_flags & MSG_DONTWAIT, &err);
1604 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001605 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001606
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001607 skb->priority = priority;
1608
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001609 /* Create L2CAP header */
1610 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001611 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001612 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1613
1614 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1615 if (unlikely(err < 0)) {
1616 kfree_skb(skb);
1617 return ERR_PTR(err);
1618 }
1619 return skb;
1620}
1621
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001622static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1623 struct msghdr *msg, size_t len,
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001624 u32 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001625{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001626 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001627 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001628 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001629 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001630 struct l2cap_hdr *lh;
1631
1632 BT_DBG("sk %p len %d", sk, (int)len);
1633
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001634 if (!conn)
1635 return ERR_PTR(-ENOTCONN);
1636
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001637 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1638 hlen = L2CAP_EXT_HDR_SIZE;
1639 else
1640 hlen = L2CAP_ENH_HDR_SIZE;
1641
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001642 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001643 hlen += L2CAP_SDULEN_SIZE;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001644
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001645 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001646 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001647
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001648 count = min_t(unsigned int, (conn->mtu - hlen), len);
1649 skb = bt_skb_send_alloc(sk, count + hlen,
1650 msg->msg_flags & MSG_DONTWAIT, &err);
1651 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001652 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001653
1654 /* Create L2CAP header */
1655 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001656 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001657 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001658
1659 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
1660
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001661 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001662 put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001663
1664 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1665 if (unlikely(err < 0)) {
1666 kfree_skb(skb);
1667 return ERR_PTR(err);
1668 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001669
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001670 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001671 put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001672
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001673 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001674 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675}
1676
Szymon Janc67c9e842011-07-28 16:24:33 +02001677static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001678{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001679 struct sk_buff *skb;
1680 struct sk_buff_head sar_queue;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001681 u32 control;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001682 size_t size = 0;
1683
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001684 skb_queue_head_init(&sar_queue);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001685 control = __set_ctrl_sar(chan, L2CAP_SAR_START);
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001686 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001687 if (IS_ERR(skb))
1688 return PTR_ERR(skb);
1689
1690 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001691 len -= chan->remote_mps;
1692 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001693
1694 while (len > 0) {
1695 size_t buflen;
1696
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001697 if (len > chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001698 control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001699 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001700 } else {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001701 control = __set_ctrl_sar(chan, L2CAP_SAR_END);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001702 buflen = len;
1703 }
1704
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001705 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001706 if (IS_ERR(skb)) {
1707 skb_queue_purge(&sar_queue);
1708 return PTR_ERR(skb);
1709 }
1710
1711 __skb_queue_tail(&sar_queue, skb);
1712 len -= buflen;
1713 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001714 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001715 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1716 if (chan->tx_send_head == NULL)
1717 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001718
1719 return size;
1720}
1721
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001722int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
1723 u32 priority)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001724{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001725 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001726 u32 control;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001727 int err;
1728
1729 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001730 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001731 skb = l2cap_create_connless_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001732 if (IS_ERR(skb))
1733 return PTR_ERR(skb);
1734
1735 l2cap_do_send(chan, skb);
1736 return len;
1737 }
1738
1739 switch (chan->mode) {
1740 case L2CAP_MODE_BASIC:
1741 /* Check outgoing MTU */
1742 if (len > chan->omtu)
1743 return -EMSGSIZE;
1744
1745 /* Create a basic PDU */
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001746 skb = l2cap_create_basic_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001747 if (IS_ERR(skb))
1748 return PTR_ERR(skb);
1749
1750 l2cap_do_send(chan, skb);
1751 err = len;
1752 break;
1753
1754 case L2CAP_MODE_ERTM:
1755 case L2CAP_MODE_STREAMING:
1756 /* Entire SDU fits into one PDU */
1757 if (len <= chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001758 control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001759 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1760 0);
1761 if (IS_ERR(skb))
1762 return PTR_ERR(skb);
1763
1764 __skb_queue_tail(&chan->tx_q, skb);
1765
1766 if (chan->tx_send_head == NULL)
1767 chan->tx_send_head = skb;
1768
1769 } else {
1770 /* Segment SDU into multiples PDUs */
1771 err = l2cap_sar_segment_sdu(chan, msg, len);
1772 if (err < 0)
1773 return err;
1774 }
1775
1776 if (chan->mode == L2CAP_MODE_STREAMING) {
1777 l2cap_streaming_send(chan);
1778 err = len;
1779 break;
1780 }
1781
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001782 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1783 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001784 err = len;
1785 break;
1786 }
1787
1788 err = l2cap_ertm_send(chan);
1789 if (err >= 0)
1790 err = len;
1791
1792 break;
1793
1794 default:
1795 BT_DBG("bad state %1.1x", chan->mode);
1796 err = -EBADFD;
1797 }
1798
1799 return err;
1800}
1801
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802/* Copy frame to all raw sockets on that connection */
1803static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1804{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001806 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807
1808 BT_DBG("conn %p", conn);
1809
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001810 rcu_read_lock();
1811
1812 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001813 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001814 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 continue;
1816
1817 /* Don't send frame to the socket it came from */
1818 if (skb->sk == sk)
1819 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001820 nskb = skb_clone(skb, GFP_ATOMIC);
1821 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 continue;
1823
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001824 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825 kfree_skb(nskb);
1826 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001827
1828 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829}
1830
1831/* ---- L2CAP signalling commands ---- */
1832static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1833 u8 code, u8 ident, u16 dlen, void *data)
1834{
1835 struct sk_buff *skb, **frag;
1836 struct l2cap_cmd_hdr *cmd;
1837 struct l2cap_hdr *lh;
1838 int len, count;
1839
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001840 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1841 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842
1843 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1844 count = min_t(unsigned int, conn->mtu, len);
1845
1846 skb = bt_skb_alloc(count, GFP_ATOMIC);
1847 if (!skb)
1848 return NULL;
1849
1850 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001851 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001852
1853 if (conn->hcon->type == LE_LINK)
1854 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1855 else
1856 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857
1858 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1859 cmd->code = code;
1860 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001861 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862
1863 if (dlen) {
1864 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1865 memcpy(skb_put(skb, count), data, count);
1866 data += count;
1867 }
1868
1869 len -= skb->len;
1870
1871 /* Continuation fragments (no L2CAP header) */
1872 frag = &skb_shinfo(skb)->frag_list;
1873 while (len) {
1874 count = min_t(unsigned int, conn->mtu, len);
1875
1876 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1877 if (!*frag)
1878 goto fail;
1879
1880 memcpy(skb_put(*frag, count), data, count);
1881
1882 len -= count;
1883 data += count;
1884
1885 frag = &(*frag)->next;
1886 }
1887
1888 return skb;
1889
1890fail:
1891 kfree_skb(skb);
1892 return NULL;
1893}
1894
1895static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1896{
1897 struct l2cap_conf_opt *opt = *ptr;
1898 int len;
1899
1900 len = L2CAP_CONF_OPT_SIZE + opt->len;
1901 *ptr += len;
1902
1903 *type = opt->type;
1904 *olen = opt->len;
1905
1906 switch (opt->len) {
1907 case 1:
1908 *val = *((u8 *) opt->val);
1909 break;
1910
1911 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001912 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 break;
1914
1915 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001916 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 break;
1918
1919 default:
1920 *val = (unsigned long) opt->val;
1921 break;
1922 }
1923
1924 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1925 return len;
1926}
1927
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1929{
1930 struct l2cap_conf_opt *opt = *ptr;
1931
1932 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1933
1934 opt->type = type;
1935 opt->len = len;
1936
1937 switch (len) {
1938 case 1:
1939 *((u8 *) opt->val) = val;
1940 break;
1941
1942 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001943 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 break;
1945
1946 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001947 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948 break;
1949
1950 default:
1951 memcpy(opt->val, (void *) val, len);
1952 break;
1953 }
1954
1955 *ptr += L2CAP_CONF_OPT_SIZE + len;
1956}
1957
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001958static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
1959{
1960 struct l2cap_conf_efs efs;
1961
Szymon Janc1ec918c2011-11-16 09:32:21 +01001962 switch (chan->mode) {
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001963 case L2CAP_MODE_ERTM:
1964 efs.id = chan->local_id;
1965 efs.stype = chan->local_stype;
1966 efs.msdu = cpu_to_le16(chan->local_msdu);
1967 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1968 efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
1969 efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
1970 break;
1971
1972 case L2CAP_MODE_STREAMING:
1973 efs.id = 1;
1974 efs.stype = L2CAP_SERV_BESTEFFORT;
1975 efs.msdu = cpu_to_le16(chan->local_msdu);
1976 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1977 efs.acc_lat = 0;
1978 efs.flush_to = 0;
1979 break;
1980
1981 default:
1982 return;
1983 }
1984
1985 l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
1986 (unsigned long) &efs);
1987}
1988
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001989static void l2cap_ack_timeout(struct work_struct *work)
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001990{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001991 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1992 ack_timer.work);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001993
Gustavo F. Padovan2fb9b3d2011-12-22 16:56:05 -02001994 BT_DBG("chan %p", chan);
1995
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001996 lock_sock(chan->sk);
Szymon Jancb17e73b2012-01-11 10:59:47 +01001997 __l2cap_send_ack(chan);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001998 release_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001999}
2000
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002001static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002002{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002003 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002004 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002005 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002006 chan->num_acked = 0;
2007 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002008
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002009 INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2010 INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2011 INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002012
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002013 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002014
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03002015 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002016}
2017
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002018static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2019{
2020 switch (mode) {
2021 case L2CAP_MODE_STREAMING:
2022 case L2CAP_MODE_ERTM:
2023 if (l2cap_mode_supported(mode, remote_feat_mask))
2024 return mode;
2025 /* fall through */
2026 default:
2027 return L2CAP_MODE_BASIC;
2028 }
2029}
2030
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002031static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
2032{
2033 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
2034}
2035
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002036static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2037{
2038 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2039}
2040
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002041static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
2042{
2043 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002044 __l2cap_ews_supported(chan)) {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002045 /* use extended control field */
2046 set_bit(FLAG_EXT_CTRL, &chan->flags);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002047 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2048 } else {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002049 chan->tx_win = min_t(u16, chan->tx_win,
2050 L2CAP_DEFAULT_TX_WINDOW);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002051 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2052 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002053}
2054
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002055static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002058 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 void *ptr = req->data;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002060 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002062 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002064 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002065 goto done;
2066
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002067 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002068 case L2CAP_MODE_STREAMING:
2069 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002070 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002071 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002072
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002073 if (__l2cap_efs_supported(chan))
2074 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2075
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002076 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002077 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002078 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002079 break;
2080 }
2081
2082done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002083 if (chan->imtu != L2CAP_DEFAULT_MTU)
2084 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002085
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002086 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002087 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002088 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2089 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002090 break;
2091
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002092 rfc.mode = L2CAP_MODE_BASIC;
2093 rfc.txwin_size = 0;
2094 rfc.max_transmit = 0;
2095 rfc.retrans_timeout = 0;
2096 rfc.monitor_timeout = 0;
2097 rfc.max_pdu_size = 0;
2098
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002099 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2100 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002101 break;
2102
2103 case L2CAP_MODE_ERTM:
2104 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002105 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002106 rfc.retrans_timeout = 0;
2107 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002108
2109 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2110 L2CAP_EXT_HDR_SIZE -
2111 L2CAP_SDULEN_SIZE -
2112 L2CAP_FCS_SIZE);
2113 rfc.max_pdu_size = cpu_to_le16(size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002114
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002115 l2cap_txwin_setup(chan);
2116
2117 rfc.txwin_size = min_t(u16, chan->tx_win,
2118 L2CAP_DEFAULT_TX_WINDOW);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002119
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002120 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2121 (unsigned long) &rfc);
2122
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002123 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2124 l2cap_add_opt_efs(&ptr, chan);
2125
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002126 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002127 break;
2128
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002129 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002130 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002131 chan->fcs = L2CAP_FCS_NONE;
2132 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002133 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002134
2135 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2136 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2137 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002138 break;
2139
2140 case L2CAP_MODE_STREAMING:
2141 rfc.mode = L2CAP_MODE_STREAMING;
2142 rfc.txwin_size = 0;
2143 rfc.max_transmit = 0;
2144 rfc.retrans_timeout = 0;
2145 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002146
2147 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2148 L2CAP_EXT_HDR_SIZE -
2149 L2CAP_SDULEN_SIZE -
2150 L2CAP_FCS_SIZE);
2151 rfc.max_pdu_size = cpu_to_le16(size);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002152
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002153 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2154 (unsigned long) &rfc);
2155
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002156 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2157 l2cap_add_opt_efs(&ptr, chan);
2158
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002159 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002160 break;
2161
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002162 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002163 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002164 chan->fcs = L2CAP_FCS_NONE;
2165 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002166 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002167 break;
2168 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002170 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002171 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172
2173 return ptr - data;
2174}
2175
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002176static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002178 struct l2cap_conf_rsp *rsp = data;
2179 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002180 void *req = chan->conf_req;
2181 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002182 int type, hint, olen;
2183 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002184 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002185 struct l2cap_conf_efs efs;
2186 u8 remote_efs = 0;
Marcel Holtmann861d6882007-10-20 13:37:06 +02002187 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002188 u16 result = L2CAP_CONF_SUCCESS;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002189 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002191 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002192
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002193 while (len >= L2CAP_CONF_OPT_SIZE) {
2194 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002196 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002197 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002198
2199 switch (type) {
2200 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002201 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002202 break;
2203
2204 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002205 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002206 break;
2207
2208 case L2CAP_CONF_QOS:
2209 break;
2210
Marcel Holtmann6464f352007-10-20 13:39:51 +02002211 case L2CAP_CONF_RFC:
2212 if (olen == sizeof(rfc))
2213 memcpy(&rfc, (void *) val, olen);
2214 break;
2215
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002216 case L2CAP_CONF_FCS:
2217 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002218 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002219 break;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002220
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002221 case L2CAP_CONF_EFS:
2222 remote_efs = 1;
2223 if (olen == sizeof(efs))
2224 memcpy(&efs, (void *) val, olen);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002225 break;
2226
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002227 case L2CAP_CONF_EWS:
2228 if (!enable_hs)
2229 return -ECONNREFUSED;
2230
2231 set_bit(FLAG_EXT_CTRL, &chan->flags);
2232 set_bit(CONF_EWS_RECV, &chan->conf_state);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002233 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002234 chan->remote_tx_win = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002235 break;
2236
2237 default:
2238 if (hint)
2239 break;
2240
2241 result = L2CAP_CONF_UNKNOWN;
2242 *((u8 *) ptr++) = type;
2243 break;
2244 }
2245 }
2246
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002247 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002248 goto done;
2249
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002250 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002251 case L2CAP_MODE_STREAMING:
2252 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002253 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002254 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002255 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002256 break;
2257 }
2258
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002259 if (remote_efs) {
2260 if (__l2cap_efs_supported(chan))
2261 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2262 else
2263 return -ECONNREFUSED;
2264 }
2265
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002266 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002267 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002268
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002269 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002270 }
2271
2272done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002273 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002274 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002275 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002276
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002277 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002278 return -ECONNREFUSED;
2279
2280 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2281 sizeof(rfc), (unsigned long) &rfc);
2282 }
2283
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002284 if (result == L2CAP_CONF_SUCCESS) {
2285 /* Configure output options and let the other side know
2286 * which ones we don't like. */
2287
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002288 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2289 result = L2CAP_CONF_UNACCEPT;
2290 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002291 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002292 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002293 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002294 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002295
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002296 if (remote_efs) {
2297 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2298 efs.stype != L2CAP_SERV_NOTRAFIC &&
2299 efs.stype != chan->local_stype) {
2300
2301 result = L2CAP_CONF_UNACCEPT;
2302
2303 if (chan->num_conf_req >= 1)
2304 return -ECONNREFUSED;
2305
2306 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002307 sizeof(efs),
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002308 (unsigned long) &efs);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002309 } else {
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002310 /* Send PENDING Conf Rsp */
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002311 result = L2CAP_CONF_PENDING;
2312 set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002313 }
2314 }
2315
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002316 switch (rfc.mode) {
2317 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002318 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002319 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002320 break;
2321
2322 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002323 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2324 chan->remote_tx_win = rfc.txwin_size;
2325 else
2326 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2327
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002328 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002329
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002330 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2331 chan->conn->mtu -
2332 L2CAP_EXT_HDR_SIZE -
2333 L2CAP_SDULEN_SIZE -
2334 L2CAP_FCS_SIZE);
2335 rfc.max_pdu_size = cpu_to_le16(size);
2336 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002337
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002338 rfc.retrans_timeout =
2339 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2340 rfc.monitor_timeout =
2341 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002342
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002343 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002344
2345 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2346 sizeof(rfc), (unsigned long) &rfc);
2347
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002348 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2349 chan->remote_id = efs.id;
2350 chan->remote_stype = efs.stype;
2351 chan->remote_msdu = le16_to_cpu(efs.msdu);
2352 chan->remote_flush_to =
2353 le32_to_cpu(efs.flush_to);
2354 chan->remote_acc_lat =
2355 le32_to_cpu(efs.acc_lat);
2356 chan->remote_sdu_itime =
2357 le32_to_cpu(efs.sdu_itime);
2358 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2359 sizeof(efs), (unsigned long) &efs);
2360 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002361 break;
2362
2363 case L2CAP_MODE_STREAMING:
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002364 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2365 chan->conn->mtu -
2366 L2CAP_EXT_HDR_SIZE -
2367 L2CAP_SDULEN_SIZE -
2368 L2CAP_FCS_SIZE);
2369 rfc.max_pdu_size = cpu_to_le16(size);
2370 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002371
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002372 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002373
2374 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2375 sizeof(rfc), (unsigned long) &rfc);
2376
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002377 break;
2378
2379 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002380 result = L2CAP_CONF_UNACCEPT;
2381
2382 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002383 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002384 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002385
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002386 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002387 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002388 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002389 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002390 rsp->result = cpu_to_le16(result);
2391 rsp->flags = cpu_to_le16(0x0000);
2392
2393 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394}
2395
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002396static 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 -03002397{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002398 struct l2cap_conf_req *req = data;
2399 void *ptr = req->data;
2400 int type, olen;
2401 unsigned long val;
Mat Martineau36e999a2011-12-08 17:23:21 -08002402 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002403 struct l2cap_conf_efs efs;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002404
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002405 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002406
2407 while (len >= L2CAP_CONF_OPT_SIZE) {
2408 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2409
2410 switch (type) {
2411 case L2CAP_CONF_MTU:
2412 if (val < L2CAP_DEFAULT_MIN_MTU) {
2413 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002414 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002415 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002416 chan->imtu = val;
2417 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002418 break;
2419
2420 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002421 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002422 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002423 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002424 break;
2425
2426 case L2CAP_CONF_RFC:
2427 if (olen == sizeof(rfc))
2428 memcpy(&rfc, (void *)val, olen);
2429
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002430 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002431 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002432 return -ECONNREFUSED;
2433
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002434 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002435
2436 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2437 sizeof(rfc), (unsigned long) &rfc);
2438 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002439
2440 case L2CAP_CONF_EWS:
2441 chan->tx_win = min_t(u16, val,
2442 L2CAP_DEFAULT_EXT_WINDOW);
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002443 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2444 chan->tx_win);
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002445 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002446
2447 case L2CAP_CONF_EFS:
2448 if (olen == sizeof(efs))
2449 memcpy(&efs, (void *)val, olen);
2450
2451 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2452 efs.stype != L2CAP_SERV_NOTRAFIC &&
2453 efs.stype != chan->local_stype)
2454 return -ECONNREFUSED;
2455
2456 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2457 sizeof(efs), (unsigned long) &efs);
2458 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002459 }
2460 }
2461
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002462 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002463 return -ECONNREFUSED;
2464
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002465 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002466
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002467 if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002468 switch (rfc.mode) {
2469 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002470 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2471 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2472 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002473
2474 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2475 chan->local_msdu = le16_to_cpu(efs.msdu);
2476 chan->local_sdu_itime =
2477 le32_to_cpu(efs.sdu_itime);
2478 chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
2479 chan->local_flush_to =
2480 le32_to_cpu(efs.flush_to);
2481 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002482 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002483
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002484 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002485 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002486 }
2487 }
2488
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002489 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002490 req->flags = cpu_to_le16(0x0000);
2491
2492 return ptr - data;
2493}
2494
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002495static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496{
2497 struct l2cap_conf_rsp *rsp = data;
2498 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002500 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002502 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002503 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002504 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505
2506 return ptr - data;
2507}
2508
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002509void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002510{
2511 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002512 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002513 u8 buf[128];
2514
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002515 rsp.scid = cpu_to_le16(chan->dcid);
2516 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002517 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2518 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2519 l2cap_send_cmd(conn, chan->ident,
2520 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2521
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002522 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002523 return;
2524
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002525 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2526 l2cap_build_conf_req(chan, buf), buf);
2527 chan->num_conf_req++;
2528}
2529
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002530static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002531{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002532 int type, olen;
2533 unsigned long val;
2534 struct l2cap_conf_rfc rfc;
2535
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002536 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002537
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002538 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002539 return;
2540
2541 while (len >= L2CAP_CONF_OPT_SIZE) {
2542 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2543
2544 switch (type) {
2545 case L2CAP_CONF_RFC:
2546 if (olen == sizeof(rfc))
2547 memcpy(&rfc, (void *)val, olen);
2548 goto done;
2549 }
2550 }
2551
Mat Martineau36e999a2011-12-08 17:23:21 -08002552 /* Use sane default values in case a misbehaving remote device
2553 * did not send an RFC option.
2554 */
2555 rfc.mode = chan->mode;
2556 rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
2557 rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
2558 rfc.max_pdu_size = cpu_to_le16(chan->imtu);
2559
2560 BT_ERR("Expected RFC option was not found, using defaults");
2561
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002562done:
2563 switch (rfc.mode) {
2564 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002565 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2566 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2567 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002568 break;
2569 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002570 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002571 }
2572}
2573
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002574static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2575{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002576 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002577
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002578 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002579 return 0;
2580
2581 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2582 cmd->ident == conn->info_ident) {
Ulisses Furquim371fd832011-12-21 20:02:36 -02002583 __cancel_delayed_work(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002584
2585 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002586 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002587
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002588 l2cap_conn_start(conn);
2589 }
2590
2591 return 0;
2592}
2593
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2595{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2597 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002598 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002599 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002600 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601
2602 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002603 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604
2605 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2606
2607 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002608 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2609 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610 result = L2CAP_CR_BAD_PSM;
2611 goto sendresp;
2612 }
2613
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002614 parent = pchan->sk;
2615
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002616 lock_sock(parent);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002617
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002618 /* Check if the ACL is secure enough (if not SDP) */
2619 if (psm != cpu_to_le16(0x0001) &&
2620 !hci_conn_check_link_mode(conn->hcon)) {
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002621 conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002622 result = L2CAP_CR_SEC_BLOCK;
2623 goto response;
2624 }
2625
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626 result = L2CAP_CR_NO_MEM;
2627
2628 /* Check for backlog size */
2629 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002630 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631 goto response;
2632 }
2633
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002634 chan = pchan->ops->new_connection(pchan->data);
2635 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 goto response;
2637
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002638 sk = chan->sk;
2639
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002641 if (__l2cap_get_chan_by_dcid(conn, scid)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002643 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644 goto response;
2645 }
2646
2647 hci_conn_hold(conn->hcon);
2648
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649 bacpy(&bt_sk(sk)->src, conn->src);
2650 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002651 chan->psm = psm;
2652 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002654 bt_accept_enqueue(parent, sk);
2655
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02002656 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002657
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002658 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002660 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002662 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663
Marcel Holtmann984947d2009-02-06 23:35:19 +01002664 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02002665 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002666 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002667 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002668 result = L2CAP_CR_PEND;
2669 status = L2CAP_CS_AUTHOR_PEND;
2670 parent->sk_data_ready(parent, 0);
2671 } else {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002672 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002673 result = L2CAP_CR_SUCCESS;
2674 status = L2CAP_CS_NO_INFO;
2675 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002676 } else {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002677 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002678 result = L2CAP_CR_PEND;
2679 status = L2CAP_CS_AUTHEN_PEND;
2680 }
2681 } else {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002682 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002683 result = L2CAP_CR_PEND;
2684 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685 }
2686
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687response:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002688 release_sock(parent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689
2690sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002691 rsp.scid = cpu_to_le16(scid);
2692 rsp.dcid = cpu_to_le16(dcid);
2693 rsp.result = cpu_to_le16(result);
2694 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002696
2697 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2698 struct l2cap_info_req info;
2699 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2700
2701 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2702 conn->info_ident = l2cap_get_ident(conn);
2703
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02002704 schedule_delayed_work(&conn->info_timer,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002705 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2706
2707 l2cap_send_cmd(conn, conn->info_ident,
2708 L2CAP_INFO_REQ, sizeof(info), &info);
2709 }
2710
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002711 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002712 result == L2CAP_CR_SUCCESS) {
2713 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002714 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002715 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002716 l2cap_build_conf_req(chan, buf), buf);
2717 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002718 }
2719
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720 return 0;
2721}
2722
2723static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2724{
2725 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2726 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002727 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 struct sock *sk;
2729 u8 req[128];
2730
2731 scid = __le16_to_cpu(rsp->scid);
2732 dcid = __le16_to_cpu(rsp->dcid);
2733 result = __le16_to_cpu(rsp->result);
2734 status = __le16_to_cpu(rsp->status);
2735
2736 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2737
2738 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002739 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002740 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002741 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002743 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002744 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002745 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746 }
2747
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002748 sk = chan->sk;
2749
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750 switch (result) {
2751 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002752 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002753 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002754 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002755 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002756
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002757 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002758 break;
2759
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002761 l2cap_build_conf_req(chan, req), req);
2762 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763 break;
2764
2765 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002766 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 break;
2768
2769 default:
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002770 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 break;
2772 }
2773
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002774 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775 return 0;
2776}
2777
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002778static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002779{
2780 /* FCS is enabled only in ERTM or streaming mode, if one or both
2781 * sides request it.
2782 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002783 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002784 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002785 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002786 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002787}
2788
Al Viro88219a02007-07-29 00:17:25 -07002789static 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 -07002790{
2791 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2792 u16 dcid, flags;
2793 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002794 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002796 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797
2798 dcid = __le16_to_cpu(req->dcid);
2799 flags = __le16_to_cpu(req->flags);
2800
2801 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2802
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002803 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002804 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805 return -ENOENT;
2806
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002807 sk = chan->sk;
2808
David S. Miller033b1142011-07-21 13:38:42 -07002809 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002810 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002811
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002812 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2813 rej.scid = cpu_to_le16(chan->scid);
2814 rej.dcid = cpu_to_le16(chan->dcid);
2815
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002816 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2817 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002818 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002819 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002820
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002821 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002822 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002823 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002824 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002825 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002826 L2CAP_CONF_REJECT, flags), rsp);
2827 goto unlock;
2828 }
2829
2830 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002831 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2832 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833
2834 if (flags & 0x0001) {
2835 /* Incomplete config. Send empty response. */
2836 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_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002839 goto unlock;
2840 }
2841
2842 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002843 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002844 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002845 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002847 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002848
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002849 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002850 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002851
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002852 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002853 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002854
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002855 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002856 goto unlock;
2857
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002858 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002859 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002860
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002861 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002862
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002863 chan->next_tx_seq = 0;
2864 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002865 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002866 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002867 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002868
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002870 goto unlock;
2871 }
2872
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002873 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002874 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002876 l2cap_build_conf_req(chan, buf), buf);
2877 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002878 }
2879
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002880 /* Got Conf Rsp PENDING from remote side and asume we sent
2881 Conf Rsp PENDING in the code above */
2882 if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
2883 test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2884
2885 /* check compatibility */
2886
2887 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2888 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2889
2890 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002891 l2cap_build_conf_rsp(chan, rsp,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002892 L2CAP_CONF_SUCCESS, 0x0000), rsp);
2893 }
2894
Linus Torvalds1da177e2005-04-16 15:20:36 -07002895unlock:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002896 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897 return 0;
2898}
2899
2900static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2901{
2902 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2903 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002904 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002906 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002907
2908 scid = __le16_to_cpu(rsp->scid);
2909 flags = __le16_to_cpu(rsp->flags);
2910 result = __le16_to_cpu(rsp->result);
2911
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002912 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2913 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002915 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002916 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917 return 0;
2918
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002919 sk = chan->sk;
2920
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921 switch (result) {
2922 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002923 l2cap_conf_rfc_get(chan, rsp->data, len);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002924 clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925 break;
2926
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002927 case L2CAP_CONF_PENDING:
2928 set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
2929
2930 if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2931 char buf[64];
2932
2933 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2934 buf, &result);
2935 if (len < 0) {
2936 l2cap_send_disconn_req(conn, chan, ECONNRESET);
2937 goto done;
2938 }
2939
2940 /* check compatibility */
2941
2942 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2943 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2944
2945 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002946 l2cap_build_conf_rsp(chan, buf,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002947 L2CAP_CONF_SUCCESS, 0x0000), buf);
2948 }
2949 goto done;
2950
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002952 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002953 char req[64];
2954
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002955 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002956 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002957 goto done;
2958 }
2959
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002960 /* throw out any old stored conf requests */
2961 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002962 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2963 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002964 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002965 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002966 goto done;
2967 }
2968
2969 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2970 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002971 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002972 if (result != L2CAP_CONF_SUCCESS)
2973 goto done;
2974 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975 }
2976
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002977 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002978 sk->sk_err = ECONNRESET;
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01002979 __set_chan_timer(chan,
2980 msecs_to_jiffies(L2CAP_DISC_REJ_TIMEOUT));
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002981 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002982 goto done;
2983 }
2984
2985 if (flags & 0x01)
2986 goto done;
2987
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002988 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002990 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002991 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002992
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002993 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002994 chan->next_tx_seq = 0;
2995 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002996 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002997 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002998 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002999
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000 l2cap_chan_ready(sk);
3001 }
3002
3003done:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003004 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005 return 0;
3006}
3007
3008static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3009{
3010 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3011 struct l2cap_disconn_rsp rsp;
3012 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003013 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014 struct sock *sk;
3015
3016 scid = __le16_to_cpu(req->scid);
3017 dcid = __le16_to_cpu(req->dcid);
3018
3019 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3020
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003021 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003022 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023 return 0;
3024
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003025 sk = chan->sk;
3026
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003027 rsp.dcid = cpu_to_le16(chan->scid);
3028 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3030
3031 sk->sk_shutdown = SHUTDOWN_MASK;
3032
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003033 l2cap_chan_del(chan, ECONNRESET);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003034 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003036 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037 return 0;
3038}
3039
3040static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3041{
3042 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3043 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003044 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045 struct sock *sk;
3046
3047 scid = __le16_to_cpu(rsp->scid);
3048 dcid = __le16_to_cpu(rsp->dcid);
3049
3050 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3051
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003052 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003053 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054 return 0;
3055
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003056 sk = chan->sk;
3057
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003058 l2cap_chan_del(chan, 0);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003059 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003060
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003061 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062 return 0;
3063}
3064
3065static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3066{
3067 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003068 u16 type;
3069
3070 type = __le16_to_cpu(req->type);
3071
3072 BT_DBG("type 0x%4.4x", type);
3073
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003074 if (type == L2CAP_IT_FEAT_MASK) {
3075 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003076 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003077 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3078 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3079 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003080 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003081 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3082 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003083 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003084 feat_mask |= L2CAP_FEAT_EXT_FLOW
3085 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003086
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003087 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003088 l2cap_send_cmd(conn, cmd->ident,
3089 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003090 } else if (type == L2CAP_IT_FIXED_CHAN) {
3091 u8 buf[12];
3092 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
Mat Martineau50a147c2011-11-02 16:18:34 -07003093
3094 if (enable_hs)
3095 l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
3096 else
3097 l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
3098
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003099 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3100 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003101 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003102 l2cap_send_cmd(conn, cmd->ident,
3103 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003104 } else {
3105 struct l2cap_info_rsp rsp;
3106 rsp.type = cpu_to_le16(type);
3107 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3108 l2cap_send_cmd(conn, cmd->ident,
3109 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3110 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111
3112 return 0;
3113}
3114
3115static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3116{
3117 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3118 u16 type, result;
3119
3120 type = __le16_to_cpu(rsp->type);
3121 result = __le16_to_cpu(rsp->result);
3122
3123 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3124
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003125 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3126 if (cmd->ident != conn->info_ident ||
3127 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3128 return 0;
3129
Ulisses Furquim371fd832011-12-21 20:02:36 -02003130 __cancel_delayed_work(&conn->info_timer);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003131
Ville Tervoadb08ed2010-08-04 09:43:33 +03003132 if (result != L2CAP_IR_SUCCESS) {
3133 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3134 conn->info_ident = 0;
3135
3136 l2cap_conn_start(conn);
3137
3138 return 0;
3139 }
3140
Marcel Holtmann984947d2009-02-06 23:35:19 +01003141 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003142 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003143
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003144 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003145 struct l2cap_info_req req;
3146 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3147
3148 conn->info_ident = l2cap_get_ident(conn);
3149
3150 l2cap_send_cmd(conn, conn->info_ident,
3151 L2CAP_INFO_REQ, sizeof(req), &req);
3152 } else {
3153 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3154 conn->info_ident = 0;
3155
3156 l2cap_conn_start(conn);
3157 }
3158 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003159 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003160 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003161
3162 l2cap_conn_start(conn);
3163 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003164
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165 return 0;
3166}
3167
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003168static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3169 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3170 void *data)
3171{
3172 struct l2cap_create_chan_req *req = data;
3173 struct l2cap_create_chan_rsp rsp;
3174 u16 psm, scid;
3175
3176 if (cmd_len != sizeof(*req))
3177 return -EPROTO;
3178
3179 if (!enable_hs)
3180 return -EINVAL;
3181
3182 psm = le16_to_cpu(req->psm);
3183 scid = le16_to_cpu(req->scid);
3184
3185 BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3186
3187 /* Placeholder: Always reject */
3188 rsp.dcid = 0;
3189 rsp.scid = cpu_to_le16(scid);
3190 rsp.result = L2CAP_CR_NO_MEM;
3191 rsp.status = L2CAP_CS_NO_INFO;
3192
3193 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3194 sizeof(rsp), &rsp);
3195
3196 return 0;
3197}
3198
3199static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3200 struct l2cap_cmd_hdr *cmd, void *data)
3201{
3202 BT_DBG("conn %p", conn);
3203
3204 return l2cap_connect_rsp(conn, cmd, data);
3205}
3206
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003207static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
3208 u16 icid, u16 result)
3209{
3210 struct l2cap_move_chan_rsp rsp;
3211
3212 BT_DBG("icid %d, result %d", icid, result);
3213
3214 rsp.icid = cpu_to_le16(icid);
3215 rsp.result = cpu_to_le16(result);
3216
3217 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
3218}
3219
3220static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
3221 struct l2cap_chan *chan, u16 icid, u16 result)
3222{
3223 struct l2cap_move_chan_cfm cfm;
3224 u8 ident;
3225
3226 BT_DBG("icid %d, result %d", icid, result);
3227
3228 ident = l2cap_get_ident(conn);
3229 if (chan)
3230 chan->ident = ident;
3231
3232 cfm.icid = cpu_to_le16(icid);
3233 cfm.result = cpu_to_le16(result);
3234
3235 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
3236}
3237
3238static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
3239 u16 icid)
3240{
3241 struct l2cap_move_chan_cfm_rsp rsp;
3242
3243 BT_DBG("icid %d", icid);
3244
3245 rsp.icid = cpu_to_le16(icid);
3246 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
3247}
3248
3249static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
3250 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3251{
3252 struct l2cap_move_chan_req *req = data;
3253 u16 icid = 0;
3254 u16 result = L2CAP_MR_NOT_ALLOWED;
3255
3256 if (cmd_len != sizeof(*req))
3257 return -EPROTO;
3258
3259 icid = le16_to_cpu(req->icid);
3260
3261 BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
3262
3263 if (!enable_hs)
3264 return -EINVAL;
3265
3266 /* Placeholder: Always refuse */
3267 l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
3268
3269 return 0;
3270}
3271
3272static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
3273 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3274{
3275 struct l2cap_move_chan_rsp *rsp = data;
3276 u16 icid, result;
3277
3278 if (cmd_len != sizeof(*rsp))
3279 return -EPROTO;
3280
3281 icid = le16_to_cpu(rsp->icid);
3282 result = le16_to_cpu(rsp->result);
3283
3284 BT_DBG("icid %d, result %d", icid, result);
3285
3286 /* Placeholder: Always unconfirmed */
3287 l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
3288
3289 return 0;
3290}
3291
3292static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
3293 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3294{
3295 struct l2cap_move_chan_cfm *cfm = data;
3296 u16 icid, result;
3297
3298 if (cmd_len != sizeof(*cfm))
3299 return -EPROTO;
3300
3301 icid = le16_to_cpu(cfm->icid);
3302 result = le16_to_cpu(cfm->result);
3303
3304 BT_DBG("icid %d, result %d", icid, result);
3305
3306 l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
3307
3308 return 0;
3309}
3310
3311static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
3312 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3313{
3314 struct l2cap_move_chan_cfm_rsp *rsp = data;
3315 u16 icid;
3316
3317 if (cmd_len != sizeof(*rsp))
3318 return -EPROTO;
3319
3320 icid = le16_to_cpu(rsp->icid);
3321
3322 BT_DBG("icid %d", icid);
3323
3324 return 0;
3325}
3326
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003327static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02003328 u16 to_multiplier)
3329{
3330 u16 max_latency;
3331
3332 if (min > max || min < 6 || max > 3200)
3333 return -EINVAL;
3334
3335 if (to_multiplier < 10 || to_multiplier > 3200)
3336 return -EINVAL;
3337
3338 if (max >= to_multiplier * 8)
3339 return -EINVAL;
3340
3341 max_latency = (to_multiplier * 8 / max) - 1;
3342 if (latency > 499 || latency > max_latency)
3343 return -EINVAL;
3344
3345 return 0;
3346}
3347
3348static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3349 struct l2cap_cmd_hdr *cmd, u8 *data)
3350{
3351 struct hci_conn *hcon = conn->hcon;
3352 struct l2cap_conn_param_update_req *req;
3353 struct l2cap_conn_param_update_rsp rsp;
3354 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003355 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02003356
3357 if (!(hcon->link_mode & HCI_LM_MASTER))
3358 return -EINVAL;
3359
3360 cmd_len = __le16_to_cpu(cmd->len);
3361 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3362 return -EPROTO;
3363
3364 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003365 min = __le16_to_cpu(req->min);
3366 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02003367 latency = __le16_to_cpu(req->latency);
3368 to_multiplier = __le16_to_cpu(req->to_multiplier);
3369
3370 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3371 min, max, latency, to_multiplier);
3372
3373 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003374
3375 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
3376 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02003377 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3378 else
3379 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3380
3381 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3382 sizeof(rsp), &rsp);
3383
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003384 if (!err)
3385 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
3386
Claudio Takahaside731152011-02-11 19:28:55 -02003387 return 0;
3388}
3389
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003390static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
3391 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
3392{
3393 int err = 0;
3394
3395 switch (cmd->code) {
3396 case L2CAP_COMMAND_REJ:
3397 l2cap_command_rej(conn, cmd, data);
3398 break;
3399
3400 case L2CAP_CONN_REQ:
3401 err = l2cap_connect_req(conn, cmd, data);
3402 break;
3403
3404 case L2CAP_CONN_RSP:
3405 err = l2cap_connect_rsp(conn, cmd, data);
3406 break;
3407
3408 case L2CAP_CONF_REQ:
3409 err = l2cap_config_req(conn, cmd, cmd_len, data);
3410 break;
3411
3412 case L2CAP_CONF_RSP:
3413 err = l2cap_config_rsp(conn, cmd, data);
3414 break;
3415
3416 case L2CAP_DISCONN_REQ:
3417 err = l2cap_disconnect_req(conn, cmd, data);
3418 break;
3419
3420 case L2CAP_DISCONN_RSP:
3421 err = l2cap_disconnect_rsp(conn, cmd, data);
3422 break;
3423
3424 case L2CAP_ECHO_REQ:
3425 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3426 break;
3427
3428 case L2CAP_ECHO_RSP:
3429 break;
3430
3431 case L2CAP_INFO_REQ:
3432 err = l2cap_information_req(conn, cmd, data);
3433 break;
3434
3435 case L2CAP_INFO_RSP:
3436 err = l2cap_information_rsp(conn, cmd, data);
3437 break;
3438
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003439 case L2CAP_CREATE_CHAN_REQ:
3440 err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3441 break;
3442
3443 case L2CAP_CREATE_CHAN_RSP:
3444 err = l2cap_create_channel_rsp(conn, cmd, data);
3445 break;
3446
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003447 case L2CAP_MOVE_CHAN_REQ:
3448 err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
3449 break;
3450
3451 case L2CAP_MOVE_CHAN_RSP:
3452 err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
3453 break;
3454
3455 case L2CAP_MOVE_CHAN_CFM:
3456 err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
3457 break;
3458
3459 case L2CAP_MOVE_CHAN_CFM_RSP:
3460 err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
3461 break;
3462
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003463 default:
3464 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3465 err = -EINVAL;
3466 break;
3467 }
3468
3469 return err;
3470}
3471
3472static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3473 struct l2cap_cmd_hdr *cmd, u8 *data)
3474{
3475 switch (cmd->code) {
3476 case L2CAP_COMMAND_REJ:
3477 return 0;
3478
3479 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003480 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003481
3482 case L2CAP_CONN_PARAM_UPDATE_RSP:
3483 return 0;
3484
3485 default:
3486 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3487 return -EINVAL;
3488 }
3489}
3490
3491static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3492 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003493{
3494 u8 *data = skb->data;
3495 int len = skb->len;
3496 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003497 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498
3499 l2cap_raw_recv(conn, skb);
3500
3501 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003502 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3504 data += L2CAP_CMD_HDR_SIZE;
3505 len -= L2CAP_CMD_HDR_SIZE;
3506
Al Viro88219a02007-07-29 00:17:25 -07003507 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003508
Al Viro88219a02007-07-29 00:17:25 -07003509 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 -07003510
Al Viro88219a02007-07-29 00:17:25 -07003511 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512 BT_DBG("corrupted command");
3513 break;
3514 }
3515
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003516 if (conn->hcon->type == LE_LINK)
3517 err = l2cap_le_sig_cmd(conn, &cmd, data);
3518 else
3519 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520
3521 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003522 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003523
3524 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003525
3526 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003527 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003528 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3529 }
3530
Al Viro88219a02007-07-29 00:17:25 -07003531 data += cmd_len;
3532 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003533 }
3534
3535 kfree_skb(skb);
3536}
3537
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003538static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003539{
3540 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003541 int hdr_size;
3542
3543 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3544 hdr_size = L2CAP_EXT_HDR_SIZE;
3545 else
3546 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003547
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003548 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003549 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003550 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3551 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3552
3553 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003554 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003555 }
3556 return 0;
3557}
3558
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003559static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003560{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003561 u32 control = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003562
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003563 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003564
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003565 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003566
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003567 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003568 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003569 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003570 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003571 }
3572
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003573 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003574 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003575
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003576 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003577
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003578 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003579 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003580 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003581 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003582 }
3583}
3584
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003585static 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 -03003586{
3587 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003588 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003589
3590 bt_cb(skb)->tx_seq = tx_seq;
3591 bt_cb(skb)->sar = sar;
3592
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003593 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003594
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003595 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003596
Szymon Janc039d9572011-11-16 09:32:19 +01003597 while (next_skb) {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003598 if (bt_cb(next_skb)->tx_seq == tx_seq)
3599 return -EINVAL;
3600
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003601 next_tx_seq_offset = __seq_offset(chan,
3602 bt_cb(next_skb)->tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003603
3604 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003605 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003606 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003607 }
3608
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003609 if (skb_queue_is_last(&chan->srej_q, next_skb))
Szymon Janc039d9572011-11-16 09:32:19 +01003610 next_skb = NULL;
3611 else
3612 next_skb = skb_queue_next(&chan->srej_q, next_skb);
3613 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003614
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003615 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003616
3617 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003618}
3619
Mat Martineau84084a32011-07-22 14:54:00 -07003620static void append_skb_frag(struct sk_buff *skb,
3621 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003622{
Mat Martineau84084a32011-07-22 14:54:00 -07003623 /* skb->len reflects data in skb as well as all fragments
3624 * skb->data_len reflects only data in fragments
3625 */
3626 if (!skb_has_frag_list(skb))
3627 skb_shinfo(skb)->frag_list = new_frag;
3628
3629 new_frag->next = NULL;
3630
3631 (*last_frag)->next = new_frag;
3632 *last_frag = new_frag;
3633
3634 skb->len += new_frag->len;
3635 skb->data_len += new_frag->len;
3636 skb->truesize += new_frag->truesize;
3637}
3638
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003639static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
Mat Martineau84084a32011-07-22 14:54:00 -07003640{
3641 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003642
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003643 switch (__get_ctrl_sar(chan, control)) {
3644 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003645 if (chan->sdu)
3646 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003647
Mat Martineau84084a32011-07-22 14:54:00 -07003648 err = chan->ops->recv(chan->data, skb);
3649 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003650
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003651 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003652 if (chan->sdu)
3653 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003654
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003655 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003656 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003657
Mat Martineau84084a32011-07-22 14:54:00 -07003658 if (chan->sdu_len > chan->imtu) {
3659 err = -EMSGSIZE;
3660 break;
3661 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003662
Mat Martineau84084a32011-07-22 14:54:00 -07003663 if (skb->len >= chan->sdu_len)
3664 break;
3665
3666 chan->sdu = skb;
3667 chan->sdu_last_frag = skb;
3668
3669 skb = NULL;
3670 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003671 break;
3672
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003673 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003674 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003675 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003676
Mat Martineau84084a32011-07-22 14:54:00 -07003677 append_skb_frag(chan->sdu, skb,
3678 &chan->sdu_last_frag);
3679 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003680
Mat Martineau84084a32011-07-22 14:54:00 -07003681 if (chan->sdu->len >= chan->sdu_len)
3682 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003683
Mat Martineau84084a32011-07-22 14:54:00 -07003684 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003685 break;
3686
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003687 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003688 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003689 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003690
Mat Martineau84084a32011-07-22 14:54:00 -07003691 append_skb_frag(chan->sdu, skb,
3692 &chan->sdu_last_frag);
3693 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003694
Mat Martineau84084a32011-07-22 14:54:00 -07003695 if (chan->sdu->len != chan->sdu_len)
3696 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003697
Mat Martineau84084a32011-07-22 14:54:00 -07003698 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003699
Mat Martineau84084a32011-07-22 14:54:00 -07003700 if (!err) {
3701 /* Reassembly complete */
3702 chan->sdu = NULL;
3703 chan->sdu_last_frag = NULL;
3704 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003705 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003706 break;
3707 }
3708
Mat Martineau84084a32011-07-22 14:54:00 -07003709 if (err) {
3710 kfree_skb(skb);
3711 kfree_skb(chan->sdu);
3712 chan->sdu = NULL;
3713 chan->sdu_last_frag = NULL;
3714 chan->sdu_len = 0;
3715 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003716
Mat Martineau84084a32011-07-22 14:54:00 -07003717 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003718}
3719
Mat Martineau26f880d2011-07-07 09:39:01 -07003720static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003721{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003722 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003723
Mat Martineau26f880d2011-07-07 09:39:01 -07003724 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003725
Mat Martineau26f880d2011-07-07 09:39:01 -07003726 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3727
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003728 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003729 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Mat Martineau26f880d2011-07-07 09:39:01 -07003730 l2cap_send_sframe(chan, control);
3731
3732 set_bit(CONN_RNR_SENT, &chan->conn_state);
3733
3734 __clear_ack_timer(chan);
3735}
3736
3737static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3738{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003739 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003740
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003741 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003742 goto done;
3743
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003744 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003745 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003746 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003747 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003748 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003749
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003750 __clear_retrans_timer(chan);
3751 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003752
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003753 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003754
3755done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003756 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3757 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003758
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003759 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003760}
3761
Mat Martineaue3281402011-07-07 09:39:02 -07003762void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003763{
Mat Martineaue3281402011-07-07 09:39:02 -07003764 if (chan->mode == L2CAP_MODE_ERTM) {
3765 if (busy)
3766 l2cap_ertm_enter_local_busy(chan);
3767 else
3768 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003769 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003770}
3771
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003772static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003773{
3774 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003775 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003776
Mat Martineaue3281402011-07-07 09:39:02 -07003777 while ((skb = skb_peek(&chan->srej_q)) &&
3778 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3779 int err;
3780
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003781 if (bt_cb(skb)->tx_seq != tx_seq)
3782 break;
3783
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003784 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003785 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003786 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003787
3788 if (err < 0) {
3789 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3790 break;
3791 }
3792
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003793 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
3794 tx_seq = __next_seq(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003795 }
3796}
3797
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003798static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003799{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003800 struct srej_list *l, *tmp;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003801 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003802
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003803 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003804 if (l->tx_seq == tx_seq) {
3805 list_del(&l->list);
3806 kfree(l);
3807 return;
3808 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003809 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003810 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003811 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003812 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003813 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003814 }
3815}
3816
Szymon Jancaef89f22011-11-16 09:32:18 +01003817static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003818{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003819 struct srej_list *new;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003820 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003821
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003822 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003823 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003824 control |= __set_reqseq(chan, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003825 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003826
3827 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Szymon Jancaef89f22011-11-16 09:32:18 +01003828 if (!new)
3829 return -ENOMEM;
3830
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003831 new->tx_seq = chan->expected_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003832
3833 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
3834
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003835 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003836 }
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003837
3838 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Szymon Jancaef89f22011-11-16 09:32:18 +01003839
3840 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003841}
3842
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003843static 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 -03003844{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003845 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003846 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003847 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003848 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003849 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003850 int err = 0;
3851
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003852 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 -03003853 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003854
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003855 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003856 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003857 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003858 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003859 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003860 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003861 }
3862
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003863 chan->expected_ack_seq = req_seq;
3864 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003865
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003866 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003867
3868 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003869 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003870 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003871 goto drop;
3872 }
3873
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003874 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003875 goto drop;
3876
Mat Martineau02f1b642011-06-29 14:35:19 -07003877 if (tx_seq == chan->expected_tx_seq)
3878 goto expected;
3879
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003880 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003881 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003882
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003883 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003884 struct srej_list, list);
3885 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003886 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003887 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003888
3889 list_del(&first->list);
3890 kfree(first);
3891
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003892 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003893 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003894 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003895 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003896 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003897 }
3898 } else {
3899 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003900
3901 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003902 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003903 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003904
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003905 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003906 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003907 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003908 return 0;
3909 }
3910 }
Szymon Jancaef89f22011-11-16 09:32:18 +01003911
3912 err = l2cap_send_srejframe(chan, tx_seq);
3913 if (err < 0) {
3914 l2cap_send_disconn_req(chan->conn, chan, -err);
3915 return err;
3916 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003917 }
3918 } else {
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003919 expected_tx_seq_offset = __seq_offset(chan,
3920 chan->expected_tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003921
3922 /* duplicated tx_seq */
3923 if (tx_seq_offset < expected_tx_seq_offset)
3924 goto drop;
3925
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003926 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003927
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003928 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003929
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003930 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003931 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003932
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003933 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003934 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003935
Szymon Janc0ef3ef02012-01-11 10:59:46 +01003936 /* Set P-bit only if there are some I-frames to ack. */
3937 if (__clear_ack_timer(chan))
3938 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003939
Szymon Jancaef89f22011-11-16 09:32:18 +01003940 err = l2cap_send_srejframe(chan, tx_seq);
3941 if (err < 0) {
3942 l2cap_send_disconn_req(chan->conn, chan, -err);
3943 return err;
3944 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003945 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003946 return 0;
3947
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003948expected:
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003949 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003950
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003951 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003952 bt_cb(skb)->tx_seq = tx_seq;
3953 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003954 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003955 return 0;
3956 }
3957
Mat Martineau84084a32011-07-22 14:54:00 -07003958 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003959 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
3960
Mat Martineaue3281402011-07-07 09:39:02 -07003961 if (err < 0) {
3962 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3963 return err;
3964 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003965
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003966 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003967 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003968 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003969 }
3970
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003971
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003972 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3973 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003974 l2cap_send_ack(chan);
Gustavo F. Padovan4d611e42011-06-23 19:30:48 -03003975 else
3976 __set_ack_timer(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003977
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003978 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003979
3980drop:
3981 kfree_skb(skb);
3982 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003983}
3984
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003985static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003986{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003987 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003988 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003989
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003990 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003991 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003992
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003993 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003994 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3995 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3996 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003997 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003998 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003999
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004000 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004001 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004002 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004003 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004004 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004005
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004006 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004007 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004008
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004009 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004010 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004011
4012 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004013 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004014 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004015 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004016
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004017 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4018 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004019 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02004020 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004021 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004022 }
4023}
4024
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004025static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004026{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004027 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004028
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004029 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004030
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004031 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004032
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004033 chan->expected_ack_seq = tx_seq;
4034 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004035
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004036 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004037 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004038 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004039 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004040 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004041
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004042 if (test_bit(CONN_WAIT_F, &chan->conn_state))
4043 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004044 }
4045}
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004046static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004047{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004048 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004049
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004050 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004051
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004052 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004053
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004054 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004055 chan->expected_ack_seq = tx_seq;
4056 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004057
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004058 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004059 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004060
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004061 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004062
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004063 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004064 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004065 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004066 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004067 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004068 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004069 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004070 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004071 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004072 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004073 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004074 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004075 if (test_bit(CONN_WAIT_F, &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 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004078 }
4079 }
4080}
4081
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004082static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004083{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004084 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004085
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004086 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004087
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004088 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004089 chan->expected_ack_seq = tx_seq;
4090 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004091
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004092 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004093 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004094
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004095 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004096 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004097 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004098 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004099 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004100 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004101
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004102 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004103 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004104 } else {
4105 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4106 l2cap_send_sframe(chan, rx_control);
4107 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004108}
4109
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004110static 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 -03004111{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004112 BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004113
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004114 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004115 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004116 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004117 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004118 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004119 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004120 }
4121
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004122 switch (__get_ctrl_super(chan, rx_control)) {
4123 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004124 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004125 break;
4126
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004127 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004128 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004129 break;
4130
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004131 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004132 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004133 break;
4134
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004135 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004136 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004137 break;
4138 }
4139
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004140 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004141 return 0;
4142}
4143
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004144static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
4145{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004146 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004147 u32 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004148 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004149 int len, next_tx_seq_offset, req_seq_offset;
4150
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004151 control = __get_control(chan, skb->data);
4152 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004153 len = skb->len;
4154
4155 /*
4156 * We can just drop the corrupted I-frame here.
4157 * Receiver will miss it and start proper recovery
4158 * procedures and ask retransmission.
4159 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004160 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004161 goto drop;
4162
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004163 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004164 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004165
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004166 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004167 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004168
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004169 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004170 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004171 goto drop;
4172 }
4173
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004174 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004175
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004176 req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4177
4178 next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4179 chan->expected_ack_seq);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004180
4181 /* check for invalid req-seq */
4182 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004183 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004184 goto drop;
4185 }
4186
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004187 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004188 if (len < 0) {
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
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004193 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004194 } else {
4195 if (len != 0) {
4196 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004197 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004198 goto drop;
4199 }
4200
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004201 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004202 }
4203
4204 return 0;
4205
4206drop:
4207 kfree_skb(skb);
4208 return 0;
4209}
4210
Linus Torvalds1da177e2005-04-16 15:20:36 -07004211static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4212{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004213 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07004214 struct sock *sk = NULL;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004215 u32 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004216 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004217 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004218
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004219 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004220 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004221 BT_DBG("unknown cid 0x%4.4x", cid);
4222 goto drop;
4223 }
4224
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004225 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004226
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004227 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004229 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230 goto drop;
4231
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004232 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004233 case L2CAP_MODE_BASIC:
4234 /* If socket recv buffers overflows we drop data here
4235 * which is *bad* because L2CAP has to be reliable.
4236 * But we don't have any other choice. L2CAP doesn't
4237 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004238
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004239 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004240 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004241
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004242 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004243 goto done;
4244 break;
4245
4246 case L2CAP_MODE_ERTM:
Gustavo F. Padovaneb403a12011-06-24 01:54:50 -03004247 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004248
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004249 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004250
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004251 case L2CAP_MODE_STREAMING:
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004252 control = __get_control(chan, skb->data);
4253 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004254 len = skb->len;
4255
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004256 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004257 goto drop;
4258
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004259 if (__is_sar_start(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004260 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004261
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004262 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004263 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004264
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004265 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004266 goto drop;
4267
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004268 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004269
Mat Martineau84084a32011-07-22 14:54:00 -07004270 if (chan->expected_tx_seq != tx_seq) {
4271 /* Frame(s) missing - must discard partial SDU */
4272 kfree_skb(chan->sdu);
4273 chan->sdu = NULL;
4274 chan->sdu_last_frag = NULL;
4275 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004276
Mat Martineau84084a32011-07-22 14:54:00 -07004277 /* TODO: Notify userland of missing data */
4278 }
4279
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004280 chan->expected_tx_seq = __next_seq(chan, tx_seq);
Mat Martineau84084a32011-07-22 14:54:00 -07004281
4282 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
4283 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004284
4285 goto done;
4286
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004287 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004288 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004289 break;
4290 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004291
4292drop:
4293 kfree_skb(skb);
4294
4295done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004296 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004297 release_sock(sk);
Marcel Holtmann01394182006-07-03 10:02:46 +02004298
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299 return 0;
4300}
4301
Al Viro8e036fc2007-07-29 00:16:36 -07004302static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004304 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004305 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004307 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
4308 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309 goto drop;
4310
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004311 sk = chan->sk;
4312
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004313 lock_sock(sk);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00004314
Linus Torvalds1da177e2005-04-16 15:20:36 -07004315 BT_DBG("sk %p, len %d", sk, skb->len);
4316
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004317 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318 goto drop;
4319
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004320 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004321 goto drop;
4322
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004323 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324 goto done;
4325
4326drop:
4327 kfree_skb(skb);
4328
4329done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004330 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004331 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332 return 0;
4333}
4334
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004335static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
4336{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004337 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004338 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004339
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004340 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
4341 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004342 goto drop;
4343
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004344 sk = chan->sk;
4345
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004346 lock_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004347
4348 BT_DBG("sk %p, len %d", sk, skb->len);
4349
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004350 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004351 goto drop;
4352
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004353 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004354 goto drop;
4355
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004356 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004357 goto done;
4358
4359drop:
4360 kfree_skb(skb);
4361
4362done:
4363 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004364 release_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004365 return 0;
4366}
4367
Linus Torvalds1da177e2005-04-16 15:20:36 -07004368static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4369{
4370 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004371 u16 cid, len;
4372 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004373
4374 skb_pull(skb, L2CAP_HDR_SIZE);
4375 cid = __le16_to_cpu(lh->cid);
4376 len = __le16_to_cpu(lh->len);
4377
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004378 if (len != skb->len) {
4379 kfree_skb(skb);
4380 return;
4381 }
4382
Linus Torvalds1da177e2005-04-16 15:20:36 -07004383 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4384
4385 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004386 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004387 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004388 l2cap_sig_channel(conn, skb);
4389 break;
4390
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004391 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004392 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004393 skb_pull(skb, 2);
4394 l2cap_conless_channel(conn, psm, skb);
4395 break;
4396
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004397 case L2CAP_CID_LE_DATA:
4398 l2cap_att_channel(conn, cid, skb);
4399 break;
4400
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004401 case L2CAP_CID_SMP:
4402 if (smp_sig_channel(conn, skb))
4403 l2cap_conn_del(conn->hcon, EACCES);
4404 break;
4405
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406 default:
4407 l2cap_data_channel(conn, cid, skb);
4408 break;
4409 }
4410}
4411
4412/* ---- L2CAP interface with lower layer (HCI) ---- */
4413
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004414int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415{
4416 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004417 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418
Linus Torvalds1da177e2005-04-16 15:20:36 -07004419 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4420
4421 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004422 read_lock(&chan_list_lock);
4423 list_for_each_entry(c, &chan_list, global_l) {
4424 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004425
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004426 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427 continue;
4428
4429 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004430 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004431 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004432 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004433 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004434 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4435 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004436 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004437 lm2 |= HCI_LM_MASTER;
4438 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004440 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004441
4442 return exact ? lm1 : lm2;
4443}
4444
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004445int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446{
Marcel Holtmann01394182006-07-03 10:02:46 +02004447 struct l2cap_conn *conn;
4448
Linus Torvalds1da177e2005-04-16 15:20:36 -07004449 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4450
Linus Torvalds1da177e2005-04-16 15:20:36 -07004451 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452 conn = l2cap_conn_add(hcon, status);
4453 if (conn)
4454 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004455 } else
Joe Perchese1750722011-06-29 18:18:29 -07004456 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004457
4458 return 0;
4459}
4460
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004461int l2cap_disconn_ind(struct hci_conn *hcon)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004462{
4463 struct l2cap_conn *conn = hcon->l2cap_data;
4464
4465 BT_DBG("hcon %p", hcon);
4466
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004467 if (!conn)
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02004468 return HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01004469 return conn->disc_reason;
4470}
4471
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004472int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004473{
4474 BT_DBG("hcon %p reason %d", hcon, reason);
4475
Joe Perchese1750722011-06-29 18:18:29 -07004476 l2cap_conn_del(hcon, bt_to_errno(reason));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004477 return 0;
4478}
4479
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004480static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004481{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004482 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004483 return;
4484
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004485 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004486 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004487 __clear_chan_timer(chan);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004488 __set_chan_timer(chan,
4489 msecs_to_jiffies(L2CAP_ENC_TIMEOUT));
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004490 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004491 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004492 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004493 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004494 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004495 }
4496}
4497
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004498int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004499{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004500 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004501 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004502
Marcel Holtmann01394182006-07-03 10:02:46 +02004503 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004504 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004505
Linus Torvalds1da177e2005-04-16 15:20:36 -07004506 BT_DBG("conn %p", conn);
4507
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004508 if (hcon->type == LE_LINK) {
4509 smp_distribute_keys(conn, 0);
Ulisses Furquim371fd832011-12-21 20:02:36 -02004510 __cancel_delayed_work(&conn->security_timer);
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004511 }
4512
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02004513 rcu_read_lock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02004515 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004516 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004517
Linus Torvalds1da177e2005-04-16 15:20:36 -07004518 bh_lock_sock(sk);
4519
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004520 BT_DBG("chan->scid %d", chan->scid);
4521
4522 if (chan->scid == L2CAP_CID_LE_DATA) {
4523 if (!status && encrypt) {
4524 chan->sec_level = hcon->sec_level;
4525 l2cap_chan_ready(sk);
4526 }
4527
4528 bh_unlock_sock(sk);
4529 continue;
4530 }
4531
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004532 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004533 bh_unlock_sock(sk);
4534 continue;
4535 }
4536
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004537 if (!status && (chan->state == BT_CONNECTED ||
4538 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004539 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004540 bh_unlock_sock(sk);
4541 continue;
4542 }
4543
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004544 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004545 if (!status) {
4546 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004547 req.scid = cpu_to_le16(chan->scid);
4548 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004549
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004550 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004551 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004552
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004553 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004554 L2CAP_CONN_REQ, sizeof(req), &req);
4555 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004556 __clear_chan_timer(chan);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004557 __set_chan_timer(chan,
4558 msecs_to_jiffies(L2CAP_DISC_TIMEOUT));
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004559 }
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004560 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004561 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004562 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004563
4564 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004565 if (bt_sk(sk)->defer_setup) {
4566 struct sock *parent = bt_sk(sk)->parent;
4567 res = L2CAP_CR_PEND;
4568 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004569 if (parent)
4570 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004571 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004572 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004573 res = L2CAP_CR_SUCCESS;
4574 stat = L2CAP_CS_NO_INFO;
4575 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004576 } else {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004577 l2cap_state_change(chan, BT_DISCONN);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004578 __set_chan_timer(chan,
4579 msecs_to_jiffies(L2CAP_DISC_TIMEOUT));
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004580 res = L2CAP_CR_SEC_BLOCK;
4581 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004582 }
4583
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004584 rsp.scid = cpu_to_le16(chan->dcid);
4585 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004586 rsp.result = cpu_to_le16(res);
4587 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004588 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4589 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004590 }
4591
Linus Torvalds1da177e2005-04-16 15:20:36 -07004592 bh_unlock_sock(sk);
4593 }
4594
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02004595 rcu_read_unlock();
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004596
Linus Torvalds1da177e2005-04-16 15:20:36 -07004597 return 0;
4598}
4599
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004600int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004601{
4602 struct l2cap_conn *conn = hcon->l2cap_data;
4603
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004604 if (!conn)
4605 conn = l2cap_conn_add(hcon, 0);
4606
4607 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004608 goto drop;
4609
4610 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4611
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004612 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004613 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004614 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004615 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004616 int len;
4617
4618 if (conn->rx_len) {
4619 BT_ERR("Unexpected start frame (len %d)", skb->len);
4620 kfree_skb(conn->rx_skb);
4621 conn->rx_skb = NULL;
4622 conn->rx_len = 0;
4623 l2cap_conn_unreliable(conn, ECOMM);
4624 }
4625
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004626 /* Start fragment always begin with Basic L2CAP header */
4627 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004628 BT_ERR("Frame is too short (len %d)", skb->len);
4629 l2cap_conn_unreliable(conn, ECOMM);
4630 goto drop;
4631 }
4632
4633 hdr = (struct l2cap_hdr *) skb->data;
4634 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004635 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004636
4637 if (len == skb->len) {
4638 /* Complete frame received */
4639 l2cap_recv_frame(conn, skb);
4640 return 0;
4641 }
4642
4643 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4644
4645 if (skb->len > len) {
4646 BT_ERR("Frame is too long (len %d, expected len %d)",
4647 skb->len, len);
4648 l2cap_conn_unreliable(conn, ECOMM);
4649 goto drop;
4650 }
4651
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004652 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004653
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004654 if (chan && chan->sk) {
4655 struct sock *sk = chan->sk;
4656
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004657 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004658 BT_ERR("Frame exceeding recv MTU (len %d, "
4659 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004660 chan->imtu);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004661 release_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004662 l2cap_conn_unreliable(conn, ECOMM);
4663 goto drop;
4664 }
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004665 release_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004666 }
4667
Linus Torvalds1da177e2005-04-16 15:20:36 -07004668 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004669 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4670 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004671 goto drop;
4672
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004673 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004674 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004675 conn->rx_len = len - skb->len;
4676 } else {
4677 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4678
4679 if (!conn->rx_len) {
4680 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4681 l2cap_conn_unreliable(conn, ECOMM);
4682 goto drop;
4683 }
4684
4685 if (skb->len > conn->rx_len) {
4686 BT_ERR("Fragment is too long (len %d, expected %d)",
4687 skb->len, conn->rx_len);
4688 kfree_skb(conn->rx_skb);
4689 conn->rx_skb = NULL;
4690 conn->rx_len = 0;
4691 l2cap_conn_unreliable(conn, ECOMM);
4692 goto drop;
4693 }
4694
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004695 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004696 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004697 conn->rx_len -= skb->len;
4698
4699 if (!conn->rx_len) {
4700 /* Complete frame received */
4701 l2cap_recv_frame(conn, conn->rx_skb);
4702 conn->rx_skb = NULL;
4703 }
4704 }
4705
4706drop:
4707 kfree_skb(skb);
4708 return 0;
4709}
4710
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004711static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004712{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004713 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004714
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02004715 read_lock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004716
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004717 list_for_each_entry(c, &chan_list, global_l) {
4718 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004719
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004720 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 +01004721 batostr(&bt_sk(sk)->src),
4722 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004723 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004724 c->scid, c->dcid, c->imtu, c->omtu,
4725 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004726}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004727
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02004728 read_unlock(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004729
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004730 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004731}
4732
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004733static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4734{
4735 return single_open(file, l2cap_debugfs_show, inode->i_private);
4736}
4737
4738static const struct file_operations l2cap_debugfs_fops = {
4739 .open = l2cap_debugfs_open,
4740 .read = seq_read,
4741 .llseek = seq_lseek,
4742 .release = single_release,
4743};
4744
4745static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004746
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004747int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004748{
4749 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004750
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004751 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004752 if (err < 0)
4753 return err;
4754
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004755 if (bt_debugfs) {
4756 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4757 bt_debugfs, NULL, &l2cap_debugfs_fops);
4758 if (!l2cap_debugfs)
4759 BT_ERR("Failed to create L2CAP debug file");
4760 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004761
Linus Torvalds1da177e2005-04-16 15:20:36 -07004762 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004763}
4764
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004765void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004766{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004767 debugfs_remove(l2cap_debugfs);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004768 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004769}
4770
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004771module_param(disable_ertm, bool, 0644);
4772MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");