blob: 32d338c30e65a034460652579112fb6c9b61f806 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Gustavo F. Padovan590051d2011-12-18 13:39:33 -02006 Copyright (C) 2011 ProFUSION Embedded Systems
Linus Torvalds1da177e2005-04-16 15:20:36 -07007
8 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License version 2 as
12 published by the Free Software Foundation;
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
17 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090018 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090023 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
24 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070025 SOFTWARE IS DISCLAIMED.
26*/
27
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020028/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070029
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/module.h>
31
32#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080033#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/errno.h>
35#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/sched.h>
37#include <linux/slab.h>
38#include <linux/poll.h>
39#include <linux/fcntl.h>
40#include <linux/init.h>
41#include <linux/interrupt.h>
42#include <linux/socket.h>
43#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080045#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010046#include <linux/debugfs.h>
47#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030048#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030049#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#include <net/sock.h>
51
52#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070053#include <asm/unaligned.h>
54
55#include <net/bluetooth/bluetooth.h>
56#include <net/bluetooth/hci_core.h>
57#include <net/bluetooth/l2cap.h>
Anderson Brigliab501d6a2011-06-07 18:46:31 -030058#include <net/bluetooth/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
Rusty Russelleb939922011-12-19 14:08:01 +000060bool disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020061
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070062static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Mat Martineau50a147c2011-11-02 16:18:34 -070063static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Johannes Bergb5ad8b72011-06-01 08:54:45 +020065static LIST_HEAD(chan_list);
66static DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Linus Torvalds1da177e2005-04-16 15:20:36 -070068static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
69 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030070static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
71 void *data);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -030072static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030073static void l2cap_send_disconn_req(struct l2cap_conn *conn,
74 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030076static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
77
Marcel Holtmann01394182006-07-03 10:02:46 +020078/* ---- L2CAP channels ---- */
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -030079
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. Padovanaf05b30b2009-04-20 01:31:08 -0300318 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300319 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200320
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +0200321 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +0100322
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300323 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200324
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300325 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
Ville Tervob62f3282011-02-10 22:38:50 -0300326 if (conn->hcon->type == LE_LINK) {
327 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300328 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300329 chan->scid = L2CAP_CID_LE_DATA;
330 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300331 } else {
332 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300333 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300334 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300335 }
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300336 } else if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200337 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300338 chan->scid = L2CAP_CID_CONN_LESS;
339 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300340 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200341 } else {
342 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300343 chan->scid = L2CAP_CID_SIGNALING;
344 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300345 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200346 }
347
Andrei Emeltchenko8f7975b2011-10-13 16:18:54 +0300348 chan->local_id = L2CAP_BESTEFFORT_ID;
349 chan->local_stype = L2CAP_SERV_BESTEFFORT;
350 chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
351 chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
352 chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
353 chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
354
Ulisses Furquim371fd832011-12-21 20:02:36 -0200355 l2cap_chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300356
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200357 list_add_rcu(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200358}
359
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900360/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200361 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300362static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200363{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300364 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300365 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200366 struct sock *parent = bt_sk(sk)->parent;
367
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300368 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200369
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300370 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200371
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900372 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300373 /* Delete from channel list */
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200374 list_del_rcu(&chan->list);
375 synchronize_rcu();
376
Ulisses Furquim371fd832011-12-21 20:02:36 -0200377 l2cap_chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300378
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300379 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200380 hci_conn_put(conn->hcon);
381 }
382
Gustavo F. 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 Furquim24d2b8c2012-01-30 18:26:29 -02001021 cancel_delayed_work_sync(&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 Furquim24d2b8c2012-01-30 18:26:29 -02001024 cancel_delayed_work_sync(&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
Johan Hedberg4aa832c2012-01-08 22:51:16 +02001123int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001125 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 bdaddr_t *src = &bt_sk(sk)->src;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 struct l2cap_conn *conn;
1128 struct hci_conn *hcon;
1129 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001130 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001131 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001133 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001134 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001136 hdev = hci_get_route(dst, src);
1137 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 return -EHOSTUNREACH;
1139
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001140 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001142 lock_sock(sk);
1143
1144 /* PSM must be odd and lsb of upper byte must be 0 */
1145 if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
1146 chan->chan_type != L2CAP_CHAN_RAW) {
1147 err = -EINVAL;
1148 goto done;
1149 }
1150
1151 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
1152 err = -EINVAL;
1153 goto done;
1154 }
1155
1156 switch (chan->mode) {
1157 case L2CAP_MODE_BASIC:
1158 break;
1159 case L2CAP_MODE_ERTM:
1160 case L2CAP_MODE_STREAMING:
1161 if (!disable_ertm)
1162 break;
1163 /* fall through */
1164 default:
1165 err = -ENOTSUPP;
1166 goto done;
1167 }
1168
1169 switch (sk->sk_state) {
1170 case BT_CONNECT:
1171 case BT_CONNECT2:
1172 case BT_CONFIG:
1173 /* Already connecting */
1174 err = 0;
1175 goto done;
1176
1177 case BT_CONNECTED:
1178 /* Already connected */
1179 err = -EISCONN;
1180 goto done;
1181
1182 case BT_OPEN:
1183 case BT_BOUND:
1184 /* Can connect */
1185 break;
1186
1187 default:
1188 err = -EBADFD;
1189 goto done;
1190 }
1191
1192 /* Set destination address and psm */
Gustavo F. Padovan9219b2a2012-01-02 20:08:04 -02001193 bacpy(&bt_sk(sk)->dst, dst);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001194 chan->psm = psm;
1195 chan->dcid = cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001197 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001198
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001199 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001200 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001201 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001202 else
1203 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001204 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001205
Ville Tervo30e76272011-02-22 16:10:53 -03001206 if (IS_ERR(hcon)) {
1207 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001209 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
1211 conn = l2cap_conn_add(hcon, 0);
1212 if (!conn) {
1213 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001214 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 goto done;
1216 }
1217
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 /* Update source addr of the socket */
1219 bacpy(src, conn->src);
1220
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001221 l2cap_chan_add(conn, chan);
1222
Gustavo F. 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. Padovanaf05b30b2009-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. Padovanaf05b30b2009-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. Padovan710f9b0a2011-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. Padovan7990681c2011-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. Padovan710f9b0a2011-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. Padovan710f9b0a2011-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. Padovan710f9b0a2011-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. Padovan710f9b0a2011-03-25 14:30:37 -03002517 return;
2518
Gustavo F. Padovan710f9b0a2011-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 Furquim6de32752012-01-30 18:26:28 -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. Padovanaf05b30b2009-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 Kaczmarek6e1da682012-01-04 12:10:42 +01002973 __set_chan_timer(chan,
2974 msecs_to_jiffies(L2CAP_DISC_REJ_TIMEOUT));
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002975 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976 goto done;
2977 }
2978
2979 if (flags & 0x01)
2980 goto done;
2981
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002982 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002984 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002985 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002986
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002987 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002988 chan->next_tx_seq = 0;
2989 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002990 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002991 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002992 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002993
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994 l2cap_chan_ready(sk);
2995 }
2996
2997done:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002998 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999 return 0;
3000}
3001
3002static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3003{
3004 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3005 struct l2cap_disconn_rsp rsp;
3006 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003007 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008 struct sock *sk;
3009
3010 scid = __le16_to_cpu(req->scid);
3011 dcid = __le16_to_cpu(req->dcid);
3012
3013 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3014
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003015 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003016 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017 return 0;
3018
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003019 sk = chan->sk;
3020
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003021 rsp.dcid = cpu_to_le16(chan->scid);
3022 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3024
3025 sk->sk_shutdown = SHUTDOWN_MASK;
3026
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003027 l2cap_chan_del(chan, ECONNRESET);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003028 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003030 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031 return 0;
3032}
3033
3034static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3035{
3036 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3037 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003038 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039 struct sock *sk;
3040
3041 scid = __le16_to_cpu(rsp->scid);
3042 dcid = __le16_to_cpu(rsp->dcid);
3043
3044 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3045
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003046 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003047 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048 return 0;
3049
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003050 sk = chan->sk;
3051
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003052 l2cap_chan_del(chan, 0);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003053 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003055 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056 return 0;
3057}
3058
3059static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3060{
3061 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062 u16 type;
3063
3064 type = __le16_to_cpu(req->type);
3065
3066 BT_DBG("type 0x%4.4x", type);
3067
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003068 if (type == L2CAP_IT_FEAT_MASK) {
3069 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003070 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003071 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3072 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3073 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003074 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003075 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3076 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003077 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003078 feat_mask |= L2CAP_FEAT_EXT_FLOW
3079 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003080
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003081 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003082 l2cap_send_cmd(conn, cmd->ident,
3083 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003084 } else if (type == L2CAP_IT_FIXED_CHAN) {
3085 u8 buf[12];
3086 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
Mat Martineau50a147c2011-11-02 16:18:34 -07003087
3088 if (enable_hs)
3089 l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
3090 else
3091 l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
3092
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003093 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3094 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003095 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003096 l2cap_send_cmd(conn, cmd->ident,
3097 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003098 } else {
3099 struct l2cap_info_rsp rsp;
3100 rsp.type = cpu_to_le16(type);
3101 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3102 l2cap_send_cmd(conn, cmd->ident,
3103 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3104 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105
3106 return 0;
3107}
3108
3109static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3110{
3111 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3112 u16 type, result;
3113
3114 type = __le16_to_cpu(rsp->type);
3115 result = __le16_to_cpu(rsp->result);
3116
3117 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3118
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003119 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3120 if (cmd->ident != conn->info_ident ||
3121 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3122 return 0;
3123
Ulisses Furquim6de32752012-01-30 18:26:28 -02003124 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003125
Ville Tervoadb08ed2010-08-04 09:43:33 +03003126 if (result != L2CAP_IR_SUCCESS) {
3127 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3128 conn->info_ident = 0;
3129
3130 l2cap_conn_start(conn);
3131
3132 return 0;
3133 }
3134
Marcel Holtmann984947d2009-02-06 23:35:19 +01003135 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003136 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003137
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003138 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003139 struct l2cap_info_req req;
3140 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3141
3142 conn->info_ident = l2cap_get_ident(conn);
3143
3144 l2cap_send_cmd(conn, conn->info_ident,
3145 L2CAP_INFO_REQ, sizeof(req), &req);
3146 } else {
3147 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3148 conn->info_ident = 0;
3149
3150 l2cap_conn_start(conn);
3151 }
3152 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003153 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003154 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003155
3156 l2cap_conn_start(conn);
3157 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003158
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159 return 0;
3160}
3161
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003162static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3163 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3164 void *data)
3165{
3166 struct l2cap_create_chan_req *req = data;
3167 struct l2cap_create_chan_rsp rsp;
3168 u16 psm, scid;
3169
3170 if (cmd_len != sizeof(*req))
3171 return -EPROTO;
3172
3173 if (!enable_hs)
3174 return -EINVAL;
3175
3176 psm = le16_to_cpu(req->psm);
3177 scid = le16_to_cpu(req->scid);
3178
3179 BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3180
3181 /* Placeholder: Always reject */
3182 rsp.dcid = 0;
3183 rsp.scid = cpu_to_le16(scid);
3184 rsp.result = L2CAP_CR_NO_MEM;
3185 rsp.status = L2CAP_CS_NO_INFO;
3186
3187 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3188 sizeof(rsp), &rsp);
3189
3190 return 0;
3191}
3192
3193static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3194 struct l2cap_cmd_hdr *cmd, void *data)
3195{
3196 BT_DBG("conn %p", conn);
3197
3198 return l2cap_connect_rsp(conn, cmd, data);
3199}
3200
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003201static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
3202 u16 icid, u16 result)
3203{
3204 struct l2cap_move_chan_rsp rsp;
3205
3206 BT_DBG("icid %d, result %d", icid, result);
3207
3208 rsp.icid = cpu_to_le16(icid);
3209 rsp.result = cpu_to_le16(result);
3210
3211 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
3212}
3213
3214static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
3215 struct l2cap_chan *chan, u16 icid, u16 result)
3216{
3217 struct l2cap_move_chan_cfm cfm;
3218 u8 ident;
3219
3220 BT_DBG("icid %d, result %d", icid, result);
3221
3222 ident = l2cap_get_ident(conn);
3223 if (chan)
3224 chan->ident = ident;
3225
3226 cfm.icid = cpu_to_le16(icid);
3227 cfm.result = cpu_to_le16(result);
3228
3229 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
3230}
3231
3232static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
3233 u16 icid)
3234{
3235 struct l2cap_move_chan_cfm_rsp rsp;
3236
3237 BT_DBG("icid %d", icid);
3238
3239 rsp.icid = cpu_to_le16(icid);
3240 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
3241}
3242
3243static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
3244 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3245{
3246 struct l2cap_move_chan_req *req = data;
3247 u16 icid = 0;
3248 u16 result = L2CAP_MR_NOT_ALLOWED;
3249
3250 if (cmd_len != sizeof(*req))
3251 return -EPROTO;
3252
3253 icid = le16_to_cpu(req->icid);
3254
3255 BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
3256
3257 if (!enable_hs)
3258 return -EINVAL;
3259
3260 /* Placeholder: Always refuse */
3261 l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
3262
3263 return 0;
3264}
3265
3266static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
3267 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3268{
3269 struct l2cap_move_chan_rsp *rsp = data;
3270 u16 icid, result;
3271
3272 if (cmd_len != sizeof(*rsp))
3273 return -EPROTO;
3274
3275 icid = le16_to_cpu(rsp->icid);
3276 result = le16_to_cpu(rsp->result);
3277
3278 BT_DBG("icid %d, result %d", icid, result);
3279
3280 /* Placeholder: Always unconfirmed */
3281 l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
3282
3283 return 0;
3284}
3285
3286static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
3287 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3288{
3289 struct l2cap_move_chan_cfm *cfm = data;
3290 u16 icid, result;
3291
3292 if (cmd_len != sizeof(*cfm))
3293 return -EPROTO;
3294
3295 icid = le16_to_cpu(cfm->icid);
3296 result = le16_to_cpu(cfm->result);
3297
3298 BT_DBG("icid %d, result %d", icid, result);
3299
3300 l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
3301
3302 return 0;
3303}
3304
3305static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
3306 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3307{
3308 struct l2cap_move_chan_cfm_rsp *rsp = data;
3309 u16 icid;
3310
3311 if (cmd_len != sizeof(*rsp))
3312 return -EPROTO;
3313
3314 icid = le16_to_cpu(rsp->icid);
3315
3316 BT_DBG("icid %d", icid);
3317
3318 return 0;
3319}
3320
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003321static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02003322 u16 to_multiplier)
3323{
3324 u16 max_latency;
3325
3326 if (min > max || min < 6 || max > 3200)
3327 return -EINVAL;
3328
3329 if (to_multiplier < 10 || to_multiplier > 3200)
3330 return -EINVAL;
3331
3332 if (max >= to_multiplier * 8)
3333 return -EINVAL;
3334
3335 max_latency = (to_multiplier * 8 / max) - 1;
3336 if (latency > 499 || latency > max_latency)
3337 return -EINVAL;
3338
3339 return 0;
3340}
3341
3342static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3343 struct l2cap_cmd_hdr *cmd, u8 *data)
3344{
3345 struct hci_conn *hcon = conn->hcon;
3346 struct l2cap_conn_param_update_req *req;
3347 struct l2cap_conn_param_update_rsp rsp;
3348 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003349 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02003350
3351 if (!(hcon->link_mode & HCI_LM_MASTER))
3352 return -EINVAL;
3353
3354 cmd_len = __le16_to_cpu(cmd->len);
3355 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3356 return -EPROTO;
3357
3358 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003359 min = __le16_to_cpu(req->min);
3360 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02003361 latency = __le16_to_cpu(req->latency);
3362 to_multiplier = __le16_to_cpu(req->to_multiplier);
3363
3364 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3365 min, max, latency, to_multiplier);
3366
3367 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003368
3369 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
3370 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02003371 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3372 else
3373 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3374
3375 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3376 sizeof(rsp), &rsp);
3377
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003378 if (!err)
3379 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
3380
Claudio Takahaside731152011-02-11 19:28:55 -02003381 return 0;
3382}
3383
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003384static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
3385 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
3386{
3387 int err = 0;
3388
3389 switch (cmd->code) {
3390 case L2CAP_COMMAND_REJ:
3391 l2cap_command_rej(conn, cmd, data);
3392 break;
3393
3394 case L2CAP_CONN_REQ:
3395 err = l2cap_connect_req(conn, cmd, data);
3396 break;
3397
3398 case L2CAP_CONN_RSP:
3399 err = l2cap_connect_rsp(conn, cmd, data);
3400 break;
3401
3402 case L2CAP_CONF_REQ:
3403 err = l2cap_config_req(conn, cmd, cmd_len, data);
3404 break;
3405
3406 case L2CAP_CONF_RSP:
3407 err = l2cap_config_rsp(conn, cmd, data);
3408 break;
3409
3410 case L2CAP_DISCONN_REQ:
3411 err = l2cap_disconnect_req(conn, cmd, data);
3412 break;
3413
3414 case L2CAP_DISCONN_RSP:
3415 err = l2cap_disconnect_rsp(conn, cmd, data);
3416 break;
3417
3418 case L2CAP_ECHO_REQ:
3419 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3420 break;
3421
3422 case L2CAP_ECHO_RSP:
3423 break;
3424
3425 case L2CAP_INFO_REQ:
3426 err = l2cap_information_req(conn, cmd, data);
3427 break;
3428
3429 case L2CAP_INFO_RSP:
3430 err = l2cap_information_rsp(conn, cmd, data);
3431 break;
3432
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003433 case L2CAP_CREATE_CHAN_REQ:
3434 err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3435 break;
3436
3437 case L2CAP_CREATE_CHAN_RSP:
3438 err = l2cap_create_channel_rsp(conn, cmd, data);
3439 break;
3440
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003441 case L2CAP_MOVE_CHAN_REQ:
3442 err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
3443 break;
3444
3445 case L2CAP_MOVE_CHAN_RSP:
3446 err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
3447 break;
3448
3449 case L2CAP_MOVE_CHAN_CFM:
3450 err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
3451 break;
3452
3453 case L2CAP_MOVE_CHAN_CFM_RSP:
3454 err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
3455 break;
3456
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003457 default:
3458 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3459 err = -EINVAL;
3460 break;
3461 }
3462
3463 return err;
3464}
3465
3466static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3467 struct l2cap_cmd_hdr *cmd, u8 *data)
3468{
3469 switch (cmd->code) {
3470 case L2CAP_COMMAND_REJ:
3471 return 0;
3472
3473 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003474 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003475
3476 case L2CAP_CONN_PARAM_UPDATE_RSP:
3477 return 0;
3478
3479 default:
3480 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3481 return -EINVAL;
3482 }
3483}
3484
3485static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3486 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487{
3488 u8 *data = skb->data;
3489 int len = skb->len;
3490 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003491 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003492
3493 l2cap_raw_recv(conn, skb);
3494
3495 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003496 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003497 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3498 data += L2CAP_CMD_HDR_SIZE;
3499 len -= L2CAP_CMD_HDR_SIZE;
3500
Al Viro88219a02007-07-29 00:17:25 -07003501 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003502
Al Viro88219a02007-07-29 00:17:25 -07003503 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 -07003504
Al Viro88219a02007-07-29 00:17:25 -07003505 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506 BT_DBG("corrupted command");
3507 break;
3508 }
3509
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003510 if (conn->hcon->type == LE_LINK)
3511 err = l2cap_le_sig_cmd(conn, &cmd, data);
3512 else
3513 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514
3515 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003516 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003517
3518 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003519
3520 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003521 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003522 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3523 }
3524
Al Viro88219a02007-07-29 00:17:25 -07003525 data += cmd_len;
3526 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003527 }
3528
3529 kfree_skb(skb);
3530}
3531
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003532static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003533{
3534 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003535 int hdr_size;
3536
3537 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3538 hdr_size = L2CAP_EXT_HDR_SIZE;
3539 else
3540 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003541
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003542 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003543 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003544 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3545 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3546
3547 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003548 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003549 }
3550 return 0;
3551}
3552
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003553static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003554{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003555 u32 control = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003556
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003557 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003558
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003559 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003560
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003561 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003562 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003563 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003564 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003565 }
3566
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003567 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003568 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003569
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003570 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003571
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003572 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003573 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003574 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003575 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003576 }
3577}
3578
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003579static 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 -03003580{
3581 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003582 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003583
3584 bt_cb(skb)->tx_seq = tx_seq;
3585 bt_cb(skb)->sar = sar;
3586
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003587 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003588
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003589 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003590
Szymon Janc039d9572011-11-16 09:32:19 +01003591 while (next_skb) {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003592 if (bt_cb(next_skb)->tx_seq == tx_seq)
3593 return -EINVAL;
3594
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003595 next_tx_seq_offset = __seq_offset(chan,
3596 bt_cb(next_skb)->tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003597
3598 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003599 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003600 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003601 }
3602
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003603 if (skb_queue_is_last(&chan->srej_q, next_skb))
Szymon Janc039d9572011-11-16 09:32:19 +01003604 next_skb = NULL;
3605 else
3606 next_skb = skb_queue_next(&chan->srej_q, next_skb);
3607 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003608
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003609 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003610
3611 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003612}
3613
Mat Martineau84084a32011-07-22 14:54:00 -07003614static void append_skb_frag(struct sk_buff *skb,
3615 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003616{
Mat Martineau84084a32011-07-22 14:54:00 -07003617 /* skb->len reflects data in skb as well as all fragments
3618 * skb->data_len reflects only data in fragments
3619 */
3620 if (!skb_has_frag_list(skb))
3621 skb_shinfo(skb)->frag_list = new_frag;
3622
3623 new_frag->next = NULL;
3624
3625 (*last_frag)->next = new_frag;
3626 *last_frag = new_frag;
3627
3628 skb->len += new_frag->len;
3629 skb->data_len += new_frag->len;
3630 skb->truesize += new_frag->truesize;
3631}
3632
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003633static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
Mat Martineau84084a32011-07-22 14:54:00 -07003634{
3635 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003636
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003637 switch (__get_ctrl_sar(chan, control)) {
3638 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003639 if (chan->sdu)
3640 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003641
Mat Martineau84084a32011-07-22 14:54:00 -07003642 err = chan->ops->recv(chan->data, skb);
3643 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003644
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003645 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003646 if (chan->sdu)
3647 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003648
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003649 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003650 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003651
Mat Martineau84084a32011-07-22 14:54:00 -07003652 if (chan->sdu_len > chan->imtu) {
3653 err = -EMSGSIZE;
3654 break;
3655 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003656
Mat Martineau84084a32011-07-22 14:54:00 -07003657 if (skb->len >= chan->sdu_len)
3658 break;
3659
3660 chan->sdu = skb;
3661 chan->sdu_last_frag = skb;
3662
3663 skb = NULL;
3664 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003665 break;
3666
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003667 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003668 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003669 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003670
Mat Martineau84084a32011-07-22 14:54:00 -07003671 append_skb_frag(chan->sdu, skb,
3672 &chan->sdu_last_frag);
3673 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003674
Mat Martineau84084a32011-07-22 14:54:00 -07003675 if (chan->sdu->len >= chan->sdu_len)
3676 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003677
Mat Martineau84084a32011-07-22 14:54:00 -07003678 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003679 break;
3680
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003681 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003682 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003683 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003684
Mat Martineau84084a32011-07-22 14:54:00 -07003685 append_skb_frag(chan->sdu, skb,
3686 &chan->sdu_last_frag);
3687 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003688
Mat Martineau84084a32011-07-22 14:54:00 -07003689 if (chan->sdu->len != chan->sdu_len)
3690 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003691
Mat Martineau84084a32011-07-22 14:54:00 -07003692 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003693
Mat Martineau84084a32011-07-22 14:54:00 -07003694 if (!err) {
3695 /* Reassembly complete */
3696 chan->sdu = NULL;
3697 chan->sdu_last_frag = NULL;
3698 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003699 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003700 break;
3701 }
3702
Mat Martineau84084a32011-07-22 14:54:00 -07003703 if (err) {
3704 kfree_skb(skb);
3705 kfree_skb(chan->sdu);
3706 chan->sdu = NULL;
3707 chan->sdu_last_frag = NULL;
3708 chan->sdu_len = 0;
3709 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003710
Mat Martineau84084a32011-07-22 14:54:00 -07003711 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003712}
3713
Mat Martineau26f880d2011-07-07 09:39:01 -07003714static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003715{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003716 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003717
Mat Martineau26f880d2011-07-07 09:39:01 -07003718 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003719
Mat Martineau26f880d2011-07-07 09:39:01 -07003720 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3721
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003722 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003723 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Mat Martineau26f880d2011-07-07 09:39:01 -07003724 l2cap_send_sframe(chan, control);
3725
3726 set_bit(CONN_RNR_SENT, &chan->conn_state);
3727
3728 __clear_ack_timer(chan);
3729}
3730
3731static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3732{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003733 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003734
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003735 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003736 goto done;
3737
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003738 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003739 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003740 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003741 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003742 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003743
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003744 __clear_retrans_timer(chan);
3745 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003746
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003747 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003748
3749done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003750 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3751 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003752
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003753 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003754}
3755
Mat Martineaue3281402011-07-07 09:39:02 -07003756void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003757{
Mat Martineaue3281402011-07-07 09:39:02 -07003758 if (chan->mode == L2CAP_MODE_ERTM) {
3759 if (busy)
3760 l2cap_ertm_enter_local_busy(chan);
3761 else
3762 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003763 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003764}
3765
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003766static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003767{
3768 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003769 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003770
Mat Martineaue3281402011-07-07 09:39:02 -07003771 while ((skb = skb_peek(&chan->srej_q)) &&
3772 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3773 int err;
3774
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003775 if (bt_cb(skb)->tx_seq != tx_seq)
3776 break;
3777
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003778 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003779 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003780 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003781
3782 if (err < 0) {
3783 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3784 break;
3785 }
3786
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003787 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
3788 tx_seq = __next_seq(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003789 }
3790}
3791
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003792static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003793{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003794 struct srej_list *l, *tmp;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003795 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003796
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003797 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003798 if (l->tx_seq == tx_seq) {
3799 list_del(&l->list);
3800 kfree(l);
3801 return;
3802 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003803 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003804 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003805 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003806 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003807 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003808 }
3809}
3810
Szymon Jancaef89f22011-11-16 09:32:18 +01003811static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003812{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003813 struct srej_list *new;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003814 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003815
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003816 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003817 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003818 control |= __set_reqseq(chan, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003819 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003820
3821 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Szymon Jancaef89f22011-11-16 09:32:18 +01003822 if (!new)
3823 return -ENOMEM;
3824
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003825 new->tx_seq = chan->expected_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003826
3827 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
3828
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003829 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003830 }
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003831
3832 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Szymon Jancaef89f22011-11-16 09:32:18 +01003833
3834 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003835}
3836
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003837static 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 -03003838{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003839 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003840 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003841 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003842 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003843 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003844 int err = 0;
3845
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003846 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 -03003847 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003848
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003849 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003850 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003851 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003852 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003853 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003854 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003855 }
3856
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003857 chan->expected_ack_seq = req_seq;
3858 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003859
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003860 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003861
3862 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003863 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003864 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003865 goto drop;
3866 }
3867
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003868 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003869 goto drop;
3870
Mat Martineau02f1b642011-06-29 14:35:19 -07003871 if (tx_seq == chan->expected_tx_seq)
3872 goto expected;
3873
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003874 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003875 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003876
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003877 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003878 struct srej_list, list);
3879 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003880 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003881 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003882
3883 list_del(&first->list);
3884 kfree(first);
3885
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003886 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003887 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003888 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003889 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003890 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003891 }
3892 } else {
3893 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003894
3895 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003896 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003897 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003898
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003899 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003900 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003901 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003902 return 0;
3903 }
3904 }
Szymon Jancaef89f22011-11-16 09:32:18 +01003905
3906 err = l2cap_send_srejframe(chan, tx_seq);
3907 if (err < 0) {
3908 l2cap_send_disconn_req(chan->conn, chan, -err);
3909 return err;
3910 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003911 }
3912 } else {
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003913 expected_tx_seq_offset = __seq_offset(chan,
3914 chan->expected_tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003915
3916 /* duplicated tx_seq */
3917 if (tx_seq_offset < expected_tx_seq_offset)
3918 goto drop;
3919
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003920 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003921
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003922 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003923
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003924 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003925 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003926
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003927 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003928 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003929
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003930 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003931
Szymon Jancaef89f22011-11-16 09:32:18 +01003932 err = l2cap_send_srejframe(chan, tx_seq);
3933 if (err < 0) {
3934 l2cap_send_disconn_req(chan->conn, chan, -err);
3935 return err;
3936 }
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003937
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003938 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003939 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003940 return 0;
3941
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003942expected:
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003943 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003944
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003945 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003946 bt_cb(skb)->tx_seq = tx_seq;
3947 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003948 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003949 return 0;
3950 }
3951
Mat Martineau84084a32011-07-22 14:54:00 -07003952 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003953 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
3954
Mat Martineaue3281402011-07-07 09:39:02 -07003955 if (err < 0) {
3956 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3957 return err;
3958 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003959
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003960 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003961 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003962 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003963 }
3964
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003965
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003966 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3967 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003968 l2cap_send_ack(chan);
Gustavo F. Padovan4d611e42011-06-23 19:30:48 -03003969 else
3970 __set_ack_timer(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003971
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003972 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003973
3974drop:
3975 kfree_skb(skb);
3976 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003977}
3978
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003979static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003980{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003981 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003982 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003983
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003984 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003985 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003986
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003987 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003988 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3989 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3990 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003991 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003992 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003993
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003994 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003995 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003996 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003997 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003998 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003999
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004000 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004001 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004002
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004003 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004004 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004005
4006 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004007 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004008 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004009 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004010
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004011 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4012 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004013 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02004014 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004015 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004016 }
4017}
4018
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004019static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004020{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004021 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004022
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004023 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004024
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004025 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004026
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004027 chan->expected_ack_seq = tx_seq;
4028 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004029
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004030 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004031 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004032 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004033 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004034 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004035
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004036 if (test_bit(CONN_WAIT_F, &chan->conn_state))
4037 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004038 }
4039}
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004040static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004041{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004042 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004043
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004044 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004045
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004046 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004047
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004048 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004049 chan->expected_ack_seq = tx_seq;
4050 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004051
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004052 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004053 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004054
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004055 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004056
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004057 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004058 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004059 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004060 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004061 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004062 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004063 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004064 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004065 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004066 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004067 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004068 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004069 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004070 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004071 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004072 }
4073 }
4074}
4075
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004076static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004077{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004078 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004079
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004080 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004081
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004082 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004083 chan->expected_ack_seq = tx_seq;
4084 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004085
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004086 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004087 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004088
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004089 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004090 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004091 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004092 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004093 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004094 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004095
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004096 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004097 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004098 } else {
4099 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4100 l2cap_send_sframe(chan, rx_control);
4101 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004102}
4103
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004104static 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 -03004105{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004106 BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004107
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004108 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004109 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004110 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004111 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004112 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004113 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004114 }
4115
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004116 switch (__get_ctrl_super(chan, rx_control)) {
4117 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004118 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004119 break;
4120
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004121 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004122 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004123 break;
4124
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004125 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004126 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004127 break;
4128
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004129 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004130 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004131 break;
4132 }
4133
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004134 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004135 return 0;
4136}
4137
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004138static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
4139{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004140 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004141 u32 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004142 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004143 int len, next_tx_seq_offset, req_seq_offset;
4144
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004145 control = __get_control(chan, skb->data);
4146 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004147 len = skb->len;
4148
4149 /*
4150 * We can just drop the corrupted I-frame here.
4151 * Receiver will miss it and start proper recovery
4152 * procedures and ask retransmission.
4153 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004154 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004155 goto drop;
4156
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004157 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004158 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004159
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004160 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004161 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004162
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004163 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004164 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004165 goto drop;
4166 }
4167
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004168 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004169
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004170 req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4171
4172 next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4173 chan->expected_ack_seq);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004174
4175 /* check for invalid req-seq */
4176 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004177 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004178 goto drop;
4179 }
4180
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004181 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004182 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004183 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004184 goto drop;
4185 }
4186
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004187 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004188 } else {
4189 if (len != 0) {
4190 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004191 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004192 goto drop;
4193 }
4194
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004195 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004196 }
4197
4198 return 0;
4199
4200drop:
4201 kfree_skb(skb);
4202 return 0;
4203}
4204
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4206{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004207 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07004208 struct sock *sk = NULL;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004209 u32 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004210 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004211 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004212
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004213 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004214 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004215 BT_DBG("unknown cid 0x%4.4x", cid);
4216 goto drop;
4217 }
4218
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004219 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004220
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004221 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004223 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004224 goto drop;
4225
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004226 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004227 case L2CAP_MODE_BASIC:
4228 /* If socket recv buffers overflows we drop data here
4229 * which is *bad* because L2CAP has to be reliable.
4230 * But we don't have any other choice. L2CAP doesn't
4231 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004233 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004234 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004235
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004236 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004237 goto done;
4238 break;
4239
4240 case L2CAP_MODE_ERTM:
Gustavo F. Padovaneb403a12011-06-24 01:54:50 -03004241 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004242
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004243 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004244
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004245 case L2CAP_MODE_STREAMING:
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004246 control = __get_control(chan, skb->data);
4247 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004248 len = skb->len;
4249
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004250 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004251 goto drop;
4252
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004253 if (__is_sar_start(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004254 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004255
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004256 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004257 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004258
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004259 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004260 goto drop;
4261
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004262 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004263
Mat Martineau84084a32011-07-22 14:54:00 -07004264 if (chan->expected_tx_seq != tx_seq) {
4265 /* Frame(s) missing - must discard partial SDU */
4266 kfree_skb(chan->sdu);
4267 chan->sdu = NULL;
4268 chan->sdu_last_frag = NULL;
4269 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004270
Mat Martineau84084a32011-07-22 14:54:00 -07004271 /* TODO: Notify userland of missing data */
4272 }
4273
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004274 chan->expected_tx_seq = __next_seq(chan, tx_seq);
Mat Martineau84084a32011-07-22 14:54:00 -07004275
4276 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
4277 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004278
4279 goto done;
4280
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004281 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004282 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004283 break;
4284 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004285
4286drop:
4287 kfree_skb(skb);
4288
4289done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004290 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004291 release_sock(sk);
Marcel Holtmann01394182006-07-03 10:02:46 +02004292
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293 return 0;
4294}
4295
Al Viro8e036fc2007-07-29 00:16:36 -07004296static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004298 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004299 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004301 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
4302 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303 goto drop;
4304
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004305 sk = chan->sk;
4306
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004307 lock_sock(sk);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00004308
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309 BT_DBG("sk %p, len %d", sk, skb->len);
4310
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004311 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312 goto drop;
4313
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004314 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004315 goto drop;
4316
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004317 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318 goto done;
4319
4320drop:
4321 kfree_skb(skb);
4322
4323done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004324 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004325 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326 return 0;
4327}
4328
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004329static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
4330{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004331 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004332 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004333
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004334 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
4335 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004336 goto drop;
4337
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004338 sk = chan->sk;
4339
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004340 lock_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004341
4342 BT_DBG("sk %p, len %d", sk, skb->len);
4343
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004344 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004345 goto drop;
4346
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004347 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004348 goto drop;
4349
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004350 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004351 goto done;
4352
4353drop:
4354 kfree_skb(skb);
4355
4356done:
4357 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004358 release_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004359 return 0;
4360}
4361
Linus Torvalds1da177e2005-04-16 15:20:36 -07004362static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4363{
4364 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004365 u16 cid, len;
4366 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367
4368 skb_pull(skb, L2CAP_HDR_SIZE);
4369 cid = __le16_to_cpu(lh->cid);
4370 len = __le16_to_cpu(lh->len);
4371
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004372 if (len != skb->len) {
4373 kfree_skb(skb);
4374 return;
4375 }
4376
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4378
4379 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004380 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004381 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382 l2cap_sig_channel(conn, skb);
4383 break;
4384
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004385 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004386 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004387 skb_pull(skb, 2);
4388 l2cap_conless_channel(conn, psm, skb);
4389 break;
4390
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004391 case L2CAP_CID_LE_DATA:
4392 l2cap_att_channel(conn, cid, skb);
4393 break;
4394
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004395 case L2CAP_CID_SMP:
4396 if (smp_sig_channel(conn, skb))
4397 l2cap_conn_del(conn->hcon, EACCES);
4398 break;
4399
Linus Torvalds1da177e2005-04-16 15:20:36 -07004400 default:
4401 l2cap_data_channel(conn, cid, skb);
4402 break;
4403 }
4404}
4405
4406/* ---- L2CAP interface with lower layer (HCI) ---- */
4407
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004408int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004409{
4410 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004411 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412
Linus Torvalds1da177e2005-04-16 15:20:36 -07004413 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4414
4415 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004416 read_lock(&chan_list_lock);
4417 list_for_each_entry(c, &chan_list, global_l) {
4418 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004419
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004420 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421 continue;
4422
4423 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004424 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004425 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004426 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004428 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4429 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004430 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004431 lm2 |= HCI_LM_MASTER;
4432 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004433 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004434 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435
4436 return exact ? lm1 : lm2;
4437}
4438
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004439int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440{
Marcel Holtmann01394182006-07-03 10:02:46 +02004441 struct l2cap_conn *conn;
4442
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4444
Linus Torvalds1da177e2005-04-16 15:20:36 -07004445 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446 conn = l2cap_conn_add(hcon, status);
4447 if (conn)
4448 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004449 } else
Joe Perchese1750722011-06-29 18:18:29 -07004450 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004451
4452 return 0;
4453}
4454
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004455int l2cap_disconn_ind(struct hci_conn *hcon)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004456{
4457 struct l2cap_conn *conn = hcon->l2cap_data;
4458
4459 BT_DBG("hcon %p", hcon);
4460
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004461 if (!conn)
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02004462 return HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01004463 return conn->disc_reason;
4464}
4465
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004466int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467{
4468 BT_DBG("hcon %p reason %d", hcon, reason);
4469
Joe Perchese1750722011-06-29 18:18:29 -07004470 l2cap_conn_del(hcon, bt_to_errno(reason));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004471 return 0;
4472}
4473
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004474static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004475{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004476 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004477 return;
4478
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004479 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004480 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004481 __clear_chan_timer(chan);
Andrzej Kaczmarek6e1da682012-01-04 12:10:42 +01004482 __set_chan_timer(chan,
4483 msecs_to_jiffies(L2CAP_ENC_TIMEOUT));
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004484 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004485 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004486 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004487 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004488 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004489 }
4490}
4491
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004492int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004494 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004495 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004496
Marcel Holtmann01394182006-07-03 10:02:46 +02004497 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004498 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004499
Linus Torvalds1da177e2005-04-16 15:20:36 -07004500 BT_DBG("conn %p", conn);
4501
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004502 if (hcon->type == LE_LINK) {
4503 smp_distribute_keys(conn, 0);
Ulisses Furquim6de32752012-01-30 18:26:28 -02004504 cancel_delayed_work(&conn->security_timer);
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004505 }
4506
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02004507 rcu_read_lock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004508
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02004509 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004510 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004511
Linus Torvalds1da177e2005-04-16 15:20:36 -07004512 bh_lock_sock(sk);
4513
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004514 BT_DBG("chan->scid %d", chan->scid);
4515
4516 if (chan->scid == L2CAP_CID_LE_DATA) {
4517 if (!status && encrypt) {
4518 chan->sec_level = hcon->sec_level;
4519 l2cap_chan_ready(sk);
4520 }
4521
4522 bh_unlock_sock(sk);
4523 continue;
4524 }
4525
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004526 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004527 bh_unlock_sock(sk);
4528 continue;
4529 }
4530
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004531 if (!status && (chan->state == BT_CONNECTED ||
4532 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004533 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004534 bh_unlock_sock(sk);
4535 continue;
4536 }
4537
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004538 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004539 if (!status) {
4540 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004541 req.scid = cpu_to_le16(chan->scid);
4542 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004543
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004544 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004545 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004546
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004547 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004548 L2CAP_CONN_REQ, sizeof(req), &req);
4549 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004550 __clear_chan_timer(chan);
Andrzej Kaczmarek6e1da682012-01-04 12:10:42 +01004551 __set_chan_timer(chan,
4552 msecs_to_jiffies(L2CAP_DISC_TIMEOUT));
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004553 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004554 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004555 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004556 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004557
4558 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004559 if (bt_sk(sk)->defer_setup) {
4560 struct sock *parent = bt_sk(sk)->parent;
4561 res = L2CAP_CR_PEND;
4562 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004563 if (parent)
4564 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004565 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004566 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004567 res = L2CAP_CR_SUCCESS;
4568 stat = L2CAP_CS_NO_INFO;
4569 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004570 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004571 l2cap_state_change(chan, BT_DISCONN);
Andrzej Kaczmarek6e1da682012-01-04 12:10:42 +01004572 __set_chan_timer(chan,
4573 msecs_to_jiffies(L2CAP_DISC_TIMEOUT));
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004574 res = L2CAP_CR_SEC_BLOCK;
4575 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004576 }
4577
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004578 rsp.scid = cpu_to_le16(chan->dcid);
4579 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004580 rsp.result = cpu_to_le16(res);
4581 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004582 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4583 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004584 }
4585
Linus Torvalds1da177e2005-04-16 15:20:36 -07004586 bh_unlock_sock(sk);
4587 }
4588
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02004589 rcu_read_unlock();
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004590
Linus Torvalds1da177e2005-04-16 15:20:36 -07004591 return 0;
4592}
4593
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004594int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004595{
4596 struct l2cap_conn *conn = hcon->l2cap_data;
4597
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004598 if (!conn)
4599 conn = l2cap_conn_add(hcon, 0);
4600
4601 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004602 goto drop;
4603
4604 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4605
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004606 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004607 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004608 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004609 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004610 int len;
4611
4612 if (conn->rx_len) {
4613 BT_ERR("Unexpected start frame (len %d)", skb->len);
4614 kfree_skb(conn->rx_skb);
4615 conn->rx_skb = NULL;
4616 conn->rx_len = 0;
4617 l2cap_conn_unreliable(conn, ECOMM);
4618 }
4619
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004620 /* Start fragment always begin with Basic L2CAP header */
4621 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004622 BT_ERR("Frame is too short (len %d)", skb->len);
4623 l2cap_conn_unreliable(conn, ECOMM);
4624 goto drop;
4625 }
4626
4627 hdr = (struct l2cap_hdr *) skb->data;
4628 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004629 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004630
4631 if (len == skb->len) {
4632 /* Complete frame received */
4633 l2cap_recv_frame(conn, skb);
4634 return 0;
4635 }
4636
4637 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4638
4639 if (skb->len > len) {
4640 BT_ERR("Frame is too long (len %d, expected len %d)",
4641 skb->len, len);
4642 l2cap_conn_unreliable(conn, ECOMM);
4643 goto drop;
4644 }
4645
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004646 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004647
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004648 if (chan && chan->sk) {
4649 struct sock *sk = chan->sk;
4650
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004651 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004652 BT_ERR("Frame exceeding recv MTU (len %d, "
4653 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004654 chan->imtu);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004655 release_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004656 l2cap_conn_unreliable(conn, ECOMM);
4657 goto drop;
4658 }
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004659 release_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004660 }
4661
Linus Torvalds1da177e2005-04-16 15:20:36 -07004662 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004663 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4664 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004665 goto drop;
4666
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004667 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004668 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004669 conn->rx_len = len - skb->len;
4670 } else {
4671 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4672
4673 if (!conn->rx_len) {
4674 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4675 l2cap_conn_unreliable(conn, ECOMM);
4676 goto drop;
4677 }
4678
4679 if (skb->len > conn->rx_len) {
4680 BT_ERR("Fragment is too long (len %d, expected %d)",
4681 skb->len, conn->rx_len);
4682 kfree_skb(conn->rx_skb);
4683 conn->rx_skb = NULL;
4684 conn->rx_len = 0;
4685 l2cap_conn_unreliable(conn, ECOMM);
4686 goto drop;
4687 }
4688
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004689 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004690 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004691 conn->rx_len -= skb->len;
4692
4693 if (!conn->rx_len) {
4694 /* Complete frame received */
4695 l2cap_recv_frame(conn, conn->rx_skb);
4696 conn->rx_skb = NULL;
4697 }
4698 }
4699
4700drop:
4701 kfree_skb(skb);
4702 return 0;
4703}
4704
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004705static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004706{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004707 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004708
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02004709 read_lock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004710
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004711 list_for_each_entry(c, &chan_list, global_l) {
4712 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004713
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004714 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 +01004715 batostr(&bt_sk(sk)->src),
4716 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004717 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004718 c->scid, c->dcid, c->imtu, c->omtu,
4719 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004720}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004721
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02004722 read_unlock(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004723
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004724 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004725}
4726
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004727static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4728{
4729 return single_open(file, l2cap_debugfs_show, inode->i_private);
4730}
4731
4732static const struct file_operations l2cap_debugfs_fops = {
4733 .open = l2cap_debugfs_open,
4734 .read = seq_read,
4735 .llseek = seq_lseek,
4736 .release = single_release,
4737};
4738
4739static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004740
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004741int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004742{
4743 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004744
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004745 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004746 if (err < 0)
4747 return err;
4748
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004749 if (bt_debugfs) {
4750 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4751 bt_debugfs, NULL, &l2cap_debugfs_fops);
4752 if (!l2cap_debugfs)
4753 BT_ERR("Failed to create L2CAP debug file");
4754 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004755
Linus Torvalds1da177e2005-04-16 15:20:36 -07004756 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004757}
4758
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004759void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004760{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004761 debugfs_remove(l2cap_debugfs);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004762 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004763}
4764
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004765module_param(disable_ertm, bool, 0644);
4766MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");