blob: ab2bfcf3cd24984d72bd3699dbee91ff27d152be [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006
7 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation;
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
16 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090017 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
18 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090022 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
23 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 SOFTWARE IS DISCLAIMED.
25*/
26
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020027/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30
31#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080032#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/errno.h>
34#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/sched.h>
36#include <linux/slab.h>
37#include <linux/poll.h>
38#include <linux/fcntl.h>
39#include <linux/init.h>
40#include <linux/interrupt.h>
41#include <linux/socket.h>
42#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080044#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010045#include <linux/debugfs.h>
46#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030047#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030048#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <net/sock.h>
50
51#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
Anderson Brigliab501d6a2011-06-07 18:46:31 -030057#include <net/bluetooth/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020059int disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020060
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070061static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010062static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030064static struct workqueue_struct *_busy_wq;
65
Johannes Bergb5ad8b72011-06-01 08:54:45 +020066static LIST_HEAD(chan_list);
67static DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070068
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030069static void l2cap_busy_work(struct work_struct *work);
70
Linus Torvalds1da177e2005-04-16 15:20:36 -070071static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
72 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030073static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
74 void *data);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -030075static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030076static void l2cap_send_disconn_req(struct l2cap_conn *conn,
77 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030079static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
80
Marcel Holtmann01394182006-07-03 10:02:46 +020081/* ---- L2CAP channels ---- */
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -030082
83static inline void chan_hold(struct l2cap_chan *c)
84{
85 atomic_inc(&c->refcnt);
86}
87
88static inline void chan_put(struct l2cap_chan *c)
89{
90 if (atomic_dec_and_test(&c->refcnt))
91 kfree(c);
92}
93
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030094static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020095{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030096 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030097
98 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030099 if (c->dcid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300100 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200101 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300102 return NULL;
103
Marcel Holtmann01394182006-07-03 10:02:46 +0200104}
105
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300106static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200107{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300108 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300109
110 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300111 if (c->scid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300112 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200113 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300114 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200115}
116
117/* Find channel with given SCID.
118 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300119static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200120{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300121 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300122
123 read_lock(&conn->chan_lock);
124 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300125 if (c)
126 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300127 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300128 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200129}
130
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300131static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200132{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300133 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300134
135 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300136 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300137 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200138 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300139 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200140}
141
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300142static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200143{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300144 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300145
146 read_lock(&conn->chan_lock);
147 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300148 if (c)
149 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300150 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300151 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200152}
153
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300154static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300155{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300156 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300157
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300158 list_for_each_entry(c, &chan_list, global_l) {
159 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300160 goto found;
161 }
162
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300163 c = NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300164found:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300165 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300166}
167
168int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
169{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300170 int err;
171
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300172 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300173
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300174 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300175 err = -EADDRINUSE;
176 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300177 }
178
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300179 if (psm) {
180 chan->psm = psm;
181 chan->sport = psm;
182 err = 0;
183 } else {
184 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300185
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300186 err = -EINVAL;
187 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300188 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300189 chan->psm = cpu_to_le16(p);
190 chan->sport = cpu_to_le16(p);
191 err = 0;
192 break;
193 }
194 }
195
196done:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300197 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300198 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300199}
200
201int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
202{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300203 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300204
205 chan->scid = scid;
206
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300207 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300208
209 return 0;
210}
211
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300212static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200213{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300214 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200215
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300216 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300217 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200218 return cid;
219 }
220
221 return 0;
222}
223
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300224static void l2cap_set_timer(struct l2cap_chan *chan, struct timer_list *timer, long timeout)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300225{
Mat Martineau774e5652011-06-29 14:35:20 -0700226 BT_DBG("chan %p state %d timeout %ld", chan->sk, chan->state, timeout);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300227
Mat Martineau774e5652011-06-29 14:35:20 -0700228 if (!mod_timer(timer, jiffies + timeout))
229 chan_hold(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300230}
231
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300232static void l2cap_clear_timer(struct l2cap_chan *chan, struct timer_list *timer)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300233{
Mat Martineau774e5652011-06-29 14:35:20 -0700234 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300235
Mat Martineau774e5652011-06-29 14:35:20 -0700236 if (timer_pending(timer) && del_timer(timer))
237 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300238}
239
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300240static void l2cap_state_change(struct l2cap_chan *chan, int state)
241{
242 chan->state = state;
243 chan->ops->state_change(chan->data, state);
244}
245
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300246static void l2cap_chan_timeout(unsigned long arg)
247{
248 struct l2cap_chan *chan = (struct l2cap_chan *) arg;
249 struct sock *sk = chan->sk;
250 int reason;
251
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300252 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300253
254 bh_lock_sock(sk);
255
256 if (sock_owned_by_user(sk)) {
257 /* sk is owned by user. Try again later */
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300258 __set_chan_timer(chan, HZ / 5);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300259 bh_unlock_sock(sk);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300260 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300261 return;
262 }
263
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300264 if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300265 reason = ECONNREFUSED;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300266 else if (chan->state == BT_CONNECT &&
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300267 chan->sec_level != BT_SECURITY_SDP)
268 reason = ECONNREFUSED;
269 else
270 reason = ETIMEDOUT;
271
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300272 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300273
274 bh_unlock_sock(sk);
275
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300276 chan->ops->close(chan->data);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300277 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300278}
279
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300280struct l2cap_chan *l2cap_chan_create(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200281{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300282 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200283
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300284 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
285 if (!chan)
286 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200287
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300288 chan->sk = sk;
289
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300290 write_lock_bh(&chan_list_lock);
291 list_add(&chan->global_l, &chan_list);
292 write_unlock_bh(&chan_list_lock);
293
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300294 setup_timer(&chan->chan_timer, l2cap_chan_timeout, (unsigned long) chan);
295
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300296 chan->state = BT_OPEN;
297
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300298 atomic_set(&chan->refcnt, 1);
299
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300300 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200301}
302
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300303void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300304{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300305 write_lock_bh(&chan_list_lock);
306 list_del(&chan->global_l);
307 write_unlock_bh(&chan_list_lock);
308
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300309 chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300310}
311
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300312static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200313{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300314 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300315 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200316
Marcel Holtmann2950f212009-02-12 14:02:50 +0100317 conn->disc_reason = 0x13;
318
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300319 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200320
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300321 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
Ville Tervob62f3282011-02-10 22:38:50 -0300322 if (conn->hcon->type == LE_LINK) {
323 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300324 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300325 chan->scid = L2CAP_CID_LE_DATA;
326 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300327 } else {
328 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300329 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300330 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300331 }
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300332 } else if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200333 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300334 chan->scid = L2CAP_CID_CONN_LESS;
335 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300336 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200337 } else {
338 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300339 chan->scid = L2CAP_CID_SIGNALING;
340 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300341 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200342 }
343
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300344 chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300345
346 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200347}
348
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900349/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200350 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300351static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200352{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300353 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300354 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200355 struct sock *parent = bt_sk(sk)->parent;
356
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300357 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200358
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300359 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200360
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900361 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300362 /* Delete from channel list */
363 write_lock_bh(&conn->chan_lock);
364 list_del(&chan->list);
365 write_unlock_bh(&conn->chan_lock);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300366 chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300367
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300368 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200369 hci_conn_put(conn->hcon);
370 }
371
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300372 l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200373 sock_set_flag(sk, SOCK_ZAPPED);
374
375 if (err)
376 sk->sk_err = err;
377
378 if (parent) {
379 bt_accept_unlink(sk);
380 parent->sk_data_ready(parent, 0);
381 } else
382 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300383
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300384 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
385 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300386 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300387
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300388 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300389
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300390 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300391 struct srej_list *l, *tmp;
392
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300393 __clear_retrans_timer(chan);
394 __clear_monitor_timer(chan);
395 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300396
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300397 skb_queue_purge(&chan->srej_q);
398 skb_queue_purge(&chan->busy_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300399
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300400 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300401 list_del(&l->list);
402 kfree(l);
403 }
404 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200405}
406
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300407static void l2cap_chan_cleanup_listen(struct sock *parent)
408{
409 struct sock *sk;
410
411 BT_DBG("parent %p", parent);
412
413 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300414 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300415 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300416 __clear_chan_timer(chan);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300417 lock_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300418 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300419 release_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300420 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300421 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300422}
423
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300424void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300425{
426 struct l2cap_conn *conn = chan->conn;
427 struct sock *sk = chan->sk;
428
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300429 BT_DBG("chan %p state %d socket %p", chan, chan->state, sk->sk_socket);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300430
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300431 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300432 case BT_LISTEN:
433 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300434
435 l2cap_state_change(chan, BT_CLOSED);
436 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300437 break;
438
439 case BT_CONNECTED:
440 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300441 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300442 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300443 __clear_chan_timer(chan);
444 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300445 l2cap_send_disconn_req(conn, chan, reason);
446 } else
447 l2cap_chan_del(chan, reason);
448 break;
449
450 case BT_CONNECT2:
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) {
453 struct l2cap_conn_rsp rsp;
454 __u16 result;
455
456 if (bt_sk(sk)->defer_setup)
457 result = L2CAP_CR_SEC_BLOCK;
458 else
459 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300460 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300461
462 rsp.scid = cpu_to_le16(chan->dcid);
463 rsp.dcid = cpu_to_le16(chan->scid);
464 rsp.result = cpu_to_le16(result);
465 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
466 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
467 sizeof(rsp), &rsp);
468 }
469
470 l2cap_chan_del(chan, reason);
471 break;
472
473 case BT_CONNECT:
474 case BT_DISCONN:
475 l2cap_chan_del(chan, reason);
476 break;
477
478 default:
479 sock_set_flag(sk, SOCK_ZAPPED);
480 break;
481 }
482}
483
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300484static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530485{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300486 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300487 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530488 case BT_SECURITY_HIGH:
489 return HCI_AT_DEDICATED_BONDING_MITM;
490 case BT_SECURITY_MEDIUM:
491 return HCI_AT_DEDICATED_BONDING;
492 default:
493 return HCI_AT_NO_BONDING;
494 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300495 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300496 if (chan->sec_level == BT_SECURITY_LOW)
497 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530498
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300499 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530500 return HCI_AT_NO_BONDING_MITM;
501 else
502 return HCI_AT_NO_BONDING;
503 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300504 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530505 case BT_SECURITY_HIGH:
506 return HCI_AT_GENERAL_BONDING_MITM;
507 case BT_SECURITY_MEDIUM:
508 return HCI_AT_GENERAL_BONDING;
509 default:
510 return HCI_AT_NO_BONDING;
511 }
512 }
513}
514
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200515/* Service level security */
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300516static inline int l2cap_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200517{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300518 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100519 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200520
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300521 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100522
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300523 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200524}
525
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200526static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200527{
528 u8 id;
529
530 /* Get next available identificator.
531 * 1 - 128 are used by kernel.
532 * 129 - 199 are reserved.
533 * 200 - 254 are used by utilities like l2ping, etc.
534 */
535
536 spin_lock_bh(&conn->lock);
537
538 if (++conn->tx_ident > 128)
539 conn->tx_ident = 1;
540
541 id = conn->tx_ident;
542
543 spin_unlock_bh(&conn->lock);
544
545 return id;
546}
547
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300548static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200549{
550 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200551 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200552
553 BT_DBG("code 0x%2.2x", code);
554
555 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300556 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200557
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200558 if (lmp_no_flush_capable(conn->hcon->hdev))
559 flags = ACL_START_NO_FLUSH;
560 else
561 flags = ACL_START;
562
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700563 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
564
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200565 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200566}
567
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300568static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300569{
570 struct sk_buff *skb;
571 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300572 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300573 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200574 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300575
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300576 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300577 return;
578
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300579 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300580 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300581
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300582 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300583
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300584 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300585 control |= L2CAP_CTRL_FRAME_TYPE;
586
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300587 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300588 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300589
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300590 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300591 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300592
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300593 skb = bt_skb_alloc(count, GFP_ATOMIC);
594 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300595 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300596
597 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300598 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300599 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300600 put_unaligned_le16(control, skb_put(skb, 2));
601
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300602 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300603 u16 fcs = crc16(0, (u8 *)lh, count - 2);
604 put_unaligned_le16(fcs, skb_put(skb, 2));
605 }
606
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200607 if (lmp_no_flush_capable(conn->hcon->hdev))
608 flags = ACL_START_NO_FLUSH;
609 else
610 flags = ACL_START;
611
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700612 bt_cb(skb)->force_active = chan->force_active;
613
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300614 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300615}
616
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300617static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300618{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300619 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300620 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300621 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300622 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300623 control |= L2CAP_SUPER_RCV_READY;
624
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300625 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300626
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300627 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300628}
629
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300630static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300631{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300632 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300633}
634
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300635static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200636{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300637 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200638
639 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100640 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
641 return;
642
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300643 if (l2cap_check_security(chan) &&
644 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200645 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300646 req.scid = cpu_to_le16(chan->scid);
647 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200648
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300649 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300650 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200651
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300652 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
653 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200654 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200655 } else {
656 struct l2cap_info_req req;
657 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
658
659 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
660 conn->info_ident = l2cap_get_ident(conn);
661
662 mod_timer(&conn->info_timer, jiffies +
663 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
664
665 l2cap_send_cmd(conn, conn->info_ident,
666 L2CAP_INFO_REQ, sizeof(req), &req);
667 }
668}
669
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300670static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
671{
672 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300673 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300674 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
675
676 switch (mode) {
677 case L2CAP_MODE_ERTM:
678 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
679 case L2CAP_MODE_STREAMING:
680 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
681 default:
682 return 0x00;
683 }
684}
685
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300686static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300687{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300688 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300689 struct l2cap_disconn_req req;
690
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300691 if (!conn)
692 return;
693
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300694 sk = chan->sk;
695
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300696 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300697 __clear_retrans_timer(chan);
698 __clear_monitor_timer(chan);
699 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300700 }
701
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300702 req.dcid = cpu_to_le16(chan->dcid);
703 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300704 l2cap_send_cmd(conn, l2cap_get_ident(conn),
705 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300706
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300707 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300708 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300709}
710
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200712static void l2cap_conn_start(struct l2cap_conn *conn)
713{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300714 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200715
716 BT_DBG("conn %p", conn);
717
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300718 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200719
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300720 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300721 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300722
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200723 bh_lock_sock(sk);
724
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300725 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200726 bh_unlock_sock(sk);
727 continue;
728 }
729
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300730 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300731 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300732
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300733 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300734 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300735 bh_unlock_sock(sk);
736 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200737 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300738
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300739 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
740 && test_bit(CONF_STATE2_DEVICE,
741 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300742 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300743 * so release the lock */
744 read_unlock_bh(&conn->chan_lock);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300745 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300746 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300747 bh_unlock_sock(sk);
748 continue;
749 }
750
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300751 req.scid = cpu_to_le16(chan->scid);
752 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300753
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300754 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300755 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300756
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300757 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
758 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300759
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300760 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200761 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300762 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300763 rsp.scid = cpu_to_le16(chan->dcid);
764 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200765
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300766 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100767 if (bt_sk(sk)->defer_setup) {
768 struct sock *parent = bt_sk(sk)->parent;
769 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
770 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
771 parent->sk_data_ready(parent, 0);
772
773 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300774 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100775 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
776 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
777 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200778 } else {
779 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
780 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
781 }
782
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300783 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
784 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300785
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300786 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300787 rsp.result != L2CAP_CR_SUCCESS) {
788 bh_unlock_sock(sk);
789 continue;
790 }
791
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300792 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300793 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300794 l2cap_build_conf_req(chan, buf), buf);
795 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200796 }
797
798 bh_unlock_sock(sk);
799 }
800
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300801 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200802}
803
Ville Tervob62f3282011-02-10 22:38:50 -0300804/* Find socket with cid and source bdaddr.
805 * Returns closest match, locked.
806 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300807static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300808{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300809 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300810
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300811 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300812
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300813 list_for_each_entry(c, &chan_list, global_l) {
814 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300815
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300816 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300817 continue;
818
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300819 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300820 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300821 if (!bacmp(&bt_sk(sk)->src, src)) {
822 read_unlock(&chan_list_lock);
823 return c;
824 }
Ville Tervob62f3282011-02-10 22:38:50 -0300825
826 /* Closest match */
827 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300828 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300829 }
830 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300831
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300832 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300833
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300834 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300835}
836
837static void l2cap_le_conn_ready(struct l2cap_conn *conn)
838{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300839 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300840 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300841
842 BT_DBG("");
843
844 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300845 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300846 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300847 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300848 return;
849
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300850 parent = pchan->sk;
851
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300852 bh_lock_sock(parent);
853
Ville Tervob62f3282011-02-10 22:38:50 -0300854 /* Check for backlog size */
855 if (sk_acceptq_is_full(parent)) {
856 BT_DBG("backlog full %d", parent->sk_ack_backlog);
857 goto clean;
858 }
859
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300860 chan = pchan->ops->new_connection(pchan->data);
861 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300862 goto clean;
863
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300864 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300865
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300866 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300867
868 hci_conn_hold(conn->hcon);
869
Ville Tervob62f3282011-02-10 22:38:50 -0300870 bacpy(&bt_sk(sk)->src, conn->src);
871 bacpy(&bt_sk(sk)->dst, conn->dst);
872
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300873 bt_accept_enqueue(parent, sk);
874
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300875 __l2cap_chan_add(conn, chan);
876
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300877 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300878
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300879 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300880 parent->sk_data_ready(parent, 0);
881
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300882 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300883
884clean:
885 bh_unlock_sock(parent);
886}
887
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300888static void l2cap_chan_ready(struct sock *sk)
889{
890 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
891 struct sock *parent = bt_sk(sk)->parent;
892
893 BT_DBG("sk %p, parent %p", sk, parent);
894
895 chan->conf_state = 0;
896 __clear_chan_timer(chan);
897
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300898 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300899 sk->sk_state_change(sk);
900
901 if (parent)
902 parent->sk_data_ready(parent, 0);
903}
904
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200905static void l2cap_conn_ready(struct l2cap_conn *conn)
906{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300907 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200908
909 BT_DBG("conn %p", conn);
910
Ville Tervob62f3282011-02-10 22:38:50 -0300911 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
912 l2cap_le_conn_ready(conn);
913
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300914 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200915
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300916 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300917 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300918
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200919 bh_lock_sock(sk);
920
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300921 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300922 if (smp_conn_security(conn, chan->sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300923 l2cap_chan_ready(sk);
Ville Tervoacd7d372011-02-10 22:38:49 -0300924
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300925 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300926 __clear_chan_timer(chan);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300927 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200928 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300929
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300930 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300931 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200932
933 bh_unlock_sock(sk);
934 }
935
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300936 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200937}
938
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200939/* Notify sockets that we cannot guaranty reliability anymore */
940static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
941{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300942 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200943
944 BT_DBG("conn %p", conn);
945
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300946 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200947
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300948 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300949 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300950
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300951 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200952 sk->sk_err = err;
953 }
954
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300955 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200956}
957
958static void l2cap_info_timeout(unsigned long arg)
959{
960 struct l2cap_conn *conn = (void *) arg;
961
Marcel Holtmann984947d2009-02-06 23:35:19 +0100962 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100963 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100964
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200965 l2cap_conn_start(conn);
966}
967
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300968static void l2cap_conn_del(struct hci_conn *hcon, int err)
969{
970 struct l2cap_conn *conn = hcon->l2cap_data;
971 struct l2cap_chan *chan, *l;
972 struct sock *sk;
973
974 if (!conn)
975 return;
976
977 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
978
979 kfree_skb(conn->rx_skb);
980
981 /* Kill channels */
982 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
983 sk = chan->sk;
984 bh_lock_sock(sk);
985 l2cap_chan_del(chan, err);
986 bh_unlock_sock(sk);
987 chan->ops->close(chan->data);
988 }
989
990 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
991 del_timer_sync(&conn->info_timer);
992
993 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
994 del_timer(&conn->security_timer);
995
996 hcon->l2cap_data = NULL;
997 kfree(conn);
998}
999
1000static void security_timeout(unsigned long arg)
1001{
1002 struct l2cap_conn *conn = (void *) arg;
1003
1004 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1005}
1006
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1008{
Marcel Holtmann01394182006-07-03 10:02:46 +02001009 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010
Marcel Holtmann01394182006-07-03 10:02:46 +02001011 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 return conn;
1013
Marcel Holtmann01394182006-07-03 10:02:46 +02001014 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1015 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017
1018 hcon->l2cap_data = conn;
1019 conn->hcon = hcon;
1020
Marcel Holtmann01394182006-07-03 10:02:46 +02001021 BT_DBG("hcon %p conn %p", hcon, conn);
1022
Ville Tervoacd7d372011-02-10 22:38:49 -03001023 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1024 conn->mtu = hcon->hdev->le_mtu;
1025 else
1026 conn->mtu = hcon->hdev->acl_mtu;
1027
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 conn->src = &hcon->hdev->bdaddr;
1029 conn->dst = &hcon->dst;
1030
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001031 conn->feat_mask = 0;
1032
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001034 rwlock_init(&conn->chan_lock);
1035
1036 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001038 if (hcon->type == LE_LINK)
1039 setup_timer(&conn->security_timer, security_timeout,
1040 (unsigned long) conn);
1041 else
Ville Tervob62f3282011-02-10 22:38:50 -03001042 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +00001043 (unsigned long) conn);
1044
Marcel Holtmann2950f212009-02-12 14:02:50 +01001045 conn->disc_reason = 0x13;
1046
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 return conn;
1048}
1049
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001050static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001052 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001053 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001054 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055}
1056
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058
1059/* Find socket with psm and source bdaddr.
1060 * Returns closest match.
1061 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001062static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001064 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001066 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001067
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001068 list_for_each_entry(c, &chan_list, global_l) {
1069 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001070
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001071 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 continue;
1073
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001074 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001076 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001077 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001078 return c;
1079 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080
1081 /* Closest match */
1082 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001083 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 }
1085 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001087 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001088
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001089 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090}
1091
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001092int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001094 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 bdaddr_t *src = &bt_sk(sk)->src;
1096 bdaddr_t *dst = &bt_sk(sk)->dst;
1097 struct l2cap_conn *conn;
1098 struct hci_conn *hcon;
1099 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001100 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001101 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001103 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001104 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001106 hdev = hci_get_route(dst, src);
1107 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 return -EHOSTUNREACH;
1109
1110 hci_dev_lock_bh(hdev);
1111
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001112 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001113
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001114 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001115 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001116 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001117 else
1118 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001119 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001120
Ville Tervo30e76272011-02-22 16:10:53 -03001121 if (IS_ERR(hcon)) {
1122 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001124 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125
1126 conn = l2cap_conn_add(hcon, 0);
1127 if (!conn) {
1128 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001129 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 goto done;
1131 }
1132
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 /* Update source addr of the socket */
1134 bacpy(src, conn->src);
1135
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001136 l2cap_chan_add(conn, chan);
1137
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001138 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001139 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140
1141 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001142 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001143 __clear_chan_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001144 if (l2cap_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001145 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001146 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001147 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 }
1149
Ville Tervo30e76272011-02-22 16:10:53 -03001150 err = 0;
1151
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152done:
1153 hci_dev_unlock_bh(hdev);
1154 hci_dev_put(hdev);
1155 return err;
1156}
1157
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001158int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001159{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001160 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001161 DECLARE_WAITQUEUE(wait, current);
1162 int err = 0;
1163 int timeo = HZ/5;
1164
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001165 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001166 while ((chan->unacked_frames > 0 && chan->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001167 set_current_state(TASK_INTERRUPTIBLE);
1168
1169 if (!timeo)
1170 timeo = HZ/5;
1171
1172 if (signal_pending(current)) {
1173 err = sock_intr_errno(timeo);
1174 break;
1175 }
1176
1177 release_sock(sk);
1178 timeo = schedule_timeout(timeo);
1179 lock_sock(sk);
1180
1181 err = sock_error(sk);
1182 if (err)
1183 break;
1184 }
1185 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001186 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001187 return err;
1188}
1189
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001190static void l2cap_monitor_timeout(unsigned long arg)
1191{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001192 struct l2cap_chan *chan = (void *) arg;
1193 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001194
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001195 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001196
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001197 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001198 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001199 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001200 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001201 return;
1202 }
1203
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001204 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001205 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001206
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001207 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001208 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001209}
1210
1211static void l2cap_retrans_timeout(unsigned long arg)
1212{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001213 struct l2cap_chan *chan = (void *) arg;
1214 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001215
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001216 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001217
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001218 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001219 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001220 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001221
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001222 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001223
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001224 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001225 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001226}
1227
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001228static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001229{
1230 struct sk_buff *skb;
1231
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001232 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001233 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001234 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001235 break;
1236
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001237 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001238 kfree_skb(skb);
1239
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001240 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001241 }
1242
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001243 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001244 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001245}
1246
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001247void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001248{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001249 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001250 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001251
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001252 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001253
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001254 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001255 flags = ACL_START_NO_FLUSH;
1256 else
1257 flags = ACL_START;
1258
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -07001259 bt_cb(skb)->force_active = chan->force_active;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001260 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001261}
1262
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001263void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001264{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001265 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001266 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001267
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001268 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001269 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001270 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001271 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001272
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001273 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001274 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1275 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001276 }
1277
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001278 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001279
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001280 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001281 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001282}
1283
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001284static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001285{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001286 struct sk_buff *skb, *tx_skb;
1287 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001288
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001289 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001290 if (!skb)
1291 return;
1292
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001293 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001294 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001295 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001296
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001297 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001298 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001299
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001300 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001301
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001302 if (chan->remote_max_tx &&
1303 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001304 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001305 return;
1306 }
1307
1308 tx_skb = skb_clone(skb, GFP_ATOMIC);
1309 bt_cb(skb)->retries++;
1310 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001311 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001312
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001313 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001314 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001315
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001316 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001317 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001318
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001319 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1320
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001321 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001322 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1323 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1324 }
1325
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001326 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001327}
1328
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001329int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001330{
1331 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001332 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001333 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001334
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001335 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001336 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001337
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001338 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001339
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001340 if (chan->remote_max_tx &&
1341 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001342 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001343 break;
1344 }
1345
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001346 tx_skb = skb_clone(skb, GFP_ATOMIC);
1347
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001348 bt_cb(skb)->retries++;
1349
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001350 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001351 control &= L2CAP_CTRL_SAR;
1352
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001353 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001354 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001355
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001356 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1357 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001358 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1359
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001360
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001361 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001362 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1363 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1364 }
1365
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001366 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001367
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001368 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001369
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001370 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1371 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001372
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301373 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001374 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301375
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001376 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001377
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001378 if (skb_queue_is_last(&chan->tx_q, skb))
1379 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001380 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001381 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001382
1383 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001384 }
1385
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001386 return nsent;
1387}
1388
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001389static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001390{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001391 int ret;
1392
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001393 if (!skb_queue_empty(&chan->tx_q))
1394 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001395
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001396 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001397 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001398 return ret;
1399}
1400
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001401static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001402{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001403 u16 control = 0;
1404
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001405 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001406
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001407 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001408 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001409 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001410 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001411 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001412 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001413
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001414 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001415 return;
1416
1417 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001418 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001419}
1420
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001421static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001422{
1423 struct srej_list *tail;
1424 u16 control;
1425
1426 control = L2CAP_SUPER_SELECT_REJECT;
1427 control |= L2CAP_CTRL_FINAL;
1428
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001429 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001430 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1431
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001432 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001433}
1434
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001435static 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 -07001436{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001437 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001438 struct sk_buff **frag;
1439 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001441 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001442 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443
1444 sent += count;
1445 len -= count;
1446
1447 /* Continuation fragments (no L2CAP header) */
1448 frag = &skb_shinfo(skb)->frag_list;
1449 while (len) {
1450 count = min_t(unsigned int, conn->mtu, len);
1451
1452 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1453 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001454 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001455 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1456 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457
1458 sent += count;
1459 len -= count;
1460
1461 frag = &(*frag)->next;
1462 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463
1464 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001465}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001467struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001468{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001469 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001470 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001471 struct sk_buff *skb;
1472 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1473 struct l2cap_hdr *lh;
1474
1475 BT_DBG("sk %p len %d", sk, (int)len);
1476
1477 count = min_t(unsigned int, (conn->mtu - hlen), len);
1478 skb = bt_skb_send_alloc(sk, count + hlen,
1479 msg->msg_flags & MSG_DONTWAIT, &err);
1480 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001481 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001482
1483 /* Create L2CAP header */
1484 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001485 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001486 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001487 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001488
1489 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1490 if (unlikely(err < 0)) {
1491 kfree_skb(skb);
1492 return ERR_PTR(err);
1493 }
1494 return skb;
1495}
1496
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001497struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001498{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001499 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001500 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001501 struct sk_buff *skb;
1502 int err, count, hlen = L2CAP_HDR_SIZE;
1503 struct l2cap_hdr *lh;
1504
1505 BT_DBG("sk %p len %d", sk, (int)len);
1506
1507 count = min_t(unsigned int, (conn->mtu - hlen), len);
1508 skb = bt_skb_send_alloc(sk, count + hlen,
1509 msg->msg_flags & MSG_DONTWAIT, &err);
1510 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001511 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001512
1513 /* Create L2CAP header */
1514 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001515 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001516 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1517
1518 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1519 if (unlikely(err < 0)) {
1520 kfree_skb(skb);
1521 return ERR_PTR(err);
1522 }
1523 return skb;
1524}
1525
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001526struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001527{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001528 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001529 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001530 struct sk_buff *skb;
1531 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1532 struct l2cap_hdr *lh;
1533
1534 BT_DBG("sk %p len %d", sk, (int)len);
1535
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001536 if (!conn)
1537 return ERR_PTR(-ENOTCONN);
1538
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001539 if (sdulen)
1540 hlen += 2;
1541
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001542 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001543 hlen += 2;
1544
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001545 count = min_t(unsigned int, (conn->mtu - hlen), len);
1546 skb = bt_skb_send_alloc(sk, count + hlen,
1547 msg->msg_flags & MSG_DONTWAIT, &err);
1548 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001549 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001550
1551 /* Create L2CAP header */
1552 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001553 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001554 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1555 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001556 if (sdulen)
1557 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001558
1559 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1560 if (unlikely(err < 0)) {
1561 kfree_skb(skb);
1562 return ERR_PTR(err);
1563 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001564
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001565 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001566 put_unaligned_le16(0, skb_put(skb, 2));
1567
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001568 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001569 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570}
1571
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001572int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001573{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001574 struct sk_buff *skb;
1575 struct sk_buff_head sar_queue;
1576 u16 control;
1577 size_t size = 0;
1578
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001579 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001580 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001581 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001582 if (IS_ERR(skb))
1583 return PTR_ERR(skb);
1584
1585 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001586 len -= chan->remote_mps;
1587 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001588
1589 while (len > 0) {
1590 size_t buflen;
1591
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001592 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001593 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001594 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001595 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001596 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001597 buflen = len;
1598 }
1599
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001600 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001601 if (IS_ERR(skb)) {
1602 skb_queue_purge(&sar_queue);
1603 return PTR_ERR(skb);
1604 }
1605
1606 __skb_queue_tail(&sar_queue, skb);
1607 len -= buflen;
1608 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001609 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001610 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1611 if (chan->tx_send_head == NULL)
1612 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001613
1614 return size;
1615}
1616
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001617int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1618{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001619 struct sk_buff *skb;
1620 u16 control;
1621 int err;
1622
1623 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001624 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001625 skb = l2cap_create_connless_pdu(chan, msg, len);
1626 if (IS_ERR(skb))
1627 return PTR_ERR(skb);
1628
1629 l2cap_do_send(chan, skb);
1630 return len;
1631 }
1632
1633 switch (chan->mode) {
1634 case L2CAP_MODE_BASIC:
1635 /* Check outgoing MTU */
1636 if (len > chan->omtu)
1637 return -EMSGSIZE;
1638
1639 /* Create a basic PDU */
1640 skb = l2cap_create_basic_pdu(chan, msg, len);
1641 if (IS_ERR(skb))
1642 return PTR_ERR(skb);
1643
1644 l2cap_do_send(chan, skb);
1645 err = len;
1646 break;
1647
1648 case L2CAP_MODE_ERTM:
1649 case L2CAP_MODE_STREAMING:
1650 /* Entire SDU fits into one PDU */
1651 if (len <= chan->remote_mps) {
1652 control = L2CAP_SDU_UNSEGMENTED;
1653 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1654 0);
1655 if (IS_ERR(skb))
1656 return PTR_ERR(skb);
1657
1658 __skb_queue_tail(&chan->tx_q, skb);
1659
1660 if (chan->tx_send_head == NULL)
1661 chan->tx_send_head = skb;
1662
1663 } else {
1664 /* Segment SDU into multiples PDUs */
1665 err = l2cap_sar_segment_sdu(chan, msg, len);
1666 if (err < 0)
1667 return err;
1668 }
1669
1670 if (chan->mode == L2CAP_MODE_STREAMING) {
1671 l2cap_streaming_send(chan);
1672 err = len;
1673 break;
1674 }
1675
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001676 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1677 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001678 err = len;
1679 break;
1680 }
1681
1682 err = l2cap_ertm_send(chan);
1683 if (err >= 0)
1684 err = len;
1685
1686 break;
1687
1688 default:
1689 BT_DBG("bad state %1.1x", chan->mode);
1690 err = -EBADFD;
1691 }
1692
1693 return err;
1694}
1695
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696/* Copy frame to all raw sockets on that connection */
1697static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1698{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001700 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701
1702 BT_DBG("conn %p", conn);
1703
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001704 read_lock(&conn->chan_lock);
1705 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001706 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001707 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 continue;
1709
1710 /* Don't send frame to the socket it came from */
1711 if (skb->sk == sk)
1712 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001713 nskb = skb_clone(skb, GFP_ATOMIC);
1714 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 continue;
1716
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001717 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 kfree_skb(nskb);
1719 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001720 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721}
1722
1723/* ---- L2CAP signalling commands ---- */
1724static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1725 u8 code, u8 ident, u16 dlen, void *data)
1726{
1727 struct sk_buff *skb, **frag;
1728 struct l2cap_cmd_hdr *cmd;
1729 struct l2cap_hdr *lh;
1730 int len, count;
1731
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001732 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1733 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734
1735 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1736 count = min_t(unsigned int, conn->mtu, len);
1737
1738 skb = bt_skb_alloc(count, GFP_ATOMIC);
1739 if (!skb)
1740 return NULL;
1741
1742 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001743 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001744
1745 if (conn->hcon->type == LE_LINK)
1746 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1747 else
1748 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749
1750 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1751 cmd->code = code;
1752 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001753 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754
1755 if (dlen) {
1756 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1757 memcpy(skb_put(skb, count), data, count);
1758 data += count;
1759 }
1760
1761 len -= skb->len;
1762
1763 /* Continuation fragments (no L2CAP header) */
1764 frag = &skb_shinfo(skb)->frag_list;
1765 while (len) {
1766 count = min_t(unsigned int, conn->mtu, len);
1767
1768 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1769 if (!*frag)
1770 goto fail;
1771
1772 memcpy(skb_put(*frag, count), data, count);
1773
1774 len -= count;
1775 data += count;
1776
1777 frag = &(*frag)->next;
1778 }
1779
1780 return skb;
1781
1782fail:
1783 kfree_skb(skb);
1784 return NULL;
1785}
1786
1787static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1788{
1789 struct l2cap_conf_opt *opt = *ptr;
1790 int len;
1791
1792 len = L2CAP_CONF_OPT_SIZE + opt->len;
1793 *ptr += len;
1794
1795 *type = opt->type;
1796 *olen = opt->len;
1797
1798 switch (opt->len) {
1799 case 1:
1800 *val = *((u8 *) opt->val);
1801 break;
1802
1803 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001804 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 break;
1806
1807 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001808 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 break;
1810
1811 default:
1812 *val = (unsigned long) opt->val;
1813 break;
1814 }
1815
1816 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1817 return len;
1818}
1819
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1821{
1822 struct l2cap_conf_opt *opt = *ptr;
1823
1824 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1825
1826 opt->type = type;
1827 opt->len = len;
1828
1829 switch (len) {
1830 case 1:
1831 *((u8 *) opt->val) = val;
1832 break;
1833
1834 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001835 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 break;
1837
1838 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001839 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 break;
1841
1842 default:
1843 memcpy(opt->val, (void *) val, len);
1844 break;
1845 }
1846
1847 *ptr += L2CAP_CONF_OPT_SIZE + len;
1848}
1849
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001850static void l2cap_ack_timeout(unsigned long arg)
1851{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001852 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001853
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001854 bh_lock_sock(chan->sk);
1855 l2cap_send_ack(chan);
1856 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001857}
1858
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001859static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001860{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001861 struct sock *sk = chan->sk;
1862
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001863 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001864 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001865 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001866 chan->num_acked = 0;
1867 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001868
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001869 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1870 (unsigned long) chan);
1871 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1872 (unsigned long) chan);
1873 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001874
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001875 skb_queue_head_init(&chan->srej_q);
1876 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001877
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001878 INIT_LIST_HEAD(&chan->srej_l);
1879
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001880 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001881
1882 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001883}
1884
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001885static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1886{
1887 switch (mode) {
1888 case L2CAP_MODE_STREAMING:
1889 case L2CAP_MODE_ERTM:
1890 if (l2cap_mode_supported(mode, remote_feat_mask))
1891 return mode;
1892 /* fall through */
1893 default:
1894 return L2CAP_MODE_BASIC;
1895 }
1896}
1897
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03001898static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001901 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 void *ptr = req->data;
1903
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001904 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001906 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001907 goto done;
1908
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001909 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001910 case L2CAP_MODE_STREAMING:
1911 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001912 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001913 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001914
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001915 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001916 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001917 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001918 break;
1919 }
1920
1921done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001922 if (chan->imtu != L2CAP_DEFAULT_MTU)
1923 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001924
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001925 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001926 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001927 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1928 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001929 break;
1930
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001931 rfc.mode = L2CAP_MODE_BASIC;
1932 rfc.txwin_size = 0;
1933 rfc.max_transmit = 0;
1934 rfc.retrans_timeout = 0;
1935 rfc.monitor_timeout = 0;
1936 rfc.max_pdu_size = 0;
1937
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001938 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1939 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001940 break;
1941
1942 case L2CAP_MODE_ERTM:
1943 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001944 rfc.txwin_size = chan->tx_win;
1945 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001946 rfc.retrans_timeout = 0;
1947 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001948 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001949 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1950 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001951
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001952 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1953 (unsigned long) &rfc);
1954
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001955 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001956 break;
1957
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001958 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001959 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001960 chan->fcs = L2CAP_FCS_NONE;
1961 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001962 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001963 break;
1964
1965 case L2CAP_MODE_STREAMING:
1966 rfc.mode = L2CAP_MODE_STREAMING;
1967 rfc.txwin_size = 0;
1968 rfc.max_transmit = 0;
1969 rfc.retrans_timeout = 0;
1970 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001971 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001972 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1973 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001974
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001975 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1976 (unsigned long) &rfc);
1977
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001978 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001979 break;
1980
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001981 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001982 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001983 chan->fcs = L2CAP_FCS_NONE;
1984 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001985 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001986 break;
1987 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001989 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001990 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991
1992 return ptr - data;
1993}
1994
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001995static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001997 struct l2cap_conf_rsp *rsp = data;
1998 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001999 void *req = chan->conf_req;
2000 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002001 int type, hint, olen;
2002 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002003 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002004 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002005 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002007 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002008
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002009 while (len >= L2CAP_CONF_OPT_SIZE) {
2010 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002012 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002013 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002014
2015 switch (type) {
2016 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002017 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002018 break;
2019
2020 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002021 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002022 break;
2023
2024 case L2CAP_CONF_QOS:
2025 break;
2026
Marcel Holtmann6464f352007-10-20 13:39:51 +02002027 case L2CAP_CONF_RFC:
2028 if (olen == sizeof(rfc))
2029 memcpy(&rfc, (void *) val, olen);
2030 break;
2031
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002032 case L2CAP_CONF_FCS:
2033 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002034 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002035
2036 break;
2037
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002038 default:
2039 if (hint)
2040 break;
2041
2042 result = L2CAP_CONF_UNKNOWN;
2043 *((u8 *) ptr++) = type;
2044 break;
2045 }
2046 }
2047
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002048 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002049 goto done;
2050
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002051 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002052 case L2CAP_MODE_STREAMING:
2053 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002054 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002055 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002056 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002057 break;
2058 }
2059
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002060 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002061 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002062
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002063 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002064 }
2065
2066done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002067 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002068 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002069 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002070
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002071 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002072 return -ECONNREFUSED;
2073
2074 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2075 sizeof(rfc), (unsigned long) &rfc);
2076 }
2077
2078
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002079 if (result == L2CAP_CONF_SUCCESS) {
2080 /* Configure output options and let the other side know
2081 * which ones we don't like. */
2082
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002083 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2084 result = L2CAP_CONF_UNACCEPT;
2085 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002086 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002087 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002088 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002089 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002090
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002091 switch (rfc.mode) {
2092 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002093 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002094 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002095 break;
2096
2097 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002098 chan->remote_tx_win = rfc.txwin_size;
2099 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002100
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002101 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2102 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002103
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002104 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002105
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002106 rfc.retrans_timeout =
2107 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2108 rfc.monitor_timeout =
2109 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002110
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002111 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002112
2113 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2114 sizeof(rfc), (unsigned long) &rfc);
2115
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002116 break;
2117
2118 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002119 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2120 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002121
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002122 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002123
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002124 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002125
2126 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2127 sizeof(rfc), (unsigned long) &rfc);
2128
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002129 break;
2130
2131 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002132 result = L2CAP_CONF_UNACCEPT;
2133
2134 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002135 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002136 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002137
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002138 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002139 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002140 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002141 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002142 rsp->result = cpu_to_le16(result);
2143 rsp->flags = cpu_to_le16(0x0000);
2144
2145 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146}
2147
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002148static 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 -03002149{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002150 struct l2cap_conf_req *req = data;
2151 void *ptr = req->data;
2152 int type, olen;
2153 unsigned long val;
2154 struct l2cap_conf_rfc rfc;
2155
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002156 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002157
2158 while (len >= L2CAP_CONF_OPT_SIZE) {
2159 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2160
2161 switch (type) {
2162 case L2CAP_CONF_MTU:
2163 if (val < L2CAP_DEFAULT_MIN_MTU) {
2164 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002165 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002166 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002167 chan->imtu = val;
2168 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002169 break;
2170
2171 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002172 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002173 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002174 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002175 break;
2176
2177 case L2CAP_CONF_RFC:
2178 if (olen == sizeof(rfc))
2179 memcpy(&rfc, (void *)val, olen);
2180
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002181 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002182 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002183 return -ECONNREFUSED;
2184
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002185 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002186
2187 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2188 sizeof(rfc), (unsigned long) &rfc);
2189 break;
2190 }
2191 }
2192
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002193 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002194 return -ECONNREFUSED;
2195
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002196 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002197
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002198 if (*result == L2CAP_CONF_SUCCESS) {
2199 switch (rfc.mode) {
2200 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002201 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2202 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2203 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002204 break;
2205 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002206 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002207 }
2208 }
2209
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002210 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002211 req->flags = cpu_to_le16(0x0000);
2212
2213 return ptr - data;
2214}
2215
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002216static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217{
2218 struct l2cap_conf_rsp *rsp = data;
2219 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002221 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002223 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002224 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002225 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226
2227 return ptr - data;
2228}
2229
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002230void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002231{
2232 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002233 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002234 u8 buf[128];
2235
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002236 rsp.scid = cpu_to_le16(chan->dcid);
2237 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002238 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2239 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2240 l2cap_send_cmd(conn, chan->ident,
2241 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2242
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002243 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002244 return;
2245
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002246 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2247 l2cap_build_conf_req(chan, buf), buf);
2248 chan->num_conf_req++;
2249}
2250
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002251static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002252{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002253 int type, olen;
2254 unsigned long val;
2255 struct l2cap_conf_rfc rfc;
2256
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002257 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002258
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002259 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002260 return;
2261
2262 while (len >= L2CAP_CONF_OPT_SIZE) {
2263 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2264
2265 switch (type) {
2266 case L2CAP_CONF_RFC:
2267 if (olen == sizeof(rfc))
2268 memcpy(&rfc, (void *)val, olen);
2269 goto done;
2270 }
2271 }
2272
2273done:
2274 switch (rfc.mode) {
2275 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002276 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2277 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2278 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002279 break;
2280 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002281 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002282 }
2283}
2284
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002285static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2286{
2287 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2288
2289 if (rej->reason != 0x0000)
2290 return 0;
2291
2292 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2293 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002294 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002295
2296 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002297 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002298
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002299 l2cap_conn_start(conn);
2300 }
2301
2302 return 0;
2303}
2304
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2306{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2308 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002309 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002310 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002311 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312
2313 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002314 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315
2316 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2317
2318 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002319 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2320 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 result = L2CAP_CR_BAD_PSM;
2322 goto sendresp;
2323 }
2324
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002325 parent = pchan->sk;
2326
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002327 bh_lock_sock(parent);
2328
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002329 /* Check if the ACL is secure enough (if not SDP) */
2330 if (psm != cpu_to_le16(0x0001) &&
2331 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002332 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002333 result = L2CAP_CR_SEC_BLOCK;
2334 goto response;
2335 }
2336
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 result = L2CAP_CR_NO_MEM;
2338
2339 /* Check for backlog size */
2340 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002341 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342 goto response;
2343 }
2344
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002345 chan = pchan->ops->new_connection(pchan->data);
2346 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 goto response;
2348
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002349 sk = chan->sk;
2350
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002351 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352
2353 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002354 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2355 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002357 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 goto response;
2359 }
2360
2361 hci_conn_hold(conn->hcon);
2362
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 bacpy(&bt_sk(sk)->src, conn->src);
2364 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002365 chan->psm = psm;
2366 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002368 bt_accept_enqueue(parent, sk);
2369
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002370 __l2cap_chan_add(conn, chan);
2371
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002372 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002374 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002376 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377
Marcel Holtmann984947d2009-02-06 23:35:19 +01002378 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002379 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002380 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002381 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002382 result = L2CAP_CR_PEND;
2383 status = L2CAP_CS_AUTHOR_PEND;
2384 parent->sk_data_ready(parent, 0);
2385 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002386 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002387 result = L2CAP_CR_SUCCESS;
2388 status = L2CAP_CS_NO_INFO;
2389 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002390 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002391 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002392 result = L2CAP_CR_PEND;
2393 status = L2CAP_CS_AUTHEN_PEND;
2394 }
2395 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002396 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002397 result = L2CAP_CR_PEND;
2398 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 }
2400
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002401 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402
2403response:
2404 bh_unlock_sock(parent);
2405
2406sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002407 rsp.scid = cpu_to_le16(scid);
2408 rsp.dcid = cpu_to_le16(dcid);
2409 rsp.result = cpu_to_le16(result);
2410 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002412
2413 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2414 struct l2cap_info_req info;
2415 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2416
2417 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2418 conn->info_ident = l2cap_get_ident(conn);
2419
2420 mod_timer(&conn->info_timer, jiffies +
2421 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2422
2423 l2cap_send_cmd(conn, conn->info_ident,
2424 L2CAP_INFO_REQ, sizeof(info), &info);
2425 }
2426
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002427 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002428 result == L2CAP_CR_SUCCESS) {
2429 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002430 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002431 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002432 l2cap_build_conf_req(chan, buf), buf);
2433 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002434 }
2435
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 return 0;
2437}
2438
2439static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2440{
2441 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2442 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002443 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444 struct sock *sk;
2445 u8 req[128];
2446
2447 scid = __le16_to_cpu(rsp->scid);
2448 dcid = __le16_to_cpu(rsp->dcid);
2449 result = __le16_to_cpu(rsp->result);
2450 status = __le16_to_cpu(rsp->status);
2451
2452 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2453
2454 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002455 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002456 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002457 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002459 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002460 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002461 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462 }
2463
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002464 sk = chan->sk;
2465
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466 switch (result) {
2467 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002468 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002469 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002470 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002471 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002472
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002473 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002474 break;
2475
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002477 l2cap_build_conf_req(chan, req), req);
2478 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 break;
2480
2481 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002482 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483 break;
2484
2485 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002486 /* don't delete l2cap channel if sk is owned by user */
2487 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002488 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002489 __clear_chan_timer(chan);
2490 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002491 break;
2492 }
2493
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002494 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495 break;
2496 }
2497
2498 bh_unlock_sock(sk);
2499 return 0;
2500}
2501
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002502static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002503{
2504 /* FCS is enabled only in ERTM or streaming mode, if one or both
2505 * sides request it.
2506 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002507 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002508 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002509 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002510 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002511}
2512
Al Viro88219a02007-07-29 00:17:25 -07002513static 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 -07002514{
2515 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2516 u16 dcid, flags;
2517 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002518 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002520 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521
2522 dcid = __le16_to_cpu(req->dcid);
2523 flags = __le16_to_cpu(req->flags);
2524
2525 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2526
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002527 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002528 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529 return -ENOENT;
2530
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002531 sk = chan->sk;
2532
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002533 if (chan->state != BT_CONFIG) {
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002534 struct l2cap_cmd_rej rej;
2535
2536 rej.reason = cpu_to_le16(0x0002);
2537 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2538 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002539 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002540 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002541
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002542 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002543 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002544 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002545 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002546 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002547 L2CAP_CONF_REJECT, flags), rsp);
2548 goto unlock;
2549 }
2550
2551 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002552 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2553 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554
2555 if (flags & 0x0001) {
2556 /* Incomplete config. Send empty response. */
2557 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002558 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002559 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 goto unlock;
2561 }
2562
2563 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002564 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002565 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002566 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002568 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002569
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002570 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002571 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002572
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002573 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002574 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002575
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002576 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002577 goto unlock;
2578
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002579 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002580 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002581
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002582 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002583
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002584 chan->next_tx_seq = 0;
2585 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002586 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002587 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002588 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002589
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002591 goto unlock;
2592 }
2593
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002594 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002595 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002597 l2cap_build_conf_req(chan, buf), buf);
2598 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599 }
2600
2601unlock:
2602 bh_unlock_sock(sk);
2603 return 0;
2604}
2605
2606static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2607{
2608 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2609 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002610 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002612 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613
2614 scid = __le16_to_cpu(rsp->scid);
2615 flags = __le16_to_cpu(rsp->flags);
2616 result = __le16_to_cpu(rsp->result);
2617
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002618 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2619 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002621 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002622 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623 return 0;
2624
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002625 sk = chan->sk;
2626
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 switch (result) {
2628 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002629 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630 break;
2631
2632 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002633 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002634 char req[64];
2635
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002636 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002637 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002638 goto done;
2639 }
2640
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002641 /* throw out any old stored conf requests */
2642 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002643 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2644 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002645 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002646 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002647 goto done;
2648 }
2649
2650 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2651 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002652 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002653 if (result != L2CAP_CONF_SUCCESS)
2654 goto done;
2655 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 }
2657
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002658 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002659 sk->sk_err = ECONNRESET;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002660 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002661 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 goto done;
2663 }
2664
2665 if (flags & 0x01)
2666 goto done;
2667
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002668 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002670 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002671 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002672
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002673 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002674 chan->next_tx_seq = 0;
2675 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002676 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002677 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002678 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002679
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 l2cap_chan_ready(sk);
2681 }
2682
2683done:
2684 bh_unlock_sock(sk);
2685 return 0;
2686}
2687
2688static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2689{
2690 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2691 struct l2cap_disconn_rsp rsp;
2692 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002693 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694 struct sock *sk;
2695
2696 scid = __le16_to_cpu(req->scid);
2697 dcid = __le16_to_cpu(req->dcid);
2698
2699 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2700
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002701 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002702 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 return 0;
2704
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002705 sk = chan->sk;
2706
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002707 rsp.dcid = cpu_to_le16(chan->scid);
2708 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2710
2711 sk->sk_shutdown = SHUTDOWN_MASK;
2712
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002713 /* don't delete l2cap channel if sk is owned by user */
2714 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002715 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002716 __clear_chan_timer(chan);
2717 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002718 bh_unlock_sock(sk);
2719 return 0;
2720 }
2721
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002722 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723 bh_unlock_sock(sk);
2724
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002725 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 return 0;
2727}
2728
2729static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2730{
2731 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2732 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002733 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734 struct sock *sk;
2735
2736 scid = __le16_to_cpu(rsp->scid);
2737 dcid = __le16_to_cpu(rsp->dcid);
2738
2739 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2740
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002741 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002742 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743 return 0;
2744
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002745 sk = chan->sk;
2746
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002747 /* don't delete l2cap channel if sk is owned by user */
2748 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002749 l2cap_state_change(chan,BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002750 __clear_chan_timer(chan);
2751 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002752 bh_unlock_sock(sk);
2753 return 0;
2754 }
2755
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002756 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757 bh_unlock_sock(sk);
2758
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002759 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760 return 0;
2761}
2762
2763static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2764{
2765 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 u16 type;
2767
2768 type = __le16_to_cpu(req->type);
2769
2770 BT_DBG("type 0x%4.4x", type);
2771
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002772 if (type == L2CAP_IT_FEAT_MASK) {
2773 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002774 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002775 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2776 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2777 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002778 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002779 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2780 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002781 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002782 l2cap_send_cmd(conn, cmd->ident,
2783 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002784 } else if (type == L2CAP_IT_FIXED_CHAN) {
2785 u8 buf[12];
2786 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2787 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2788 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2789 memcpy(buf + 4, l2cap_fixed_chan, 8);
2790 l2cap_send_cmd(conn, cmd->ident,
2791 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002792 } else {
2793 struct l2cap_info_rsp rsp;
2794 rsp.type = cpu_to_le16(type);
2795 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2796 l2cap_send_cmd(conn, cmd->ident,
2797 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2798 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799
2800 return 0;
2801}
2802
2803static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2804{
2805 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2806 u16 type, result;
2807
2808 type = __le16_to_cpu(rsp->type);
2809 result = __le16_to_cpu(rsp->result);
2810
2811 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2812
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002813 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2814 if (cmd->ident != conn->info_ident ||
2815 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2816 return 0;
2817
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002818 del_timer(&conn->info_timer);
2819
Ville Tervoadb08ed2010-08-04 09:43:33 +03002820 if (result != L2CAP_IR_SUCCESS) {
2821 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2822 conn->info_ident = 0;
2823
2824 l2cap_conn_start(conn);
2825
2826 return 0;
2827 }
2828
Marcel Holtmann984947d2009-02-06 23:35:19 +01002829 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002830 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002831
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002832 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002833 struct l2cap_info_req req;
2834 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2835
2836 conn->info_ident = l2cap_get_ident(conn);
2837
2838 l2cap_send_cmd(conn, conn->info_ident,
2839 L2CAP_INFO_REQ, sizeof(req), &req);
2840 } else {
2841 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2842 conn->info_ident = 0;
2843
2844 l2cap_conn_start(conn);
2845 }
2846 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002847 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002848 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002849
2850 l2cap_conn_start(conn);
2851 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002852
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853 return 0;
2854}
2855
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002856static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002857 u16 to_multiplier)
2858{
2859 u16 max_latency;
2860
2861 if (min > max || min < 6 || max > 3200)
2862 return -EINVAL;
2863
2864 if (to_multiplier < 10 || to_multiplier > 3200)
2865 return -EINVAL;
2866
2867 if (max >= to_multiplier * 8)
2868 return -EINVAL;
2869
2870 max_latency = (to_multiplier * 8 / max) - 1;
2871 if (latency > 499 || latency > max_latency)
2872 return -EINVAL;
2873
2874 return 0;
2875}
2876
2877static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2878 struct l2cap_cmd_hdr *cmd, u8 *data)
2879{
2880 struct hci_conn *hcon = conn->hcon;
2881 struct l2cap_conn_param_update_req *req;
2882 struct l2cap_conn_param_update_rsp rsp;
2883 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002884 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002885
2886 if (!(hcon->link_mode & HCI_LM_MASTER))
2887 return -EINVAL;
2888
2889 cmd_len = __le16_to_cpu(cmd->len);
2890 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2891 return -EPROTO;
2892
2893 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002894 min = __le16_to_cpu(req->min);
2895 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002896 latency = __le16_to_cpu(req->latency);
2897 to_multiplier = __le16_to_cpu(req->to_multiplier);
2898
2899 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2900 min, max, latency, to_multiplier);
2901
2902 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002903
2904 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2905 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002906 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2907 else
2908 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2909
2910 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2911 sizeof(rsp), &rsp);
2912
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002913 if (!err)
2914 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2915
Claudio Takahaside731152011-02-11 19:28:55 -02002916 return 0;
2917}
2918
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002919static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2920 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2921{
2922 int err = 0;
2923
2924 switch (cmd->code) {
2925 case L2CAP_COMMAND_REJ:
2926 l2cap_command_rej(conn, cmd, data);
2927 break;
2928
2929 case L2CAP_CONN_REQ:
2930 err = l2cap_connect_req(conn, cmd, data);
2931 break;
2932
2933 case L2CAP_CONN_RSP:
2934 err = l2cap_connect_rsp(conn, cmd, data);
2935 break;
2936
2937 case L2CAP_CONF_REQ:
2938 err = l2cap_config_req(conn, cmd, cmd_len, data);
2939 break;
2940
2941 case L2CAP_CONF_RSP:
2942 err = l2cap_config_rsp(conn, cmd, data);
2943 break;
2944
2945 case L2CAP_DISCONN_REQ:
2946 err = l2cap_disconnect_req(conn, cmd, data);
2947 break;
2948
2949 case L2CAP_DISCONN_RSP:
2950 err = l2cap_disconnect_rsp(conn, cmd, data);
2951 break;
2952
2953 case L2CAP_ECHO_REQ:
2954 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2955 break;
2956
2957 case L2CAP_ECHO_RSP:
2958 break;
2959
2960 case L2CAP_INFO_REQ:
2961 err = l2cap_information_req(conn, cmd, data);
2962 break;
2963
2964 case L2CAP_INFO_RSP:
2965 err = l2cap_information_rsp(conn, cmd, data);
2966 break;
2967
2968 default:
2969 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2970 err = -EINVAL;
2971 break;
2972 }
2973
2974 return err;
2975}
2976
2977static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2978 struct l2cap_cmd_hdr *cmd, u8 *data)
2979{
2980 switch (cmd->code) {
2981 case L2CAP_COMMAND_REJ:
2982 return 0;
2983
2984 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002985 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002986
2987 case L2CAP_CONN_PARAM_UPDATE_RSP:
2988 return 0;
2989
2990 default:
2991 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2992 return -EINVAL;
2993 }
2994}
2995
2996static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2997 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998{
2999 u8 *data = skb->data;
3000 int len = skb->len;
3001 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003002 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003
3004 l2cap_raw_recv(conn, skb);
3005
3006 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003007 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3009 data += L2CAP_CMD_HDR_SIZE;
3010 len -= L2CAP_CMD_HDR_SIZE;
3011
Al Viro88219a02007-07-29 00:17:25 -07003012 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013
Al Viro88219a02007-07-29 00:17:25 -07003014 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 -07003015
Al Viro88219a02007-07-29 00:17:25 -07003016 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017 BT_DBG("corrupted command");
3018 break;
3019 }
3020
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003021 if (conn->hcon->type == LE_LINK)
3022 err = l2cap_le_sig_cmd(conn, &cmd, data);
3023 else
3024 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025
3026 if (err) {
3027 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003028
3029 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030
3031 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003032 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3034 }
3035
Al Viro88219a02007-07-29 00:17:25 -07003036 data += cmd_len;
3037 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038 }
3039
3040 kfree_skb(skb);
3041}
3042
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003043static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003044{
3045 u16 our_fcs, rcv_fcs;
3046 int hdr_size = L2CAP_HDR_SIZE + 2;
3047
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003048 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003049 skb_trim(skb, skb->len - 2);
3050 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3051 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3052
3053 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003054 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003055 }
3056 return 0;
3057}
3058
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003059static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003060{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003061 u16 control = 0;
3062
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003063 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003064
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003065 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003066
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003067 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003068 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003069 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003070 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003071 }
3072
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003073 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003074 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003075
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003076 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003077
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003078 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003079 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003080 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003081 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003082 }
3083}
3084
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003085static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u8 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003086{
3087 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003088 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003089
3090 bt_cb(skb)->tx_seq = tx_seq;
3091 bt_cb(skb)->sar = sar;
3092
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003093 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003094 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003095 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003096 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003097 }
3098
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003099 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003100 if (tx_seq_offset < 0)
3101 tx_seq_offset += 64;
3102
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003103 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003104 if (bt_cb(next_skb)->tx_seq == tx_seq)
3105 return -EINVAL;
3106
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003107 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003108 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003109 if (next_tx_seq_offset < 0)
3110 next_tx_seq_offset += 64;
3111
3112 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003113 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003114 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003115 }
3116
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003117 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003118 break;
3119
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003120 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003121
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003122 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003123
3124 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003125}
3126
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003127static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003128{
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003129 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003130 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003131
3132 switch (control & L2CAP_CTRL_SAR) {
3133 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003134 if (test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003135 goto drop;
3136
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003137 return chan->ops->recv(chan->data, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003138
3139 case L2CAP_SDU_START:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003140 if (test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003141 goto drop;
3142
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003143 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003144
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003145 if (chan->sdu_len > chan->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003146 goto disconnect;
3147
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003148 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3149 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003150 return -ENOMEM;
3151
3152 /* pull sdu_len bytes only after alloc, because of Local Busy
3153 * condition we have to be sure that this will be executed
3154 * only once, i.e., when alloc does not fail */
3155 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003156
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003157 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003158
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003159 set_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003160 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003161 break;
3162
3163 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003164 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003165 goto disconnect;
3166
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003167 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003168 goto disconnect;
3169
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003170 chan->partial_sdu_len += skb->len;
3171 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003172 goto drop;
3173
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003174 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003175
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003176 break;
3177
3178 case L2CAP_SDU_END:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003179 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003180 goto disconnect;
3181
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003182 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003183 goto disconnect;
3184
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003185 if (!test_bit(CONN_SAR_RETRY, &chan->conn_state)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003186 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003187
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003188 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003189 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003190
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003191 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003192 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003193
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003194 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003195 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003196
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003197 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003198 if (!_skb) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003199 set_bit(CONN_SAR_RETRY, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003200 return -ENOMEM;
3201 }
3202
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003203 err = chan->ops->recv(chan->data, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003204 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003205 kfree_skb(_skb);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003206 set_bit(CONN_SAR_RETRY, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003207 return err;
3208 }
3209
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003210 clear_bit(CONN_SAR_RETRY, &chan->conn_state);
3211 clear_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003212
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003213 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003214 break;
3215 }
3216
3217 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003218 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003219
3220drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003221 kfree_skb(chan->sdu);
3222 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003223
3224disconnect:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003225 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003226 kfree_skb(skb);
3227 return 0;
3228}
3229
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003230static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003231{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003232 struct sk_buff *skb;
3233 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003234 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003235
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003236 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003237 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003238 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003239 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003240 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003241 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003242 }
3243
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003244 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003245 }
3246
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003247 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003248 goto done;
3249
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003250 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003251 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003252 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003253 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003254
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003255 __clear_retrans_timer(chan);
3256 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003257
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003258 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003259
3260done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003261 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3262 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003263
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003264 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003265
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003266 return 0;
3267}
3268
3269static void l2cap_busy_work(struct work_struct *work)
3270{
3271 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003272 struct l2cap_chan *chan =
3273 container_of(work, struct l2cap_chan, busy_work);
3274 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003275 int n_tries = 0, timeo = HZ/5, err;
3276 struct sk_buff *skb;
3277
3278 lock_sock(sk);
3279
3280 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003281 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003282 set_current_state(TASK_INTERRUPTIBLE);
3283
3284 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3285 err = -EBUSY;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003286 l2cap_send_disconn_req(chan->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003287 break;
3288 }
3289
3290 if (!timeo)
3291 timeo = HZ/5;
3292
3293 if (signal_pending(current)) {
3294 err = sock_intr_errno(timeo);
3295 break;
3296 }
3297
3298 release_sock(sk);
3299 timeo = schedule_timeout(timeo);
3300 lock_sock(sk);
3301
3302 err = sock_error(sk);
3303 if (err)
3304 break;
3305
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003306 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003307 break;
3308 }
3309
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003310 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003311 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003312
3313 release_sock(sk);
3314}
3315
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003316static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003317{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003318 int sctrl, err;
3319
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003320 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003321 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003322 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003323 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003324
3325
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003326 }
3327
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003328 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003329 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003330 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003331 return err;
3332 }
3333
3334 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003335 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003336
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003337 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003338 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003339 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003340
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003341 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003342 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003343 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003344
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003345 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003346
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003347 __clear_ack_timer(chan);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003348
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003349 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003350
3351 return err;
3352}
3353
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003354static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003355{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003356 struct sk_buff *_skb;
3357 int err = -EINVAL;
3358
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003359 /*
3360 * TODO: We have to notify the userland if some data is lost with the
3361 * Streaming Mode.
3362 */
3363
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003364 switch (control & L2CAP_CTRL_SAR) {
3365 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003366 if (test_bit(CONN_SAR_SDU, &chan->conn_state)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003367 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003368 break;
3369 }
3370
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003371 err = chan->ops->recv(chan->data, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003372 if (!err)
3373 return 0;
3374
3375 break;
3376
3377 case L2CAP_SDU_START:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003378 if (test_bit(CONN_SAR_SDU, &chan->conn_state)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003379 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003380 break;
3381 }
3382
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003383 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003384 skb_pull(skb, 2);
3385
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003386 if (chan->sdu_len > chan->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003387 err = -EMSGSIZE;
3388 break;
3389 }
3390
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003391 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3392 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003393 err = -ENOMEM;
3394 break;
3395 }
3396
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003397 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003398
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003399 set_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003400 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003401 err = 0;
3402 break;
3403
3404 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003405 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003406 break;
3407
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003408 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003409
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003410 chan->partial_sdu_len += skb->len;
3411 if (chan->partial_sdu_len > chan->sdu_len)
3412 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003413 else
3414 err = 0;
3415
3416 break;
3417
3418 case L2CAP_SDU_END:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003419 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003420 break;
3421
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003422 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003423
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003424 clear_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003425 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003426
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003427 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003428 goto drop;
3429
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003430 if (chan->partial_sdu_len == chan->sdu_len) {
3431 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003432 err = chan->ops->recv(chan->data, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003433 if (err < 0)
3434 kfree_skb(_skb);
3435 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003436 err = 0;
3437
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003438drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003439 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003440 break;
3441 }
3442
3443 kfree_skb(skb);
3444 return err;
3445}
3446
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003447static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003448{
3449 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003450 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003451
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003452 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003453 if (bt_cb(skb)->tx_seq != tx_seq)
3454 break;
3455
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003456 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003457 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003458 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003459 chan->buffer_seq_srej =
3460 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003461 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003462 }
3463}
3464
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003465static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003466{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003467 struct srej_list *l, *tmp;
3468 u16 control;
3469
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003470 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003471 if (l->tx_seq == tx_seq) {
3472 list_del(&l->list);
3473 kfree(l);
3474 return;
3475 }
3476 control = L2CAP_SUPER_SELECT_REJECT;
3477 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003478 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003479 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003480 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003481 }
3482}
3483
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003484static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003485{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003486 struct srej_list *new;
3487 u16 control;
3488
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003489 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003490 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003491 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003492 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003493
3494 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003495 new->tx_seq = chan->expected_tx_seq;
3496 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003497 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003498 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003499 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003500}
3501
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003502static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003503{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003504 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003505 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003506 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003507 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003508 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003509 int err = 0;
3510
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003511 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3512 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003513
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003514 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003515 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003516 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003517 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003518 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003519 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003520 }
3521
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003522 chan->expected_ack_seq = req_seq;
3523 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003524
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003525 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003526 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003527
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003528 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003529 if (tx_seq_offset < 0)
3530 tx_seq_offset += 64;
3531
3532 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003533 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003534 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003535 goto drop;
3536 }
3537
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003538 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003539 goto drop;
3540
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003541 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003542 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003543
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003544 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003545 struct srej_list, list);
3546 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003547 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003548 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003549
3550 list_del(&first->list);
3551 kfree(first);
3552
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003553 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003554 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003555 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003556 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003557 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003558 }
3559 } else {
3560 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003561
3562 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003563 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003564 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003565
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003566 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003567 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003568 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003569 return 0;
3570 }
3571 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003572 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003573 }
3574 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003575 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003576 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003577 if (expected_tx_seq_offset < 0)
3578 expected_tx_seq_offset += 64;
3579
3580 /* duplicated tx_seq */
3581 if (tx_seq_offset < expected_tx_seq_offset)
3582 goto drop;
3583
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003584 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003585
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003586 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003587
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003588 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003589 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003590
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003591 __skb_queue_head_init(&chan->srej_q);
3592 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003593 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003594
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003595 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003596
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003597 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003598
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003599 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003600 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003601 return 0;
3602
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003603expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003604 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003605
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003606 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003607 bt_cb(skb)->tx_seq = tx_seq;
3608 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003609 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003610 return 0;
3611 }
3612
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003613 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003614 if (err < 0)
3615 return 0;
3616
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003617 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003618 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003619 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003620 }
3621
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003622 __set_ack_timer(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003623
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003624 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3625 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003626 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003627
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003628 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003629
3630drop:
3631 kfree_skb(skb);
3632 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003633}
3634
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003635static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003636{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003637 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003638 rx_control);
3639
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003640 chan->expected_ack_seq = __get_reqseq(rx_control);
3641 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003642
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003643 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003644 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3645 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3646 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003647 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003648 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003649
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003650 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003651 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003652 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003653 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003654 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003655
3656 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003657 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003658
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003659 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003660 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003661
3662 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003663 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003664 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003665 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003666
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003667 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3668 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003669 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003670 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003671 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003672 }
3673}
3674
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003675static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003676{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003677 u8 tx_seq = __get_reqseq(rx_control);
3678
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003679 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003680
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003681 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003682
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003683 chan->expected_ack_seq = tx_seq;
3684 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003685
3686 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003687 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003688 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003689 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003690 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003691
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003692 if (test_bit(CONN_WAIT_F, &chan->conn_state))
3693 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003694 }
3695}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003696static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003697{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003698 u8 tx_seq = __get_reqseq(rx_control);
3699
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003700 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003701
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003702 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003703
3704 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003705 chan->expected_ack_seq = tx_seq;
3706 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003707
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003708 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003709 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003710
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003711 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003712
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003713 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003714 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003715 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003716 }
3717 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003718 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003719 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003720 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003721 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003722 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003723 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003724 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003725 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003726 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003727 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003728 }
3729 }
3730}
3731
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003732static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003733{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003734 u8 tx_seq = __get_reqseq(rx_control);
3735
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003736 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003737
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003738 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003739 chan->expected_ack_seq = tx_seq;
3740 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003741
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003742 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003743 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003744
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003745 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003746 __clear_retrans_timer(chan);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003747 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003748 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003749 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003750 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003751
3752 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003753 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003754 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003755 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003756}
3757
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003758static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003759{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003760 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003761
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003762 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003763 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003764 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003765 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003766 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003767 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003768 }
3769
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003770 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3771 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003772 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003773 break;
3774
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003775 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003776 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003777 break;
3778
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003779 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003780 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003781 break;
3782
3783 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003784 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003785 break;
3786 }
3787
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003788 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003789 return 0;
3790}
3791
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003792static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3793{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003794 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003795 u16 control;
3796 u8 req_seq;
3797 int len, next_tx_seq_offset, req_seq_offset;
3798
3799 control = get_unaligned_le16(skb->data);
3800 skb_pull(skb, 2);
3801 len = skb->len;
3802
3803 /*
3804 * We can just drop the corrupted I-frame here.
3805 * Receiver will miss it and start proper recovery
3806 * procedures and ask retransmission.
3807 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003808 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003809 goto drop;
3810
3811 if (__is_sar_start(control) && __is_iframe(control))
3812 len -= 2;
3813
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003814 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003815 len -= 2;
3816
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003817 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003818 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003819 goto drop;
3820 }
3821
3822 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003823 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003824 if (req_seq_offset < 0)
3825 req_seq_offset += 64;
3826
3827 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003828 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003829 if (next_tx_seq_offset < 0)
3830 next_tx_seq_offset += 64;
3831
3832 /* check for invalid req-seq */
3833 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003834 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003835 goto drop;
3836 }
3837
3838 if (__is_iframe(control)) {
3839 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003840 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003841 goto drop;
3842 }
3843
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003844 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003845 } else {
3846 if (len != 0) {
3847 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003848 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003849 goto drop;
3850 }
3851
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003852 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003853 }
3854
3855 return 0;
3856
3857drop:
3858 kfree_skb(skb);
3859 return 0;
3860}
3861
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3863{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003864 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003865 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003866 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003867 u8 tx_seq;
3868 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003870 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003871 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872 BT_DBG("unknown cid 0x%4.4x", cid);
3873 goto drop;
3874 }
3875
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003876 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003877
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003878 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003879
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003880 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881 goto drop;
3882
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003883 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003884 case L2CAP_MODE_BASIC:
3885 /* If socket recv buffers overflows we drop data here
3886 * which is *bad* because L2CAP has to be reliable.
3887 * But we don't have any other choice. L2CAP doesn't
3888 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003890 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003891 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003893 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003894 goto done;
3895 break;
3896
3897 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003898 if (!sock_owned_by_user(sk)) {
3899 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003900 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003901 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003902 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003903 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003904
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003905 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003906
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003907 case L2CAP_MODE_STREAMING:
3908 control = get_unaligned_le16(skb->data);
3909 skb_pull(skb, 2);
3910 len = skb->len;
3911
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003912 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003913 goto drop;
3914
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003915 if (__is_sar_start(control))
3916 len -= 2;
3917
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003918 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003919 len -= 2;
3920
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003921 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003922 goto drop;
3923
3924 tx_seq = __get_txseq(control);
3925
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003926 if (chan->expected_tx_seq == tx_seq)
3927 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003928 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003929 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003930
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003931 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003932
3933 goto done;
3934
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003935 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003936 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003937 break;
3938 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939
3940drop:
3941 kfree_skb(skb);
3942
3943done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003944 if (sk)
3945 bh_unlock_sock(sk);
3946
Linus Torvalds1da177e2005-04-16 15:20:36 -07003947 return 0;
3948}
3949
Al Viro8e036fc2007-07-29 00:16:36 -07003950static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003952 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003953 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003955 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3956 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957 goto drop;
3958
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003959 sk = chan->sk;
3960
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003961 bh_lock_sock(sk);
3962
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963 BT_DBG("sk %p, len %d", sk, skb->len);
3964
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003965 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966 goto drop;
3967
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003968 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969 goto drop;
3970
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003971 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972 goto done;
3973
3974drop:
3975 kfree_skb(skb);
3976
3977done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003978 if (sk)
3979 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003980 return 0;
3981}
3982
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003983static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3984{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003985 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003986 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003987
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003988 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3989 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003990 goto drop;
3991
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003992 sk = chan->sk;
3993
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003994 bh_lock_sock(sk);
3995
3996 BT_DBG("sk %p, len %d", sk, skb->len);
3997
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003998 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003999 goto drop;
4000
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004001 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004002 goto drop;
4003
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004004 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004005 goto done;
4006
4007drop:
4008 kfree_skb(skb);
4009
4010done:
4011 if (sk)
4012 bh_unlock_sock(sk);
4013 return 0;
4014}
4015
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4017{
4018 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004019 u16 cid, len;
4020 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021
4022 skb_pull(skb, L2CAP_HDR_SIZE);
4023 cid = __le16_to_cpu(lh->cid);
4024 len = __le16_to_cpu(lh->len);
4025
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004026 if (len != skb->len) {
4027 kfree_skb(skb);
4028 return;
4029 }
4030
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4032
4033 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004034 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004035 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036 l2cap_sig_channel(conn, skb);
4037 break;
4038
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004039 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004040 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041 skb_pull(skb, 2);
4042 l2cap_conless_channel(conn, psm, skb);
4043 break;
4044
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004045 case L2CAP_CID_LE_DATA:
4046 l2cap_att_channel(conn, cid, skb);
4047 break;
4048
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004049 case L2CAP_CID_SMP:
4050 if (smp_sig_channel(conn, skb))
4051 l2cap_conn_del(conn->hcon, EACCES);
4052 break;
4053
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054 default:
4055 l2cap_data_channel(conn, cid, skb);
4056 break;
4057 }
4058}
4059
4060/* ---- L2CAP interface with lower layer (HCI) ---- */
4061
4062static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4063{
4064 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004065 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066
4067 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004068 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069
4070 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4071
4072 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004073 read_lock(&chan_list_lock);
4074 list_for_each_entry(c, &chan_list, global_l) {
4075 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004076
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004077 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078 continue;
4079
4080 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004081 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004082 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004083 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004084 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004085 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4086 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004087 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004088 lm2 |= HCI_LM_MASTER;
4089 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004091 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092
4093 return exact ? lm1 : lm2;
4094}
4095
4096static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4097{
Marcel Holtmann01394182006-07-03 10:02:46 +02004098 struct l2cap_conn *conn;
4099
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4101
Ville Tervoacd7d372011-02-10 22:38:49 -03004102 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004103 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104
4105 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106 conn = l2cap_conn_add(hcon, status);
4107 if (conn)
4108 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004109 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110 l2cap_conn_del(hcon, bt_err(status));
4111
4112 return 0;
4113}
4114
Marcel Holtmann2950f212009-02-12 14:02:50 +01004115static int l2cap_disconn_ind(struct hci_conn *hcon)
4116{
4117 struct l2cap_conn *conn = hcon->l2cap_data;
4118
4119 BT_DBG("hcon %p", hcon);
4120
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03004121 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004122 return 0x13;
4123
4124 return conn->disc_reason;
4125}
4126
4127static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128{
4129 BT_DBG("hcon %p reason %d", hcon, reason);
4130
Ville Tervoacd7d372011-02-10 22:38:49 -03004131 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004132 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133
4134 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004135
Linus Torvalds1da177e2005-04-16 15:20:36 -07004136 return 0;
4137}
4138
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004139static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004140{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004141 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004142 return;
4143
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004144 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004145 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004146 __clear_chan_timer(chan);
4147 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004148 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004149 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004150 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004151 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004152 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004153 }
4154}
4155
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004156static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004158 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004159 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160
Marcel Holtmann01394182006-07-03 10:02:46 +02004161 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004163
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164 BT_DBG("conn %p", conn);
4165
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004166 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004167
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004168 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004169 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004170
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171 bh_lock_sock(sk);
4172
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004173 BT_DBG("chan->scid %d", chan->scid);
4174
4175 if (chan->scid == L2CAP_CID_LE_DATA) {
4176 if (!status && encrypt) {
4177 chan->sec_level = hcon->sec_level;
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03004178 del_timer(&conn->security_timer);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004179 l2cap_chan_ready(sk);
4180 }
4181
4182 bh_unlock_sock(sk);
4183 continue;
4184 }
4185
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004186 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004187 bh_unlock_sock(sk);
4188 continue;
4189 }
4190
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004191 if (!status && (chan->state == BT_CONNECTED ||
4192 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004193 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004194 bh_unlock_sock(sk);
4195 continue;
4196 }
4197
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004198 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004199 if (!status) {
4200 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004201 req.scid = cpu_to_le16(chan->scid);
4202 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004203
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004204 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004205 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004206
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004207 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004208 L2CAP_CONN_REQ, sizeof(req), &req);
4209 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004210 __clear_chan_timer(chan);
4211 __set_chan_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004212 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004213 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004214 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004215 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004216
4217 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004218 if (bt_sk(sk)->defer_setup) {
4219 struct sock *parent = bt_sk(sk)->parent;
4220 res = L2CAP_CR_PEND;
4221 stat = L2CAP_CS_AUTHOR_PEND;
4222 parent->sk_data_ready(parent, 0);
4223 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004224 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004225 res = L2CAP_CR_SUCCESS;
4226 stat = L2CAP_CS_NO_INFO;
4227 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004228 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004229 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004230 __set_chan_timer(chan, HZ / 10);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004231 res = L2CAP_CR_SEC_BLOCK;
4232 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004233 }
4234
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004235 rsp.scid = cpu_to_le16(chan->dcid);
4236 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004237 rsp.result = cpu_to_le16(res);
4238 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004239 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4240 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004241 }
4242
Linus Torvalds1da177e2005-04-16 15:20:36 -07004243 bh_unlock_sock(sk);
4244 }
4245
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004246 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004247
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248 return 0;
4249}
4250
4251static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4252{
4253 struct l2cap_conn *conn = hcon->l2cap_data;
4254
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004255 if (!conn)
4256 conn = l2cap_conn_add(hcon, 0);
4257
4258 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004259 goto drop;
4260
4261 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4262
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004263 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004265 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004266 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267 int len;
4268
4269 if (conn->rx_len) {
4270 BT_ERR("Unexpected start frame (len %d)", skb->len);
4271 kfree_skb(conn->rx_skb);
4272 conn->rx_skb = NULL;
4273 conn->rx_len = 0;
4274 l2cap_conn_unreliable(conn, ECOMM);
4275 }
4276
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004277 /* Start fragment always begin with Basic L2CAP header */
4278 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004279 BT_ERR("Frame is too short (len %d)", skb->len);
4280 l2cap_conn_unreliable(conn, ECOMM);
4281 goto drop;
4282 }
4283
4284 hdr = (struct l2cap_hdr *) skb->data;
4285 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004286 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004287
4288 if (len == skb->len) {
4289 /* Complete frame received */
4290 l2cap_recv_frame(conn, skb);
4291 return 0;
4292 }
4293
4294 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4295
4296 if (skb->len > len) {
4297 BT_ERR("Frame is too long (len %d, expected len %d)",
4298 skb->len, len);
4299 l2cap_conn_unreliable(conn, ECOMM);
4300 goto drop;
4301 }
4302
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004303 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004304
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004305 if (chan && chan->sk) {
4306 struct sock *sk = chan->sk;
4307
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004308 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004309 BT_ERR("Frame exceeding recv MTU (len %d, "
4310 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004311 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004312 bh_unlock_sock(sk);
4313 l2cap_conn_unreliable(conn, ECOMM);
4314 goto drop;
4315 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004316 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004317 }
4318
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004320 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4321 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322 goto drop;
4323
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004324 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004325 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326 conn->rx_len = len - skb->len;
4327 } else {
4328 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4329
4330 if (!conn->rx_len) {
4331 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4332 l2cap_conn_unreliable(conn, ECOMM);
4333 goto drop;
4334 }
4335
4336 if (skb->len > conn->rx_len) {
4337 BT_ERR("Fragment is too long (len %d, expected %d)",
4338 skb->len, conn->rx_len);
4339 kfree_skb(conn->rx_skb);
4340 conn->rx_skb = NULL;
4341 conn->rx_len = 0;
4342 l2cap_conn_unreliable(conn, ECOMM);
4343 goto drop;
4344 }
4345
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004346 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004347 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004348 conn->rx_len -= skb->len;
4349
4350 if (!conn->rx_len) {
4351 /* Complete frame received */
4352 l2cap_recv_frame(conn, conn->rx_skb);
4353 conn->rx_skb = NULL;
4354 }
4355 }
4356
4357drop:
4358 kfree_skb(skb);
4359 return 0;
4360}
4361
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004362static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004363{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004364 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004366 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004368 list_for_each_entry(c, &chan_list, global_l) {
4369 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004370
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004371 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 +01004372 batostr(&bt_sk(sk)->src),
4373 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004374 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004375 c->scid, c->dcid, c->imtu, c->omtu,
4376 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004377}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004378
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004379 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004380
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004381 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382}
4383
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004384static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4385{
4386 return single_open(file, l2cap_debugfs_show, inode->i_private);
4387}
4388
4389static const struct file_operations l2cap_debugfs_fops = {
4390 .open = l2cap_debugfs_open,
4391 .read = seq_read,
4392 .llseek = seq_lseek,
4393 .release = single_release,
4394};
4395
4396static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398static struct hci_proto l2cap_hci_proto = {
4399 .name = "L2CAP",
4400 .id = HCI_PROTO_L2CAP,
4401 .connect_ind = l2cap_connect_ind,
4402 .connect_cfm = l2cap_connect_cfm,
4403 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004404 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004405 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406 .recv_acldata = l2cap_recv_acldata
4407};
4408
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004409int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004410{
4411 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004412
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004413 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414 if (err < 0)
4415 return err;
4416
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004417 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004418 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004419 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420 goto error;
4421 }
4422
4423 err = hci_register_proto(&l2cap_hci_proto);
4424 if (err < 0) {
4425 BT_ERR("L2CAP protocol registration failed");
4426 bt_sock_unregister(BTPROTO_L2CAP);
4427 goto error;
4428 }
4429
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004430 if (bt_debugfs) {
4431 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4432 bt_debugfs, NULL, &l2cap_debugfs_fops);
4433 if (!l2cap_debugfs)
4434 BT_ERR("Failed to create L2CAP debug file");
4435 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004436
Linus Torvalds1da177e2005-04-16 15:20:36 -07004437 return 0;
4438
4439error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004440 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004441 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442 return err;
4443}
4444
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004445void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004447 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004448
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004449 flush_workqueue(_busy_wq);
4450 destroy_workqueue(_busy_wq);
4451
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4453 BT_ERR("L2CAP protocol unregistration failed");
4454
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004455 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456}
4457
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004458module_param(disable_ertm, bool, 0644);
4459MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");