blob: faf0b11ac1d3610805e6d049f4a2e2221c35053a [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. Padovanaf05b302009-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovanaf05b302009-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001123inline int 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. Padovanaf05b302009-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001481static 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
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001501static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001502{
1503 struct srej_list *tail;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001504 u32 control;
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001505
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001506 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001507 control |= __set_ctrl_final(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001508
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001509 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001510 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001511
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001512 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001513}
1514
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001515static 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 -07001516{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001517 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001518 struct sk_buff **frag;
1519 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001521 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001522 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523
1524 sent += count;
1525 len -= count;
1526
1527 /* Continuation fragments (no L2CAP header) */
1528 frag = &skb_shinfo(skb)->frag_list;
1529 while (len) {
1530 count = min_t(unsigned int, conn->mtu, len);
1531
1532 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1533 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001534 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001535 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1536 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001538 (*frag)->priority = skb->priority;
1539
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 sent += count;
1541 len -= count;
1542
1543 frag = &(*frag)->next;
1544 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545
1546 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001547}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001549static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
1550 struct msghdr *msg, size_t len,
1551 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001552{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001553 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001554 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001555 struct sk_buff *skb;
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001556 int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001557 struct l2cap_hdr *lh;
1558
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001559 BT_DBG("sk %p len %d priority %u", sk, (int)len, priority);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001560
1561 count = min_t(unsigned int, (conn->mtu - hlen), len);
1562 skb = bt_skb_send_alloc(sk, count + hlen,
1563 msg->msg_flags & MSG_DONTWAIT, &err);
1564 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001565 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001566
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001567 skb->priority = priority;
1568
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001569 /* Create L2CAP header */
1570 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001571 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001572 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001573 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001574
1575 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1576 if (unlikely(err < 0)) {
1577 kfree_skb(skb);
1578 return ERR_PTR(err);
1579 }
1580 return skb;
1581}
1582
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001583static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
1584 struct msghdr *msg, size_t len,
1585 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001586{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001587 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001588 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001589 struct sk_buff *skb;
1590 int err, count, hlen = L2CAP_HDR_SIZE;
1591 struct l2cap_hdr *lh;
1592
1593 BT_DBG("sk %p len %d", sk, (int)len);
1594
1595 count = min_t(unsigned int, (conn->mtu - hlen), len);
1596 skb = bt_skb_send_alloc(sk, count + hlen,
1597 msg->msg_flags & MSG_DONTWAIT, &err);
1598 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001599 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001600
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001601 skb->priority = priority;
1602
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001603 /* Create L2CAP header */
1604 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001605 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001606 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1607
1608 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1609 if (unlikely(err < 0)) {
1610 kfree_skb(skb);
1611 return ERR_PTR(err);
1612 }
1613 return skb;
1614}
1615
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001616static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1617 struct msghdr *msg, size_t len,
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001618 u32 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001619{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001620 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001621 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001622 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001623 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001624 struct l2cap_hdr *lh;
1625
1626 BT_DBG("sk %p len %d", sk, (int)len);
1627
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001628 if (!conn)
1629 return ERR_PTR(-ENOTCONN);
1630
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001631 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1632 hlen = L2CAP_EXT_HDR_SIZE;
1633 else
1634 hlen = L2CAP_ENH_HDR_SIZE;
1635
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001636 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001637 hlen += L2CAP_SDULEN_SIZE;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001638
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001639 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001640 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001641
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001642 count = min_t(unsigned int, (conn->mtu - hlen), len);
1643 skb = bt_skb_send_alloc(sk, count + hlen,
1644 msg->msg_flags & MSG_DONTWAIT, &err);
1645 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001646 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001647
1648 /* Create L2CAP header */
1649 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001650 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001651 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001652
1653 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
1654
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001655 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001656 put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001657
1658 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1659 if (unlikely(err < 0)) {
1660 kfree_skb(skb);
1661 return ERR_PTR(err);
1662 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001663
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001664 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001665 put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001666
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001667 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001668 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669}
1670
Szymon Janc67c9e842011-07-28 16:24:33 +02001671static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001672{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001673 struct sk_buff *skb;
1674 struct sk_buff_head sar_queue;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001675 u32 control;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001676 size_t size = 0;
1677
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001678 skb_queue_head_init(&sar_queue);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001679 control = __set_ctrl_sar(chan, L2CAP_SAR_START);
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001680 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001681 if (IS_ERR(skb))
1682 return PTR_ERR(skb);
1683
1684 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001685 len -= chan->remote_mps;
1686 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001687
1688 while (len > 0) {
1689 size_t buflen;
1690
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001691 if (len > chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001692 control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001693 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001694 } else {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001695 control = __set_ctrl_sar(chan, L2CAP_SAR_END);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001696 buflen = len;
1697 }
1698
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001699 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001700 if (IS_ERR(skb)) {
1701 skb_queue_purge(&sar_queue);
1702 return PTR_ERR(skb);
1703 }
1704
1705 __skb_queue_tail(&sar_queue, skb);
1706 len -= buflen;
1707 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001708 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001709 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1710 if (chan->tx_send_head == NULL)
1711 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001712
1713 return size;
1714}
1715
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001716int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
1717 u32 priority)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001718{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001719 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001720 u32 control;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001721 int err;
1722
1723 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001724 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001725 skb = l2cap_create_connless_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001726 if (IS_ERR(skb))
1727 return PTR_ERR(skb);
1728
1729 l2cap_do_send(chan, skb);
1730 return len;
1731 }
1732
1733 switch (chan->mode) {
1734 case L2CAP_MODE_BASIC:
1735 /* Check outgoing MTU */
1736 if (len > chan->omtu)
1737 return -EMSGSIZE;
1738
1739 /* Create a basic PDU */
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001740 skb = l2cap_create_basic_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001741 if (IS_ERR(skb))
1742 return PTR_ERR(skb);
1743
1744 l2cap_do_send(chan, skb);
1745 err = len;
1746 break;
1747
1748 case L2CAP_MODE_ERTM:
1749 case L2CAP_MODE_STREAMING:
1750 /* Entire SDU fits into one PDU */
1751 if (len <= chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001752 control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001753 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1754 0);
1755 if (IS_ERR(skb))
1756 return PTR_ERR(skb);
1757
1758 __skb_queue_tail(&chan->tx_q, skb);
1759
1760 if (chan->tx_send_head == NULL)
1761 chan->tx_send_head = skb;
1762
1763 } else {
1764 /* Segment SDU into multiples PDUs */
1765 err = l2cap_sar_segment_sdu(chan, msg, len);
1766 if (err < 0)
1767 return err;
1768 }
1769
1770 if (chan->mode == L2CAP_MODE_STREAMING) {
1771 l2cap_streaming_send(chan);
1772 err = len;
1773 break;
1774 }
1775
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001776 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1777 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001778 err = len;
1779 break;
1780 }
1781
1782 err = l2cap_ertm_send(chan);
1783 if (err >= 0)
1784 err = len;
1785
1786 break;
1787
1788 default:
1789 BT_DBG("bad state %1.1x", chan->mode);
1790 err = -EBADFD;
1791 }
1792
1793 return err;
1794}
1795
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796/* Copy frame to all raw sockets on that connection */
1797static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1798{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001800 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801
1802 BT_DBG("conn %p", conn);
1803
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001804 rcu_read_lock();
1805
1806 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001807 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001808 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 continue;
1810
1811 /* Don't send frame to the socket it came from */
1812 if (skb->sk == sk)
1813 continue;
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001814 nskb = skb_clone(skb, GFP_ATOMIC);
1815 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816 continue;
1817
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001818 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 kfree_skb(nskb);
1820 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001821
1822 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823}
1824
1825/* ---- L2CAP signalling commands ---- */
1826static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1827 u8 code, u8 ident, u16 dlen, void *data)
1828{
1829 struct sk_buff *skb, **frag;
1830 struct l2cap_cmd_hdr *cmd;
1831 struct l2cap_hdr *lh;
1832 int len, count;
1833
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001834 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1835 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836
1837 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1838 count = min_t(unsigned int, conn->mtu, len);
1839
1840 skb = bt_skb_alloc(count, GFP_ATOMIC);
1841 if (!skb)
1842 return NULL;
1843
1844 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001845 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001846
1847 if (conn->hcon->type == LE_LINK)
1848 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1849 else
1850 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851
1852 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1853 cmd->code = code;
1854 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001855 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856
1857 if (dlen) {
1858 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1859 memcpy(skb_put(skb, count), data, count);
1860 data += count;
1861 }
1862
1863 len -= skb->len;
1864
1865 /* Continuation fragments (no L2CAP header) */
1866 frag = &skb_shinfo(skb)->frag_list;
1867 while (len) {
1868 count = min_t(unsigned int, conn->mtu, len);
1869
1870 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1871 if (!*frag)
1872 goto fail;
1873
1874 memcpy(skb_put(*frag, count), data, count);
1875
1876 len -= count;
1877 data += count;
1878
1879 frag = &(*frag)->next;
1880 }
1881
1882 return skb;
1883
1884fail:
1885 kfree_skb(skb);
1886 return NULL;
1887}
1888
1889static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1890{
1891 struct l2cap_conf_opt *opt = *ptr;
1892 int len;
1893
1894 len = L2CAP_CONF_OPT_SIZE + opt->len;
1895 *ptr += len;
1896
1897 *type = opt->type;
1898 *olen = opt->len;
1899
1900 switch (opt->len) {
1901 case 1:
1902 *val = *((u8 *) opt->val);
1903 break;
1904
1905 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001906 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 break;
1908
1909 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001910 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 break;
1912
1913 default:
1914 *val = (unsigned long) opt->val;
1915 break;
1916 }
1917
1918 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1919 return len;
1920}
1921
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1923{
1924 struct l2cap_conf_opt *opt = *ptr;
1925
1926 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1927
1928 opt->type = type;
1929 opt->len = len;
1930
1931 switch (len) {
1932 case 1:
1933 *((u8 *) opt->val) = val;
1934 break;
1935
1936 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001937 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 break;
1939
1940 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001941 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942 break;
1943
1944 default:
1945 memcpy(opt->val, (void *) val, len);
1946 break;
1947 }
1948
1949 *ptr += L2CAP_CONF_OPT_SIZE + len;
1950}
1951
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001952static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
1953{
1954 struct l2cap_conf_efs efs;
1955
Szymon Janc1ec918c2011-11-16 09:32:21 +01001956 switch (chan->mode) {
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001957 case L2CAP_MODE_ERTM:
1958 efs.id = chan->local_id;
1959 efs.stype = chan->local_stype;
1960 efs.msdu = cpu_to_le16(chan->local_msdu);
1961 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1962 efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
1963 efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
1964 break;
1965
1966 case L2CAP_MODE_STREAMING:
1967 efs.id = 1;
1968 efs.stype = L2CAP_SERV_BESTEFFORT;
1969 efs.msdu = cpu_to_le16(chan->local_msdu);
1970 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1971 efs.acc_lat = 0;
1972 efs.flush_to = 0;
1973 break;
1974
1975 default:
1976 return;
1977 }
1978
1979 l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
1980 (unsigned long) &efs);
1981}
1982
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001983static void l2cap_ack_timeout(struct work_struct *work)
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001984{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001985 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1986 ack_timer.work);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001987
Gustavo F. Padovan2fb9b3d2011-12-22 16:56:05 -02001988 BT_DBG("chan %p", chan);
1989
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001990 lock_sock(chan->sk);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001991 l2cap_send_ack(chan);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001992 release_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001993}
1994
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001995static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001996{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001997 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001998 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001999 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002000 chan->num_acked = 0;
2001 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002002
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002003 INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2004 INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2005 INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002006
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002007 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002008
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03002009 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002010}
2011
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002012static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2013{
2014 switch (mode) {
2015 case L2CAP_MODE_STREAMING:
2016 case L2CAP_MODE_ERTM:
2017 if (l2cap_mode_supported(mode, remote_feat_mask))
2018 return mode;
2019 /* fall through */
2020 default:
2021 return L2CAP_MODE_BASIC;
2022 }
2023}
2024
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002025static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
2026{
2027 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
2028}
2029
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002030static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2031{
2032 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2033}
2034
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002035static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
2036{
2037 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002038 __l2cap_ews_supported(chan)) {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002039 /* use extended control field */
2040 set_bit(FLAG_EXT_CTRL, &chan->flags);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002041 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2042 } else {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002043 chan->tx_win = min_t(u16, chan->tx_win,
2044 L2CAP_DEFAULT_TX_WINDOW);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002045 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2046 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002047}
2048
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002049static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002052 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 void *ptr = req->data;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002054 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002056 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002058 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002059 goto done;
2060
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002061 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002062 case L2CAP_MODE_STREAMING:
2063 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002064 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002065 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002066
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002067 if (__l2cap_efs_supported(chan))
2068 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2069
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002070 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002071 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002072 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002073 break;
2074 }
2075
2076done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002077 if (chan->imtu != L2CAP_DEFAULT_MTU)
2078 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan79906812011-01-24 16:01:43 -02002079
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002080 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002081 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002082 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2083 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002084 break;
2085
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002086 rfc.mode = L2CAP_MODE_BASIC;
2087 rfc.txwin_size = 0;
2088 rfc.max_transmit = 0;
2089 rfc.retrans_timeout = 0;
2090 rfc.monitor_timeout = 0;
2091 rfc.max_pdu_size = 0;
2092
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002093 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2094 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002095 break;
2096
2097 case L2CAP_MODE_ERTM:
2098 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002099 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002100 rfc.retrans_timeout = 0;
2101 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002102
2103 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2104 L2CAP_EXT_HDR_SIZE -
2105 L2CAP_SDULEN_SIZE -
2106 L2CAP_FCS_SIZE);
2107 rfc.max_pdu_size = cpu_to_le16(size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002108
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002109 l2cap_txwin_setup(chan);
2110
2111 rfc.txwin_size = min_t(u16, chan->tx_win,
2112 L2CAP_DEFAULT_TX_WINDOW);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002113
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002114 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2115 (unsigned long) &rfc);
2116
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002117 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2118 l2cap_add_opt_efs(&ptr, chan);
2119
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002120 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002121 break;
2122
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002123 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002124 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002125 chan->fcs = L2CAP_FCS_NONE;
2126 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002127 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002128
2129 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2130 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2131 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002132 break;
2133
2134 case L2CAP_MODE_STREAMING:
2135 rfc.mode = L2CAP_MODE_STREAMING;
2136 rfc.txwin_size = 0;
2137 rfc.max_transmit = 0;
2138 rfc.retrans_timeout = 0;
2139 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002140
2141 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2142 L2CAP_EXT_HDR_SIZE -
2143 L2CAP_SDULEN_SIZE -
2144 L2CAP_FCS_SIZE);
2145 rfc.max_pdu_size = cpu_to_le16(size);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002146
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002147 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2148 (unsigned long) &rfc);
2149
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002150 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2151 l2cap_add_opt_efs(&ptr, chan);
2152
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002153 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002154 break;
2155
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002156 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002157 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002158 chan->fcs = L2CAP_FCS_NONE;
2159 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002160 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002161 break;
2162 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002164 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002165 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166
2167 return ptr - data;
2168}
2169
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002170static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002172 struct l2cap_conf_rsp *rsp = data;
2173 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002174 void *req = chan->conf_req;
2175 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002176 int type, hint, olen;
2177 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002178 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002179 struct l2cap_conf_efs efs;
2180 u8 remote_efs = 0;
Marcel Holtmann861d6882007-10-20 13:37:06 +02002181 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002182 u16 result = L2CAP_CONF_SUCCESS;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002183 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002185 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002186
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002187 while (len >= L2CAP_CONF_OPT_SIZE) {
2188 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002190 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002191 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002192
2193 switch (type) {
2194 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002195 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002196 break;
2197
2198 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002199 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002200 break;
2201
2202 case L2CAP_CONF_QOS:
2203 break;
2204
Marcel Holtmann6464f352007-10-20 13:39:51 +02002205 case L2CAP_CONF_RFC:
2206 if (olen == sizeof(rfc))
2207 memcpy(&rfc, (void *) val, olen);
2208 break;
2209
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002210 case L2CAP_CONF_FCS:
2211 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002212 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002213 break;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002214
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002215 case L2CAP_CONF_EFS:
2216 remote_efs = 1;
2217 if (olen == sizeof(efs))
2218 memcpy(&efs, (void *) val, olen);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002219 break;
2220
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002221 case L2CAP_CONF_EWS:
2222 if (!enable_hs)
2223 return -ECONNREFUSED;
2224
2225 set_bit(FLAG_EXT_CTRL, &chan->flags);
2226 set_bit(CONF_EWS_RECV, &chan->conf_state);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002227 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002228 chan->remote_tx_win = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002229 break;
2230
2231 default:
2232 if (hint)
2233 break;
2234
2235 result = L2CAP_CONF_UNKNOWN;
2236 *((u8 *) ptr++) = type;
2237 break;
2238 }
2239 }
2240
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002241 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002242 goto done;
2243
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002244 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002245 case L2CAP_MODE_STREAMING:
2246 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002247 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002248 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002249 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002250 break;
2251 }
2252
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002253 if (remote_efs) {
2254 if (__l2cap_efs_supported(chan))
2255 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2256 else
2257 return -ECONNREFUSED;
2258 }
2259
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002260 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002261 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002262
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002263 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002264 }
2265
2266done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002267 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002268 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002269 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002270
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002271 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002272 return -ECONNREFUSED;
2273
2274 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2275 sizeof(rfc), (unsigned long) &rfc);
2276 }
2277
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002278 if (result == L2CAP_CONF_SUCCESS) {
2279 /* Configure output options and let the other side know
2280 * which ones we don't like. */
2281
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002282 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2283 result = L2CAP_CONF_UNACCEPT;
2284 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002285 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002286 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002287 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002288 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002289
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002290 if (remote_efs) {
2291 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2292 efs.stype != L2CAP_SERV_NOTRAFIC &&
2293 efs.stype != chan->local_stype) {
2294
2295 result = L2CAP_CONF_UNACCEPT;
2296
2297 if (chan->num_conf_req >= 1)
2298 return -ECONNREFUSED;
2299
2300 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002301 sizeof(efs),
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002302 (unsigned long) &efs);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002303 } else {
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002304 /* Send PENDING Conf Rsp */
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002305 result = L2CAP_CONF_PENDING;
2306 set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002307 }
2308 }
2309
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002310 switch (rfc.mode) {
2311 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002312 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002313 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002314 break;
2315
2316 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002317 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2318 chan->remote_tx_win = rfc.txwin_size;
2319 else
2320 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2321
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002322 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002323
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002324 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2325 chan->conn->mtu -
2326 L2CAP_EXT_HDR_SIZE -
2327 L2CAP_SDULEN_SIZE -
2328 L2CAP_FCS_SIZE);
2329 rfc.max_pdu_size = cpu_to_le16(size);
2330 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002331
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002332 rfc.retrans_timeout =
2333 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2334 rfc.monitor_timeout =
2335 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002336
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002337 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002338
2339 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2340 sizeof(rfc), (unsigned long) &rfc);
2341
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002342 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2343 chan->remote_id = efs.id;
2344 chan->remote_stype = efs.stype;
2345 chan->remote_msdu = le16_to_cpu(efs.msdu);
2346 chan->remote_flush_to =
2347 le32_to_cpu(efs.flush_to);
2348 chan->remote_acc_lat =
2349 le32_to_cpu(efs.acc_lat);
2350 chan->remote_sdu_itime =
2351 le32_to_cpu(efs.sdu_itime);
2352 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2353 sizeof(efs), (unsigned long) &efs);
2354 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002355 break;
2356
2357 case L2CAP_MODE_STREAMING:
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002358 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2359 chan->conn->mtu -
2360 L2CAP_EXT_HDR_SIZE -
2361 L2CAP_SDULEN_SIZE -
2362 L2CAP_FCS_SIZE);
2363 rfc.max_pdu_size = cpu_to_le16(size);
2364 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002365
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002366 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002367
2368 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2369 sizeof(rfc), (unsigned long) &rfc);
2370
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002371 break;
2372
2373 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002374 result = L2CAP_CONF_UNACCEPT;
2375
2376 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002377 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002378 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002379
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002380 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002381 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002382 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002383 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002384 rsp->result = cpu_to_le16(result);
2385 rsp->flags = cpu_to_le16(0x0000);
2386
2387 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388}
2389
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002390static 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 -03002391{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002392 struct l2cap_conf_req *req = data;
2393 void *ptr = req->data;
2394 int type, olen;
2395 unsigned long val;
Mat Martineau36e999a2011-12-08 17:23:21 -08002396 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002397 struct l2cap_conf_efs efs;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002398
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002399 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002400
2401 while (len >= L2CAP_CONF_OPT_SIZE) {
2402 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2403
2404 switch (type) {
2405 case L2CAP_CONF_MTU:
2406 if (val < L2CAP_DEFAULT_MIN_MTU) {
2407 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002408 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002409 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002410 chan->imtu = val;
2411 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002412 break;
2413
2414 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002415 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002416 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002417 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002418 break;
2419
2420 case L2CAP_CONF_RFC:
2421 if (olen == sizeof(rfc))
2422 memcpy(&rfc, (void *)val, olen);
2423
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002424 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002425 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002426 return -ECONNREFUSED;
2427
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002428 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002429
2430 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2431 sizeof(rfc), (unsigned long) &rfc);
2432 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002433
2434 case L2CAP_CONF_EWS:
2435 chan->tx_win = min_t(u16, val,
2436 L2CAP_DEFAULT_EXT_WINDOW);
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002437 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2438 chan->tx_win);
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002439 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002440
2441 case L2CAP_CONF_EFS:
2442 if (olen == sizeof(efs))
2443 memcpy(&efs, (void *)val, olen);
2444
2445 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2446 efs.stype != L2CAP_SERV_NOTRAFIC &&
2447 efs.stype != chan->local_stype)
2448 return -ECONNREFUSED;
2449
2450 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2451 sizeof(efs), (unsigned long) &efs);
2452 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002453 }
2454 }
2455
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002456 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002457 return -ECONNREFUSED;
2458
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002459 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002460
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002461 if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002462 switch (rfc.mode) {
2463 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002464 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2465 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2466 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002467
2468 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2469 chan->local_msdu = le16_to_cpu(efs.msdu);
2470 chan->local_sdu_itime =
2471 le32_to_cpu(efs.sdu_itime);
2472 chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
2473 chan->local_flush_to =
2474 le32_to_cpu(efs.flush_to);
2475 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002476 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002477
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002478 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002479 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002480 }
2481 }
2482
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002483 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002484 req->flags = cpu_to_le16(0x0000);
2485
2486 return ptr - data;
2487}
2488
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002489static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490{
2491 struct l2cap_conf_rsp *rsp = data;
2492 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002494 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002496 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002497 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002498 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499
2500 return ptr - data;
2501}
2502
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002503void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002504{
2505 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002506 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002507 u8 buf[128];
2508
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002509 rsp.scid = cpu_to_le16(chan->dcid);
2510 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002511 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2512 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2513 l2cap_send_cmd(conn, chan->ident,
2514 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2515
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002516 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002517 return;
2518
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002519 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2520 l2cap_build_conf_req(chan, buf), buf);
2521 chan->num_conf_req++;
2522}
2523
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002524static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002525{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002526 int type, olen;
2527 unsigned long val;
2528 struct l2cap_conf_rfc rfc;
2529
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002530 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002531
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002532 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002533 return;
2534
2535 while (len >= L2CAP_CONF_OPT_SIZE) {
2536 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2537
2538 switch (type) {
2539 case L2CAP_CONF_RFC:
2540 if (olen == sizeof(rfc))
2541 memcpy(&rfc, (void *)val, olen);
2542 goto done;
2543 }
2544 }
2545
Mat Martineau36e999a2011-12-08 17:23:21 -08002546 /* Use sane default values in case a misbehaving remote device
2547 * did not send an RFC option.
2548 */
2549 rfc.mode = chan->mode;
2550 rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
2551 rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
2552 rfc.max_pdu_size = cpu_to_le16(chan->imtu);
2553
2554 BT_ERR("Expected RFC option was not found, using defaults");
2555
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002556done:
2557 switch (rfc.mode) {
2558 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002559 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2560 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2561 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002562 break;
2563 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002564 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002565 }
2566}
2567
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002568static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2569{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002570 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002571
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002572 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002573 return 0;
2574
2575 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2576 cmd->ident == conn->info_ident) {
Ulisses Furquim371fd832011-12-21 20:02:36 -02002577 __cancel_delayed_work(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002578
2579 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002580 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002581
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002582 l2cap_conn_start(conn);
2583 }
2584
2585 return 0;
2586}
2587
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2589{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2591 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002592 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002593 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002594 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595
2596 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002597 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598
2599 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2600
2601 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002602 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2603 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604 result = L2CAP_CR_BAD_PSM;
2605 goto sendresp;
2606 }
2607
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002608 parent = pchan->sk;
2609
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002610 lock_sock(parent);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002611
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002612 /* Check if the ACL is secure enough (if not SDP) */
2613 if (psm != cpu_to_le16(0x0001) &&
2614 !hci_conn_check_link_mode(conn->hcon)) {
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002615 conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002616 result = L2CAP_CR_SEC_BLOCK;
2617 goto response;
2618 }
2619
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 result = L2CAP_CR_NO_MEM;
2621
2622 /* Check for backlog size */
2623 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002624 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625 goto response;
2626 }
2627
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002628 chan = pchan->ops->new_connection(pchan->data);
2629 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630 goto response;
2631
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002632 sk = chan->sk;
2633
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002635 if (__l2cap_get_chan_by_dcid(conn, scid)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002637 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638 goto response;
2639 }
2640
2641 hci_conn_hold(conn->hcon);
2642
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643 bacpy(&bt_sk(sk)->src, conn->src);
2644 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002645 chan->psm = psm;
2646 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002648 bt_accept_enqueue(parent, sk);
2649
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02002650 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002651
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002652 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002654 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002656 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657
Marcel Holtmann984947d2009-02-06 23:35:19 +01002658 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02002659 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002660 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002661 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002662 result = L2CAP_CR_PEND;
2663 status = L2CAP_CS_AUTHOR_PEND;
2664 parent->sk_data_ready(parent, 0);
2665 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002666 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002667 result = L2CAP_CR_SUCCESS;
2668 status = L2CAP_CS_NO_INFO;
2669 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002670 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002671 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002672 result = L2CAP_CR_PEND;
2673 status = L2CAP_CS_AUTHEN_PEND;
2674 }
2675 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002676 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002677 result = L2CAP_CR_PEND;
2678 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679 }
2680
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681response:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002682 release_sock(parent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683
2684sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002685 rsp.scid = cpu_to_le16(scid);
2686 rsp.dcid = cpu_to_le16(dcid);
2687 rsp.result = cpu_to_le16(result);
2688 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002690
2691 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2692 struct l2cap_info_req info;
2693 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2694
2695 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2696 conn->info_ident = l2cap_get_ident(conn);
2697
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02002698 schedule_delayed_work(&conn->info_timer,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002699 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2700
2701 l2cap_send_cmd(conn, conn->info_ident,
2702 L2CAP_INFO_REQ, sizeof(info), &info);
2703 }
2704
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002705 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002706 result == L2CAP_CR_SUCCESS) {
2707 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002708 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002709 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002710 l2cap_build_conf_req(chan, buf), buf);
2711 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002712 }
2713
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714 return 0;
2715}
2716
2717static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2718{
2719 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2720 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002721 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722 struct sock *sk;
2723 u8 req[128];
2724
2725 scid = __le16_to_cpu(rsp->scid);
2726 dcid = __le16_to_cpu(rsp->dcid);
2727 result = __le16_to_cpu(rsp->result);
2728 status = __le16_to_cpu(rsp->status);
2729
2730 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2731
2732 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002733 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002734 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002735 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002737 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002738 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002739 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 }
2741
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002742 sk = chan->sk;
2743
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744 switch (result) {
2745 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002746 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002747 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002748 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002749 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002750
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002751 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002752 break;
2753
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002755 l2cap_build_conf_req(chan, req), req);
2756 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757 break;
2758
2759 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002760 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 break;
2762
2763 default:
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002764 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 break;
2766 }
2767
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002768 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 return 0;
2770}
2771
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002772static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002773{
2774 /* FCS is enabled only in ERTM or streaming mode, if one or both
2775 * sides request it.
2776 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002777 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002778 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002779 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002780 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002781}
2782
Al Viro88219a02007-07-29 00:17:25 -07002783static 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 -07002784{
2785 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2786 u16 dcid, flags;
2787 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002788 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002790 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791
2792 dcid = __le16_to_cpu(req->dcid);
2793 flags = __le16_to_cpu(req->flags);
2794
2795 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2796
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002797 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002798 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799 return -ENOENT;
2800
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002801 sk = chan->sk;
2802
David S. Miller033b1142011-07-21 13:38:42 -07002803 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002804 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002805
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002806 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2807 rej.scid = cpu_to_le16(chan->scid);
2808 rej.dcid = cpu_to_le16(chan->dcid);
2809
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002810 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2811 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002812 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002813 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002814
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002815 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002816 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002817 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002818 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002819 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002820 L2CAP_CONF_REJECT, flags), rsp);
2821 goto unlock;
2822 }
2823
2824 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002825 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2826 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002827
2828 if (flags & 0x0001) {
2829 /* Incomplete config. Send empty response. */
2830 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002831 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002832 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833 goto unlock;
2834 }
2835
2836 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002837 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002838 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002839 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002841 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002843 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002844 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002845
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002846 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002847 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002848
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002849 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002850 goto unlock;
2851
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002852 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002853 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002854
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002855 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002856
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002857 chan->next_tx_seq = 0;
2858 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002859 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002860 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002861 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002862
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002864 goto unlock;
2865 }
2866
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002867 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002868 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002870 l2cap_build_conf_req(chan, buf), buf);
2871 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002872 }
2873
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002874 /* Got Conf Rsp PENDING from remote side and asume we sent
2875 Conf Rsp PENDING in the code above */
2876 if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
2877 test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2878
2879 /* check compatibility */
2880
2881 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2882 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2883
2884 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002885 l2cap_build_conf_rsp(chan, rsp,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002886 L2CAP_CONF_SUCCESS, 0x0000), rsp);
2887 }
2888
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889unlock:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002890 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891 return 0;
2892}
2893
2894static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2895{
2896 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2897 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002898 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002900 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901
2902 scid = __le16_to_cpu(rsp->scid);
2903 flags = __le16_to_cpu(rsp->flags);
2904 result = __le16_to_cpu(rsp->result);
2905
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002906 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2907 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002909 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002910 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002911 return 0;
2912
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002913 sk = chan->sk;
2914
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915 switch (result) {
2916 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002917 l2cap_conf_rfc_get(chan, rsp->data, len);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002918 clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002919 break;
2920
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002921 case L2CAP_CONF_PENDING:
2922 set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
2923
2924 if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2925 char buf[64];
2926
2927 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2928 buf, &result);
2929 if (len < 0) {
2930 l2cap_send_disconn_req(conn, chan, ECONNRESET);
2931 goto done;
2932 }
2933
2934 /* check compatibility */
2935
2936 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2937 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2938
2939 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002940 l2cap_build_conf_rsp(chan, buf,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002941 L2CAP_CONF_SUCCESS, 0x0000), buf);
2942 }
2943 goto done;
2944
Linus Torvalds1da177e2005-04-16 15:20:36 -07002945 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002946 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002947 char req[64];
2948
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002949 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002950 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002951 goto done;
2952 }
2953
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002954 /* throw out any old stored conf requests */
2955 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002956 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2957 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002958 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002959 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002960 goto done;
2961 }
2962
2963 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2964 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002965 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002966 if (result != L2CAP_CONF_SUCCESS)
2967 goto done;
2968 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969 }
2970
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002971 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002972 sk->sk_err = ECONNRESET;
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02002973 __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002974 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975 goto done;
2976 }
2977
2978 if (flags & 0x01)
2979 goto done;
2980
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002981 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002982
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002983 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002984 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002985
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002986 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002987 chan->next_tx_seq = 0;
2988 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002989 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002990 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002991 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002992
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993 l2cap_chan_ready(sk);
2994 }
2995
2996done:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002997 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998 return 0;
2999}
3000
3001static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3002{
3003 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3004 struct l2cap_disconn_rsp rsp;
3005 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003006 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 struct sock *sk;
3008
3009 scid = __le16_to_cpu(req->scid);
3010 dcid = __le16_to_cpu(req->dcid);
3011
3012 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3013
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003014 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003015 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016 return 0;
3017
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003018 sk = chan->sk;
3019
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003020 rsp.dcid = cpu_to_le16(chan->scid);
3021 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3023
3024 sk->sk_shutdown = SHUTDOWN_MASK;
3025
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003026 l2cap_chan_del(chan, ECONNRESET);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003027 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003029 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030 return 0;
3031}
3032
3033static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3034{
3035 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3036 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003037 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038 struct sock *sk;
3039
3040 scid = __le16_to_cpu(rsp->scid);
3041 dcid = __le16_to_cpu(rsp->dcid);
3042
3043 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3044
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003045 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003046 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047 return 0;
3048
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003049 sk = chan->sk;
3050
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003051 l2cap_chan_del(chan, 0);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003052 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003054 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055 return 0;
3056}
3057
3058static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3059{
3060 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061 u16 type;
3062
3063 type = __le16_to_cpu(req->type);
3064
3065 BT_DBG("type 0x%4.4x", type);
3066
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003067 if (type == L2CAP_IT_FEAT_MASK) {
3068 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003069 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003070 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3071 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3072 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003073 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003074 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3075 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003076 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003077 feat_mask |= L2CAP_FEAT_EXT_FLOW
3078 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003079
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003080 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003081 l2cap_send_cmd(conn, cmd->ident,
3082 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003083 } else if (type == L2CAP_IT_FIXED_CHAN) {
3084 u8 buf[12];
3085 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
Mat Martineau50a147c2011-11-02 16:18:34 -07003086
3087 if (enable_hs)
3088 l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
3089 else
3090 l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
3091
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003092 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3093 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003094 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003095 l2cap_send_cmd(conn, cmd->ident,
3096 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003097 } else {
3098 struct l2cap_info_rsp rsp;
3099 rsp.type = cpu_to_le16(type);
3100 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3101 l2cap_send_cmd(conn, cmd->ident,
3102 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3103 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104
3105 return 0;
3106}
3107
3108static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3109{
3110 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3111 u16 type, result;
3112
3113 type = __le16_to_cpu(rsp->type);
3114 result = __le16_to_cpu(rsp->result);
3115
3116 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3117
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003118 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3119 if (cmd->ident != conn->info_ident ||
3120 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3121 return 0;
3122
Ulisses Furquim371fd832011-12-21 20:02:36 -02003123 __cancel_delayed_work(&conn->info_timer);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003124
Ville Tervoadb08ed2010-08-04 09:43:33 +03003125 if (result != L2CAP_IR_SUCCESS) {
3126 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3127 conn->info_ident = 0;
3128
3129 l2cap_conn_start(conn);
3130
3131 return 0;
3132 }
3133
Marcel Holtmann984947d2009-02-06 23:35:19 +01003134 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003135 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003136
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003137 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003138 struct l2cap_info_req req;
3139 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3140
3141 conn->info_ident = l2cap_get_ident(conn);
3142
3143 l2cap_send_cmd(conn, conn->info_ident,
3144 L2CAP_INFO_REQ, sizeof(req), &req);
3145 } else {
3146 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3147 conn->info_ident = 0;
3148
3149 l2cap_conn_start(conn);
3150 }
3151 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003152 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003153 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003154
3155 l2cap_conn_start(conn);
3156 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003157
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158 return 0;
3159}
3160
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003161static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3162 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3163 void *data)
3164{
3165 struct l2cap_create_chan_req *req = data;
3166 struct l2cap_create_chan_rsp rsp;
3167 u16 psm, scid;
3168
3169 if (cmd_len != sizeof(*req))
3170 return -EPROTO;
3171
3172 if (!enable_hs)
3173 return -EINVAL;
3174
3175 psm = le16_to_cpu(req->psm);
3176 scid = le16_to_cpu(req->scid);
3177
3178 BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3179
3180 /* Placeholder: Always reject */
3181 rsp.dcid = 0;
3182 rsp.scid = cpu_to_le16(scid);
3183 rsp.result = L2CAP_CR_NO_MEM;
3184 rsp.status = L2CAP_CS_NO_INFO;
3185
3186 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3187 sizeof(rsp), &rsp);
3188
3189 return 0;
3190}
3191
3192static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3193 struct l2cap_cmd_hdr *cmd, void *data)
3194{
3195 BT_DBG("conn %p", conn);
3196
3197 return l2cap_connect_rsp(conn, cmd, data);
3198}
3199
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003200static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
3201 u16 icid, u16 result)
3202{
3203 struct l2cap_move_chan_rsp rsp;
3204
3205 BT_DBG("icid %d, result %d", icid, result);
3206
3207 rsp.icid = cpu_to_le16(icid);
3208 rsp.result = cpu_to_le16(result);
3209
3210 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
3211}
3212
3213static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
3214 struct l2cap_chan *chan, u16 icid, u16 result)
3215{
3216 struct l2cap_move_chan_cfm cfm;
3217 u8 ident;
3218
3219 BT_DBG("icid %d, result %d", icid, result);
3220
3221 ident = l2cap_get_ident(conn);
3222 if (chan)
3223 chan->ident = ident;
3224
3225 cfm.icid = cpu_to_le16(icid);
3226 cfm.result = cpu_to_le16(result);
3227
3228 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
3229}
3230
3231static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
3232 u16 icid)
3233{
3234 struct l2cap_move_chan_cfm_rsp rsp;
3235
3236 BT_DBG("icid %d", icid);
3237
3238 rsp.icid = cpu_to_le16(icid);
3239 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
3240}
3241
3242static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
3243 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3244{
3245 struct l2cap_move_chan_req *req = data;
3246 u16 icid = 0;
3247 u16 result = L2CAP_MR_NOT_ALLOWED;
3248
3249 if (cmd_len != sizeof(*req))
3250 return -EPROTO;
3251
3252 icid = le16_to_cpu(req->icid);
3253
3254 BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
3255
3256 if (!enable_hs)
3257 return -EINVAL;
3258
3259 /* Placeholder: Always refuse */
3260 l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
3261
3262 return 0;
3263}
3264
3265static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
3266 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3267{
3268 struct l2cap_move_chan_rsp *rsp = data;
3269 u16 icid, result;
3270
3271 if (cmd_len != sizeof(*rsp))
3272 return -EPROTO;
3273
3274 icid = le16_to_cpu(rsp->icid);
3275 result = le16_to_cpu(rsp->result);
3276
3277 BT_DBG("icid %d, result %d", icid, result);
3278
3279 /* Placeholder: Always unconfirmed */
3280 l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
3281
3282 return 0;
3283}
3284
3285static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
3286 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3287{
3288 struct l2cap_move_chan_cfm *cfm = data;
3289 u16 icid, result;
3290
3291 if (cmd_len != sizeof(*cfm))
3292 return -EPROTO;
3293
3294 icid = le16_to_cpu(cfm->icid);
3295 result = le16_to_cpu(cfm->result);
3296
3297 BT_DBG("icid %d, result %d", icid, result);
3298
3299 l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
3300
3301 return 0;
3302}
3303
3304static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
3305 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3306{
3307 struct l2cap_move_chan_cfm_rsp *rsp = data;
3308 u16 icid;
3309
3310 if (cmd_len != sizeof(*rsp))
3311 return -EPROTO;
3312
3313 icid = le16_to_cpu(rsp->icid);
3314
3315 BT_DBG("icid %d", icid);
3316
3317 return 0;
3318}
3319
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003320static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02003321 u16 to_multiplier)
3322{
3323 u16 max_latency;
3324
3325 if (min > max || min < 6 || max > 3200)
3326 return -EINVAL;
3327
3328 if (to_multiplier < 10 || to_multiplier > 3200)
3329 return -EINVAL;
3330
3331 if (max >= to_multiplier * 8)
3332 return -EINVAL;
3333
3334 max_latency = (to_multiplier * 8 / max) - 1;
3335 if (latency > 499 || latency > max_latency)
3336 return -EINVAL;
3337
3338 return 0;
3339}
3340
3341static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3342 struct l2cap_cmd_hdr *cmd, u8 *data)
3343{
3344 struct hci_conn *hcon = conn->hcon;
3345 struct l2cap_conn_param_update_req *req;
3346 struct l2cap_conn_param_update_rsp rsp;
3347 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003348 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02003349
3350 if (!(hcon->link_mode & HCI_LM_MASTER))
3351 return -EINVAL;
3352
3353 cmd_len = __le16_to_cpu(cmd->len);
3354 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3355 return -EPROTO;
3356
3357 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003358 min = __le16_to_cpu(req->min);
3359 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02003360 latency = __le16_to_cpu(req->latency);
3361 to_multiplier = __le16_to_cpu(req->to_multiplier);
3362
3363 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3364 min, max, latency, to_multiplier);
3365
3366 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003367
3368 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
3369 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02003370 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3371 else
3372 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3373
3374 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3375 sizeof(rsp), &rsp);
3376
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003377 if (!err)
3378 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
3379
Claudio Takahaside731152011-02-11 19:28:55 -02003380 return 0;
3381}
3382
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003383static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
3384 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
3385{
3386 int err = 0;
3387
3388 switch (cmd->code) {
3389 case L2CAP_COMMAND_REJ:
3390 l2cap_command_rej(conn, cmd, data);
3391 break;
3392
3393 case L2CAP_CONN_REQ:
3394 err = l2cap_connect_req(conn, cmd, data);
3395 break;
3396
3397 case L2CAP_CONN_RSP:
3398 err = l2cap_connect_rsp(conn, cmd, data);
3399 break;
3400
3401 case L2CAP_CONF_REQ:
3402 err = l2cap_config_req(conn, cmd, cmd_len, data);
3403 break;
3404
3405 case L2CAP_CONF_RSP:
3406 err = l2cap_config_rsp(conn, cmd, data);
3407 break;
3408
3409 case L2CAP_DISCONN_REQ:
3410 err = l2cap_disconnect_req(conn, cmd, data);
3411 break;
3412
3413 case L2CAP_DISCONN_RSP:
3414 err = l2cap_disconnect_rsp(conn, cmd, data);
3415 break;
3416
3417 case L2CAP_ECHO_REQ:
3418 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3419 break;
3420
3421 case L2CAP_ECHO_RSP:
3422 break;
3423
3424 case L2CAP_INFO_REQ:
3425 err = l2cap_information_req(conn, cmd, data);
3426 break;
3427
3428 case L2CAP_INFO_RSP:
3429 err = l2cap_information_rsp(conn, cmd, data);
3430 break;
3431
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003432 case L2CAP_CREATE_CHAN_REQ:
3433 err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3434 break;
3435
3436 case L2CAP_CREATE_CHAN_RSP:
3437 err = l2cap_create_channel_rsp(conn, cmd, data);
3438 break;
3439
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003440 case L2CAP_MOVE_CHAN_REQ:
3441 err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
3442 break;
3443
3444 case L2CAP_MOVE_CHAN_RSP:
3445 err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
3446 break;
3447
3448 case L2CAP_MOVE_CHAN_CFM:
3449 err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
3450 break;
3451
3452 case L2CAP_MOVE_CHAN_CFM_RSP:
3453 err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
3454 break;
3455
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003456 default:
3457 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3458 err = -EINVAL;
3459 break;
3460 }
3461
3462 return err;
3463}
3464
3465static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3466 struct l2cap_cmd_hdr *cmd, u8 *data)
3467{
3468 switch (cmd->code) {
3469 case L2CAP_COMMAND_REJ:
3470 return 0;
3471
3472 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003473 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003474
3475 case L2CAP_CONN_PARAM_UPDATE_RSP:
3476 return 0;
3477
3478 default:
3479 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3480 return -EINVAL;
3481 }
3482}
3483
3484static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3485 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486{
3487 u8 *data = skb->data;
3488 int len = skb->len;
3489 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003490 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003491
3492 l2cap_raw_recv(conn, skb);
3493
3494 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003495 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3497 data += L2CAP_CMD_HDR_SIZE;
3498 len -= L2CAP_CMD_HDR_SIZE;
3499
Al Viro88219a02007-07-29 00:17:25 -07003500 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501
Al Viro88219a02007-07-29 00:17:25 -07003502 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 -07003503
Al Viro88219a02007-07-29 00:17:25 -07003504 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003505 BT_DBG("corrupted command");
3506 break;
3507 }
3508
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003509 if (conn->hcon->type == LE_LINK)
3510 err = l2cap_le_sig_cmd(conn, &cmd, data);
3511 else
3512 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513
3514 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003515 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003516
3517 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003518
3519 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003520 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3522 }
3523
Al Viro88219a02007-07-29 00:17:25 -07003524 data += cmd_len;
3525 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003526 }
3527
3528 kfree_skb(skb);
3529}
3530
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003531static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003532{
3533 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003534 int hdr_size;
3535
3536 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3537 hdr_size = L2CAP_EXT_HDR_SIZE;
3538 else
3539 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003540
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003541 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003542 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003543 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3544 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3545
3546 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003547 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003548 }
3549 return 0;
3550}
3551
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003552static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003553{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003554 u32 control = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003555
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003556 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003557
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003558 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003559
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003560 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003561 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003562 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003563 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003564 }
3565
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003566 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003567 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003568
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003569 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003570
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003571 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003572 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003573 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003574 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003575 }
3576}
3577
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003578static 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 -03003579{
3580 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003581 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003582
3583 bt_cb(skb)->tx_seq = tx_seq;
3584 bt_cb(skb)->sar = sar;
3585
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003586 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003587
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003588 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003589
Szymon Janc039d9572011-11-16 09:32:19 +01003590 while (next_skb) {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003591 if (bt_cb(next_skb)->tx_seq == tx_seq)
3592 return -EINVAL;
3593
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003594 next_tx_seq_offset = __seq_offset(chan,
3595 bt_cb(next_skb)->tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003596
3597 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003598 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003599 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003600 }
3601
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003602 if (skb_queue_is_last(&chan->srej_q, next_skb))
Szymon Janc039d9572011-11-16 09:32:19 +01003603 next_skb = NULL;
3604 else
3605 next_skb = skb_queue_next(&chan->srej_q, next_skb);
3606 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003607
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003608 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003609
3610 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003611}
3612
Mat Martineau84084a32011-07-22 14:54:00 -07003613static void append_skb_frag(struct sk_buff *skb,
3614 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003615{
Mat Martineau84084a32011-07-22 14:54:00 -07003616 /* skb->len reflects data in skb as well as all fragments
3617 * skb->data_len reflects only data in fragments
3618 */
3619 if (!skb_has_frag_list(skb))
3620 skb_shinfo(skb)->frag_list = new_frag;
3621
3622 new_frag->next = NULL;
3623
3624 (*last_frag)->next = new_frag;
3625 *last_frag = new_frag;
3626
3627 skb->len += new_frag->len;
3628 skb->data_len += new_frag->len;
3629 skb->truesize += new_frag->truesize;
3630}
3631
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003632static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
Mat Martineau84084a32011-07-22 14:54:00 -07003633{
3634 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003635
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003636 switch (__get_ctrl_sar(chan, control)) {
3637 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003638 if (chan->sdu)
3639 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003640
Mat Martineau84084a32011-07-22 14:54:00 -07003641 err = chan->ops->recv(chan->data, skb);
3642 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003643
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003644 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003645 if (chan->sdu)
3646 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003647
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003648 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003649 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003650
Mat Martineau84084a32011-07-22 14:54:00 -07003651 if (chan->sdu_len > chan->imtu) {
3652 err = -EMSGSIZE;
3653 break;
3654 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003655
Mat Martineau84084a32011-07-22 14:54:00 -07003656 if (skb->len >= chan->sdu_len)
3657 break;
3658
3659 chan->sdu = skb;
3660 chan->sdu_last_frag = skb;
3661
3662 skb = NULL;
3663 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003664 break;
3665
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003666 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003667 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003668 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003669
Mat Martineau84084a32011-07-22 14:54:00 -07003670 append_skb_frag(chan->sdu, skb,
3671 &chan->sdu_last_frag);
3672 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003673
Mat Martineau84084a32011-07-22 14:54:00 -07003674 if (chan->sdu->len >= chan->sdu_len)
3675 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003676
Mat Martineau84084a32011-07-22 14:54:00 -07003677 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003678 break;
3679
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003680 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003681 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003682 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003683
Mat Martineau84084a32011-07-22 14:54:00 -07003684 append_skb_frag(chan->sdu, skb,
3685 &chan->sdu_last_frag);
3686 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003687
Mat Martineau84084a32011-07-22 14:54:00 -07003688 if (chan->sdu->len != chan->sdu_len)
3689 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003690
Mat Martineau84084a32011-07-22 14:54:00 -07003691 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003692
Mat Martineau84084a32011-07-22 14:54:00 -07003693 if (!err) {
3694 /* Reassembly complete */
3695 chan->sdu = NULL;
3696 chan->sdu_last_frag = NULL;
3697 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003698 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003699 break;
3700 }
3701
Mat Martineau84084a32011-07-22 14:54:00 -07003702 if (err) {
3703 kfree_skb(skb);
3704 kfree_skb(chan->sdu);
3705 chan->sdu = NULL;
3706 chan->sdu_last_frag = NULL;
3707 chan->sdu_len = 0;
3708 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003709
Mat Martineau84084a32011-07-22 14:54:00 -07003710 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003711}
3712
Mat Martineau26f880d2011-07-07 09:39:01 -07003713static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003714{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003715 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003716
Mat Martineau26f880d2011-07-07 09:39:01 -07003717 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003718
Mat Martineau26f880d2011-07-07 09:39:01 -07003719 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3720
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003721 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003722 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Mat Martineau26f880d2011-07-07 09:39:01 -07003723 l2cap_send_sframe(chan, control);
3724
3725 set_bit(CONN_RNR_SENT, &chan->conn_state);
3726
3727 __clear_ack_timer(chan);
3728}
3729
3730static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3731{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003732 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003733
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003734 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003735 goto done;
3736
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003737 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003738 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003739 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003740 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003741 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003742
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003743 __clear_retrans_timer(chan);
3744 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003745
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003746 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003747
3748done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003749 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3750 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003751
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003752 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003753}
3754
Mat Martineaue3281402011-07-07 09:39:02 -07003755void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003756{
Mat Martineaue3281402011-07-07 09:39:02 -07003757 if (chan->mode == L2CAP_MODE_ERTM) {
3758 if (busy)
3759 l2cap_ertm_enter_local_busy(chan);
3760 else
3761 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003762 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003763}
3764
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003765static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003766{
3767 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003768 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003769
Mat Martineaue3281402011-07-07 09:39:02 -07003770 while ((skb = skb_peek(&chan->srej_q)) &&
3771 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3772 int err;
3773
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003774 if (bt_cb(skb)->tx_seq != tx_seq)
3775 break;
3776
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003777 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003778 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003779 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003780
3781 if (err < 0) {
3782 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3783 break;
3784 }
3785
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003786 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
3787 tx_seq = __next_seq(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003788 }
3789}
3790
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003791static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003792{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003793 struct srej_list *l, *tmp;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003794 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003795
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003796 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003797 if (l->tx_seq == tx_seq) {
3798 list_del(&l->list);
3799 kfree(l);
3800 return;
3801 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003802 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003803 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003804 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003805 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003806 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003807 }
3808}
3809
Szymon Jancaef89f22011-11-16 09:32:18 +01003810static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003811{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003812 struct srej_list *new;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003813 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003814
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003815 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003816 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003817 control |= __set_reqseq(chan, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003818 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003819
3820 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Szymon Jancaef89f22011-11-16 09:32:18 +01003821 if (!new)
3822 return -ENOMEM;
3823
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003824 new->tx_seq = chan->expected_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003825
3826 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
3827
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003828 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003829 }
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003830
3831 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Szymon Jancaef89f22011-11-16 09:32:18 +01003832
3833 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003834}
3835
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003836static 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 -03003837{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003838 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003839 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003840 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003841 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003842 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003843 int err = 0;
3844
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003845 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 -03003846 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003847
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003848 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003849 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003850 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003851 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003852 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003853 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003854 }
3855
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003856 chan->expected_ack_seq = req_seq;
3857 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003858
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003859 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003860
3861 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003862 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003863 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003864 goto drop;
3865 }
3866
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003867 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003868 goto drop;
3869
Mat Martineau02f1b642011-06-29 14:35:19 -07003870 if (tx_seq == chan->expected_tx_seq)
3871 goto expected;
3872
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003873 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003874 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003875
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003876 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003877 struct srej_list, list);
3878 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003879 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003880 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003881
3882 list_del(&first->list);
3883 kfree(first);
3884
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003885 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003886 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003887 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003888 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003889 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003890 }
3891 } else {
3892 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003893
3894 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003895 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003896 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003897
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003898 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003899 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003900 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003901 return 0;
3902 }
3903 }
Szymon Jancaef89f22011-11-16 09:32:18 +01003904
3905 err = l2cap_send_srejframe(chan, tx_seq);
3906 if (err < 0) {
3907 l2cap_send_disconn_req(chan->conn, chan, -err);
3908 return err;
3909 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003910 }
3911 } else {
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003912 expected_tx_seq_offset = __seq_offset(chan,
3913 chan->expected_tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003914
3915 /* duplicated tx_seq */
3916 if (tx_seq_offset < expected_tx_seq_offset)
3917 goto drop;
3918
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003919 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003920
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003921 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003922
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003923 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003924 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003925
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003926 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003927 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003928
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003929 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003930
Szymon Jancaef89f22011-11-16 09:32:18 +01003931 err = l2cap_send_srejframe(chan, tx_seq);
3932 if (err < 0) {
3933 l2cap_send_disconn_req(chan->conn, chan, -err);
3934 return err;
3935 }
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003936
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003937 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003938 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003939 return 0;
3940
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003941expected:
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003942 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003943
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003944 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003945 bt_cb(skb)->tx_seq = tx_seq;
3946 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003947 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003948 return 0;
3949 }
3950
Mat Martineau84084a32011-07-22 14:54:00 -07003951 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003952 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
3953
Mat Martineaue3281402011-07-07 09:39:02 -07003954 if (err < 0) {
3955 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3956 return err;
3957 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003958
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003959 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003960 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003961 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003962 }
3963
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003964
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003965 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3966 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003967 l2cap_send_ack(chan);
Gustavo F. Padovan4d611e42011-06-23 19:30:48 -03003968 else
3969 __set_ack_timer(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003970
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003971 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003972
3973drop:
3974 kfree_skb(skb);
3975 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003976}
3977
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003978static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003979{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003980 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003981 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003982
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003983 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003984 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003985
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003986 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003987 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3988 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3989 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003990 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003991 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003992
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003993 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003994 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003995 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003996 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003997 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003998
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003999 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004000 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004001
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004002 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004003 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004004
4005 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004006 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004007 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004008 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004009
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004010 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4011 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004012 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02004013 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004014 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004015 }
4016}
4017
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004018static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004019{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004020 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004021
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004022 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004023
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004024 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004025
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004026 chan->expected_ack_seq = tx_seq;
4027 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004028
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004029 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004030 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004031 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004032 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004033 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004034
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004035 if (test_bit(CONN_WAIT_F, &chan->conn_state))
4036 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004037 }
4038}
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004039static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004040{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004041 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004042
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004043 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004044
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004045 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004046
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004047 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004048 chan->expected_ack_seq = tx_seq;
4049 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004050
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004051 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004052 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004053
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004054 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004055
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004056 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004057 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004058 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004059 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004060 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004061 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004062 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004063 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004064 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004065 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004066 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004067 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004068 if (test_bit(CONN_WAIT_F, &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 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004071 }
4072 }
4073}
4074
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004075static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004076{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004077 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004078
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004079 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004080
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004081 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004082 chan->expected_ack_seq = tx_seq;
4083 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004084
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004085 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004086 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004087
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004088 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004089 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004090 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004091 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004092 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004093 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004094
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004095 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004096 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004097 } else {
4098 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4099 l2cap_send_sframe(chan, rx_control);
4100 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004101}
4102
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004103static 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 -03004104{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004105 BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004106
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004107 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004108 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004109 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004110 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004111 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004112 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004113 }
4114
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004115 switch (__get_ctrl_super(chan, rx_control)) {
4116 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004117 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004118 break;
4119
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004120 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004121 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004122 break;
4123
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004124 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004125 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004126 break;
4127
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004128 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004129 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004130 break;
4131 }
4132
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004133 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004134 return 0;
4135}
4136
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004137static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
4138{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004139 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004140 u32 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004141 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004142 int len, next_tx_seq_offset, req_seq_offset;
4143
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004144 control = __get_control(chan, skb->data);
4145 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004146 len = skb->len;
4147
4148 /*
4149 * We can just drop the corrupted I-frame here.
4150 * Receiver will miss it and start proper recovery
4151 * procedures and ask retransmission.
4152 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004153 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004154 goto drop;
4155
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004156 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004157 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004158
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004159 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004160 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004161
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004162 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004163 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004164 goto drop;
4165 }
4166
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004167 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004168
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004169 req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4170
4171 next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4172 chan->expected_ack_seq);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004173
4174 /* check for invalid req-seq */
4175 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004176 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004177 goto drop;
4178 }
4179
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004180 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004181 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004182 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004183 goto drop;
4184 }
4185
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004186 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004187 } else {
4188 if (len != 0) {
4189 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004190 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004191 goto drop;
4192 }
4193
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004194 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004195 }
4196
4197 return 0;
4198
4199drop:
4200 kfree_skb(skb);
4201 return 0;
4202}
4203
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4205{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004206 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07004207 struct sock *sk = NULL;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004208 u32 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004209 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004210 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004211
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004212 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004213 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214 BT_DBG("unknown cid 0x%4.4x", cid);
4215 goto drop;
4216 }
4217
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004218 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004219
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004220 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004221
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004222 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004223 goto drop;
4224
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004225 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004226 case L2CAP_MODE_BASIC:
4227 /* If socket recv buffers overflows we drop data here
4228 * which is *bad* because L2CAP has to be reliable.
4229 * But we don't have any other choice. L2CAP doesn't
4230 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004232 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004233 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004234
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004235 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004236 goto done;
4237 break;
4238
4239 case L2CAP_MODE_ERTM:
Gustavo F. Padovaneb403a12011-06-24 01:54:50 -03004240 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004241
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004242 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004243
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004244 case L2CAP_MODE_STREAMING:
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004245 control = __get_control(chan, skb->data);
4246 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004247 len = skb->len;
4248
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004249 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004250 goto drop;
4251
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004252 if (__is_sar_start(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004253 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004254
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004255 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004256 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004257
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004258 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004259 goto drop;
4260
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004261 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004262
Mat Martineau84084a32011-07-22 14:54:00 -07004263 if (chan->expected_tx_seq != tx_seq) {
4264 /* Frame(s) missing - must discard partial SDU */
4265 kfree_skb(chan->sdu);
4266 chan->sdu = NULL;
4267 chan->sdu_last_frag = NULL;
4268 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004269
Mat Martineau84084a32011-07-22 14:54:00 -07004270 /* TODO: Notify userland of missing data */
4271 }
4272
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004273 chan->expected_tx_seq = __next_seq(chan, tx_seq);
Mat Martineau84084a32011-07-22 14:54:00 -07004274
4275 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
4276 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004277
4278 goto done;
4279
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004280 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004281 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004282 break;
4283 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004284
4285drop:
4286 kfree_skb(skb);
4287
4288done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004289 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004290 release_sock(sk);
Marcel Holtmann01394182006-07-03 10:02:46 +02004291
Linus Torvalds1da177e2005-04-16 15:20:36 -07004292 return 0;
4293}
4294
Al Viro8e036fc2007-07-29 00:16:36 -07004295static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004296{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004297 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004298 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004300 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
4301 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004302 goto drop;
4303
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004304 sk = chan->sk;
4305
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004306 lock_sock(sk);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00004307
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308 BT_DBG("sk %p, len %d", sk, skb->len);
4309
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004310 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311 goto drop;
4312
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004313 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314 goto drop;
4315
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004316 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317 goto done;
4318
4319drop:
4320 kfree_skb(skb);
4321
4322done:
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03004323 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004324 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004325 return 0;
4326}
4327
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004328static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
4329{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004330 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004331 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004332
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004333 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
4334 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004335 goto drop;
4336
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004337 sk = chan->sk;
4338
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004339 lock_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004340
4341 BT_DBG("sk %p, len %d", sk, skb->len);
4342
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004343 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004344 goto drop;
4345
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004346 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004347 goto drop;
4348
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004349 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004350 goto done;
4351
4352drop:
4353 kfree_skb(skb);
4354
4355done:
4356 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004357 release_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004358 return 0;
4359}
4360
Linus Torvalds1da177e2005-04-16 15:20:36 -07004361static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4362{
4363 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004364 u16 cid, len;
4365 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004366
4367 skb_pull(skb, L2CAP_HDR_SIZE);
4368 cid = __le16_to_cpu(lh->cid);
4369 len = __le16_to_cpu(lh->len);
4370
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004371 if (len != skb->len) {
4372 kfree_skb(skb);
4373 return;
4374 }
4375
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4377
4378 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004379 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004380 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004381 l2cap_sig_channel(conn, skb);
4382 break;
4383
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004384 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004385 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004386 skb_pull(skb, 2);
4387 l2cap_conless_channel(conn, psm, skb);
4388 break;
4389
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004390 case L2CAP_CID_LE_DATA:
4391 l2cap_att_channel(conn, cid, skb);
4392 break;
4393
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004394 case L2CAP_CID_SMP:
4395 if (smp_sig_channel(conn, skb))
4396 l2cap_conn_del(conn->hcon, EACCES);
4397 break;
4398
Linus Torvalds1da177e2005-04-16 15:20:36 -07004399 default:
4400 l2cap_data_channel(conn, cid, skb);
4401 break;
4402 }
4403}
4404
4405/* ---- L2CAP interface with lower layer (HCI) ---- */
4406
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004407int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004408{
4409 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004410 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004411
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4413
4414 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004415 read_lock(&chan_list_lock);
4416 list_for_each_entry(c, &chan_list, global_l) {
4417 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004418
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004419 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420 continue;
4421
4422 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004423 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004424 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004425 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004426 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004427 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4428 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004429 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004430 lm2 |= HCI_LM_MASTER;
4431 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004432 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004433 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434
4435 return exact ? lm1 : lm2;
4436}
4437
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004438int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439{
Marcel Holtmann01394182006-07-03 10:02:46 +02004440 struct l2cap_conn *conn;
4441
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4443
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004445 conn = l2cap_conn_add(hcon, status);
4446 if (conn)
4447 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004448 } else
Joe Perchese1750722011-06-29 18:18:29 -07004449 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004450
4451 return 0;
4452}
4453
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004454int l2cap_disconn_ind(struct hci_conn *hcon)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004455{
4456 struct l2cap_conn *conn = hcon->l2cap_data;
4457
4458 BT_DBG("hcon %p", hcon);
4459
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004460 if (!conn)
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02004461 return HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01004462 return conn->disc_reason;
4463}
4464
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004465int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004466{
4467 BT_DBG("hcon %p reason %d", hcon, reason);
4468
Joe Perchese1750722011-06-29 18:18:29 -07004469 l2cap_conn_del(hcon, bt_to_errno(reason));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004470 return 0;
4471}
4472
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004473static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004474{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004475 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004476 return;
4477
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004478 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004479 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004480 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02004481 __set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004482 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004483 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004484 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004485 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004486 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004487 }
4488}
4489
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004490int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004491{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004492 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004493 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004494
Marcel Holtmann01394182006-07-03 10:02:46 +02004495 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004496 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004497
Linus Torvalds1da177e2005-04-16 15:20:36 -07004498 BT_DBG("conn %p", conn);
4499
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004500 if (hcon->type == LE_LINK) {
4501 smp_distribute_keys(conn, 0);
Ulisses Furquim371fd832011-12-21 20:02:36 -02004502 __cancel_delayed_work(&conn->security_timer);
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004503 }
4504
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02004505 rcu_read_lock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004506
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02004507 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004508 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004509
Linus Torvalds1da177e2005-04-16 15:20:36 -07004510 bh_lock_sock(sk);
4511
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004512 BT_DBG("chan->scid %d", chan->scid);
4513
4514 if (chan->scid == L2CAP_CID_LE_DATA) {
4515 if (!status && encrypt) {
4516 chan->sec_level = hcon->sec_level;
4517 l2cap_chan_ready(sk);
4518 }
4519
4520 bh_unlock_sock(sk);
4521 continue;
4522 }
4523
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004524 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004525 bh_unlock_sock(sk);
4526 continue;
4527 }
4528
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004529 if (!status && (chan->state == BT_CONNECTED ||
4530 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004531 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004532 bh_unlock_sock(sk);
4533 continue;
4534 }
4535
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004536 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004537 if (!status) {
4538 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004539 req.scid = cpu_to_le16(chan->scid);
4540 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004541
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004542 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004543 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004544
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004545 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004546 L2CAP_CONN_REQ, sizeof(req), &req);
4547 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004548 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02004549 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004550 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004551 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004552 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004553 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004554
4555 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004556 if (bt_sk(sk)->defer_setup) {
4557 struct sock *parent = bt_sk(sk)->parent;
4558 res = L2CAP_CR_PEND;
4559 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004560 if (parent)
4561 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004562 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004563 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004564 res = L2CAP_CR_SUCCESS;
4565 stat = L2CAP_CS_NO_INFO;
4566 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004567 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004568 l2cap_state_change(chan, BT_DISCONN);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02004569 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004570 res = L2CAP_CR_SEC_BLOCK;
4571 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004572 }
4573
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004574 rsp.scid = cpu_to_le16(chan->dcid);
4575 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004576 rsp.result = cpu_to_le16(res);
4577 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004578 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4579 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004580 }
4581
Linus Torvalds1da177e2005-04-16 15:20:36 -07004582 bh_unlock_sock(sk);
4583 }
4584
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02004585 rcu_read_unlock();
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004586
Linus Torvalds1da177e2005-04-16 15:20:36 -07004587 return 0;
4588}
4589
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004590int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004591{
4592 struct l2cap_conn *conn = hcon->l2cap_data;
4593
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004594 if (!conn)
4595 conn = l2cap_conn_add(hcon, 0);
4596
4597 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004598 goto drop;
4599
4600 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4601
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004602 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004603 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004604 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004605 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004606 int len;
4607
4608 if (conn->rx_len) {
4609 BT_ERR("Unexpected start frame (len %d)", skb->len);
4610 kfree_skb(conn->rx_skb);
4611 conn->rx_skb = NULL;
4612 conn->rx_len = 0;
4613 l2cap_conn_unreliable(conn, ECOMM);
4614 }
4615
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004616 /* Start fragment always begin with Basic L2CAP header */
4617 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004618 BT_ERR("Frame is too short (len %d)", skb->len);
4619 l2cap_conn_unreliable(conn, ECOMM);
4620 goto drop;
4621 }
4622
4623 hdr = (struct l2cap_hdr *) skb->data;
4624 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004625 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004626
4627 if (len == skb->len) {
4628 /* Complete frame received */
4629 l2cap_recv_frame(conn, skb);
4630 return 0;
4631 }
4632
4633 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4634
4635 if (skb->len > len) {
4636 BT_ERR("Frame is too long (len %d, expected len %d)",
4637 skb->len, len);
4638 l2cap_conn_unreliable(conn, ECOMM);
4639 goto drop;
4640 }
4641
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004642 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004643
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004644 if (chan && chan->sk) {
4645 struct sock *sk = chan->sk;
4646
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004647 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004648 BT_ERR("Frame exceeding recv MTU (len %d, "
4649 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004650 chan->imtu);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004651 release_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004652 l2cap_conn_unreliable(conn, ECOMM);
4653 goto drop;
4654 }
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004655 release_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004656 }
4657
Linus Torvalds1da177e2005-04-16 15:20:36 -07004658 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03004659 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4660 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004661 goto drop;
4662
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004663 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004664 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004665 conn->rx_len = len - skb->len;
4666 } else {
4667 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4668
4669 if (!conn->rx_len) {
4670 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4671 l2cap_conn_unreliable(conn, ECOMM);
4672 goto drop;
4673 }
4674
4675 if (skb->len > conn->rx_len) {
4676 BT_ERR("Fragment is too long (len %d, expected %d)",
4677 skb->len, conn->rx_len);
4678 kfree_skb(conn->rx_skb);
4679 conn->rx_skb = NULL;
4680 conn->rx_len = 0;
4681 l2cap_conn_unreliable(conn, ECOMM);
4682 goto drop;
4683 }
4684
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004685 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004686 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004687 conn->rx_len -= skb->len;
4688
4689 if (!conn->rx_len) {
4690 /* Complete frame received */
4691 l2cap_recv_frame(conn, conn->rx_skb);
4692 conn->rx_skb = NULL;
4693 }
4694 }
4695
4696drop:
4697 kfree_skb(skb);
4698 return 0;
4699}
4700
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004701static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004702{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004703 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004704
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02004705 read_lock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004706
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004707 list_for_each_entry(c, &chan_list, global_l) {
4708 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004709
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004710 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 +01004711 batostr(&bt_sk(sk)->src),
4712 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004713 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004714 c->scid, c->dcid, c->imtu, c->omtu,
4715 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004716}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004717
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02004718 read_unlock(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004719
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004720 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004721}
4722
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004723static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4724{
4725 return single_open(file, l2cap_debugfs_show, inode->i_private);
4726}
4727
4728static const struct file_operations l2cap_debugfs_fops = {
4729 .open = l2cap_debugfs_open,
4730 .read = seq_read,
4731 .llseek = seq_lseek,
4732 .release = single_release,
4733};
4734
4735static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004736
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004737int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004738{
4739 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004740
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004741 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004742 if (err < 0)
4743 return err;
4744
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004745 if (bt_debugfs) {
4746 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4747 bt_debugfs, NULL, &l2cap_debugfs_fops);
4748 if (!l2cap_debugfs)
4749 BT_ERR("Failed to create L2CAP debug file");
4750 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004751
Linus Torvalds1da177e2005-04-16 15:20:36 -07004752 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004753}
4754
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004755void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004756{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004757 debugfs_remove(l2cap_debugfs);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004758 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004759}
4760
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004761module_param(disable_ertm, bool, 0644);
4762MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");