blob: 285c5e13c7d51807a9f3dc9789d4cffdeffff08a [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Gustavo F. Padovan590051d2011-12-18 13:39:33 -02006 Copyright (C) 2011 ProFUSION Embedded Systems
Mat Martineau422e9252012-04-27 16:50:55 -07007 Copyright (c) 2012 Code Aurora Forum. All rights reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07008
9 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License version 2 as
13 published by the Free Software Foundation;
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
18 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090019 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
20 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
21 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090024 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
25 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070026 SOFTWARE IS DISCLAIMED.
27*/
28
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020029/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070030
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/module.h>
32
33#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080034#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/errno.h>
36#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/sched.h>
38#include <linux/slab.h>
39#include <linux/poll.h>
40#include <linux/fcntl.h>
41#include <linux/init.h>
42#include <linux/interrupt.h>
43#include <linux/socket.h>
44#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080046#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010047#include <linux/debugfs.h>
48#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030049#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030050#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070051#include <net/sock.h>
52
Linus Torvalds1da177e2005-04-16 15:20:36 -070053#include <asm/unaligned.h>
54
55#include <net/bluetooth/bluetooth.h>
56#include <net/bluetooth/hci_core.h>
57#include <net/bluetooth/l2cap.h>
Anderson Brigliab501d6a2011-06-07 18:46:31 -030058#include <net/bluetooth/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
Rusty Russelleb939922011-12-19 14:08:01 +000060bool disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020061
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070062static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Mat Martineau50a147c2011-11-02 16:18:34 -070063static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Johannes Bergb5ad8b72011-06-01 08:54:45 +020065static LIST_HEAD(chan_list);
66static DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Linus Torvalds1da177e2005-04-16 15:20:36 -070068static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
69 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030070static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
71 void *data);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -030072static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030073static void l2cap_send_disconn_req(struct l2cap_conn *conn,
74 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
Marcel Holtmann01394182006-07-03 10:02:46 +020076/* ---- L2CAP channels ---- */
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -030077
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030078static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020079{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020080 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030081
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020082 list_for_each_entry(c, &conn->chan_l, list) {
83 if (c->dcid == cid)
84 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020085 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020086 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +020087}
88
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030089static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020090{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020091 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030092
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020093 list_for_each_entry(c, &conn->chan_l, list) {
94 if (c->scid == cid)
95 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020096 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020097 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +020098}
99
100/* Find channel with given SCID.
Mat Martineauef191ad2012-05-02 09:42:00 -0700101 * Returns locked channel. */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300102static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200103{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300104 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300105
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200106 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300107 c = __l2cap_get_chan_by_scid(conn, cid);
Mat Martineauef191ad2012-05-02 09:42:00 -0700108 if (c)
109 l2cap_chan_lock(c);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200110 mutex_unlock(&conn->chan_lock);
111
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300112 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200113}
114
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300115static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200116{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200117 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300118
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200119 list_for_each_entry(c, &conn->chan_l, list) {
120 if (c->ident == ident)
121 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200122 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200123 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200124}
125
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300126static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300127{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300128 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300129
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300130 list_for_each_entry(c, &chan_list, global_l) {
131 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Szymon Janc250938c2011-11-16 09:32:22 +0100132 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300133 }
Szymon Janc250938c2011-11-16 09:32:22 +0100134 return NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300135}
136
137int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
138{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300139 int err;
140
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200141 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300142
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300143 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300144 err = -EADDRINUSE;
145 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300146 }
147
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300148 if (psm) {
149 chan->psm = psm;
150 chan->sport = psm;
151 err = 0;
152 } else {
153 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300154
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300155 err = -EINVAL;
156 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300157 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300158 chan->psm = cpu_to_le16(p);
159 chan->sport = cpu_to_le16(p);
160 err = 0;
161 break;
162 }
163 }
164
165done:
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200166 write_unlock(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300167 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300168}
169
170int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
171{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200172 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300173
174 chan->scid = scid;
175
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200176 write_unlock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300177
178 return 0;
179}
180
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300181static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200182{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300183 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200184
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300185 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300186 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200187 return cid;
188 }
189
190 return 0;
191}
192
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200193static void __l2cap_state_change(struct l2cap_chan *chan, int state)
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300194{
Andrei Emeltchenko42d2d872012-02-17 11:40:57 +0200195 BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
Gustavo F. Padovanbadaaa02011-11-23 20:11:46 -0200196 state_to_string(state));
197
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300198 chan->state = state;
199 chan->ops->state_change(chan->data, state);
200}
201
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200202static void l2cap_state_change(struct l2cap_chan *chan, int state)
203{
204 struct sock *sk = chan->sk;
205
206 lock_sock(sk);
207 __l2cap_state_change(chan, state);
208 release_sock(sk);
209}
210
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +0200211static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err)
212{
213 struct sock *sk = chan->sk;
214
215 sk->sk_err = err;
216}
217
218static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
219{
220 struct sock *sk = chan->sk;
221
222 lock_sock(sk);
223 __l2cap_chan_set_err(chan, err);
224 release_sock(sk);
225}
226
Mat Martineau3c588192012-04-11 10:48:42 -0700227/* ---- L2CAP sequence number lists ---- */
228
229/* For ERTM, ordered lists of sequence numbers must be tracked for
230 * SREJ requests that are received and for frames that are to be
231 * retransmitted. These seq_list functions implement a singly-linked
232 * list in an array, where membership in the list can also be checked
233 * in constant time. Items can also be added to the tail of the list
234 * and removed from the head in constant time, without further memory
235 * allocs or frees.
236 */
237
238static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
239{
240 size_t alloc_size, i;
241
242 /* Allocated size is a power of 2 to map sequence numbers
243 * (which may be up to 14 bits) in to a smaller array that is
244 * sized for the negotiated ERTM transmit windows.
245 */
246 alloc_size = roundup_pow_of_two(size);
247
248 seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL);
249 if (!seq_list->list)
250 return -ENOMEM;
251
252 seq_list->mask = alloc_size - 1;
253 seq_list->head = L2CAP_SEQ_LIST_CLEAR;
254 seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
255 for (i = 0; i < alloc_size; i++)
256 seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
257
258 return 0;
259}
260
261static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
262{
263 kfree(seq_list->list);
264}
265
266static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
267 u16 seq)
268{
269 /* Constant-time check for list membership */
270 return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
271}
272
273static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq)
274{
275 u16 mask = seq_list->mask;
276
277 if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) {
278 /* In case someone tries to pop the head of an empty list */
279 return L2CAP_SEQ_LIST_CLEAR;
280 } else if (seq_list->head == seq) {
281 /* Head can be removed in constant time */
282 seq_list->head = seq_list->list[seq & mask];
283 seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
284
285 if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
286 seq_list->head = L2CAP_SEQ_LIST_CLEAR;
287 seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
288 }
289 } else {
290 /* Walk the list to find the sequence number */
291 u16 prev = seq_list->head;
292 while (seq_list->list[prev & mask] != seq) {
293 prev = seq_list->list[prev & mask];
294 if (prev == L2CAP_SEQ_LIST_TAIL)
295 return L2CAP_SEQ_LIST_CLEAR;
296 }
297
298 /* Unlink the number from the list and clear it */
299 seq_list->list[prev & mask] = seq_list->list[seq & mask];
300 seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
301 if (seq_list->tail == seq)
302 seq_list->tail = prev;
303 }
304 return seq;
305}
306
307static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
308{
309 /* Remove the head in constant time */
310 return l2cap_seq_list_remove(seq_list, seq_list->head);
311}
312
313static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
314{
Gustavo Padovanf522ae32012-05-09 18:28:00 -0300315 u16 i;
Mat Martineau3c588192012-04-11 10:48:42 -0700316
Gustavo Padovanf522ae32012-05-09 18:28:00 -0300317 if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
318 return;
319
320 for (i = 0; i <= seq_list->mask; i++)
321 seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
322
323 seq_list->head = L2CAP_SEQ_LIST_CLEAR;
324 seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
Mat Martineau3c588192012-04-11 10:48:42 -0700325}
326
327static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
328{
329 u16 mask = seq_list->mask;
330
331 /* All appends happen in constant time */
332
Gustavo Padovanf522ae32012-05-09 18:28:00 -0300333 if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
334 return;
Mat Martineau3c588192012-04-11 10:48:42 -0700335
Gustavo Padovanf522ae32012-05-09 18:28:00 -0300336 if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
337 seq_list->head = seq;
338 else
339 seq_list->list[seq_list->tail & mask] = seq;
340
341 seq_list->tail = seq;
342 seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
Mat Martineau3c588192012-04-11 10:48:42 -0700343}
344
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300345static void l2cap_chan_timeout(struct work_struct *work)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300346{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300347 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
348 chan_timer.work);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200349 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300350 int reason;
351
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200352 BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300353
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200354 mutex_lock(&conn->chan_lock);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200355 l2cap_chan_lock(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300356
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300357 if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300358 reason = ECONNREFUSED;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300359 else if (chan->state == BT_CONNECT &&
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300360 chan->sec_level != BT_SECURITY_SDP)
361 reason = ECONNREFUSED;
362 else
363 reason = ETIMEDOUT;
364
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300365 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300366
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200367 l2cap_chan_unlock(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300368
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300369 chan->ops->close(chan->data);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200370 mutex_unlock(&conn->chan_lock);
371
Ulisses Furquim371fd832011-12-21 20:02:36 -0200372 l2cap_chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300373}
374
Gustavo Padovaneef1d9b2012-03-25 13:59:16 -0300375struct l2cap_chan *l2cap_chan_create(void)
Marcel Holtmann01394182006-07-03 10:02:46 +0200376{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300377 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200378
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300379 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
380 if (!chan)
381 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200382
Andrei Emeltchenkoc03b3552012-02-21 12:54:56 +0200383 mutex_init(&chan->lock);
384
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200385 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300386 list_add(&chan->global_l, &chan_list);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200387 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300388
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300389 INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300390
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300391 chan->state = BT_OPEN;
392
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300393 atomic_set(&chan->refcnt, 1);
394
Gustavo Padovaneef1d9b2012-03-25 13:59:16 -0300395 BT_DBG("chan %p", chan);
Szymon Jancabc545b2011-11-03 16:05:44 +0100396
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300397 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200398}
399
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300400void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300401{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200402 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300403 list_del(&chan->global_l);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200404 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300405
Ulisses Furquim371fd832011-12-21 20:02:36 -0200406 l2cap_chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300407}
408
Andrei Emeltchenkobd4b1652012-03-28 16:31:25 +0300409void l2cap_chan_set_defaults(struct l2cap_chan *chan)
410{
411 chan->fcs = L2CAP_FCS_CRC16;
412 chan->max_tx = L2CAP_DEFAULT_MAX_TX;
413 chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
414 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
415 chan->sec_level = BT_SECURITY_LOW;
416
417 set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
418}
419
Andrei Emeltchenko14a28492012-03-23 16:31:49 +0200420static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200421{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300422 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Andrei Emeltchenko097db762012-03-09 14:16:17 +0200423 __le16_to_cpu(chan->psm), chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200424
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +0200425 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +0100426
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300427 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200428
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200429 switch (chan->chan_type) {
430 case L2CAP_CHAN_CONN_ORIENTED:
Ville Tervob62f3282011-02-10 22:38:50 -0300431 if (conn->hcon->type == LE_LINK) {
432 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300433 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300434 chan->scid = L2CAP_CID_LE_DATA;
435 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300436 } else {
437 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300438 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300439 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300440 }
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200441 break;
442
443 case L2CAP_CHAN_CONN_LESS:
Marcel Holtmann01394182006-07-03 10:02:46 +0200444 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300445 chan->scid = L2CAP_CID_CONN_LESS;
446 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300447 chan->omtu = L2CAP_DEFAULT_MTU;
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200448 break;
449
450 default:
Marcel Holtmann01394182006-07-03 10:02:46 +0200451 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300452 chan->scid = L2CAP_CID_SIGNALING;
453 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300454 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200455 }
456
Andrei Emeltchenko8f7975b2011-10-13 16:18:54 +0300457 chan->local_id = L2CAP_BESTEFFORT_ID;
458 chan->local_stype = L2CAP_SERV_BESTEFFORT;
459 chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
460 chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
461 chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
462 chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
463
Ulisses Furquim371fd832011-12-21 20:02:36 -0200464 l2cap_chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300465
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200466 list_add(&chan->list, &conn->chan_l);
Andrei Emeltchenko643162a2012-02-22 17:11:55 +0200467}
468
Andrei Emeltchenko14a28492012-03-23 16:31:49 +0200469static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Andrei Emeltchenko643162a2012-02-22 17:11:55 +0200470{
471 mutex_lock(&conn->chan_lock);
472 __l2cap_chan_add(conn, chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200473 mutex_unlock(&conn->chan_lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200474}
475
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300476static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200477{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300478 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300479 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200480 struct sock *parent = bt_sk(sk)->parent;
481
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300482 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200483
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300484 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200485
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900486 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300487 /* Delete from channel list */
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200488 list_del(&chan->list);
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200489
Ulisses Furquim371fd832011-12-21 20:02:36 -0200490 l2cap_chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300491
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300492 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200493 hci_conn_put(conn->hcon);
494 }
495
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200496 lock_sock(sk);
497
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200498 __l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200499 sock_set_flag(sk, SOCK_ZAPPED);
500
501 if (err)
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +0200502 __l2cap_chan_set_err(chan, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200503
504 if (parent) {
505 bt_accept_unlink(sk);
506 parent->sk_data_ready(parent, 0);
507 } else
508 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300509
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200510 release_sock(sk);
511
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300512 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
513 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300514 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300515
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300516 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300517
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300518 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300519 struct srej_list *l, *tmp;
520
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300521 __clear_retrans_timer(chan);
522 __clear_monitor_timer(chan);
523 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300524
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300525 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300526
Mat Martineau3c588192012-04-11 10:48:42 -0700527 l2cap_seq_list_free(&chan->srej_list);
528 l2cap_seq_list_free(&chan->retrans_list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300529 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300530 list_del(&l->list);
531 kfree(l);
532 }
533 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200534}
535
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300536static void l2cap_chan_cleanup_listen(struct sock *parent)
537{
538 struct sock *sk;
539
540 BT_DBG("parent %p", parent);
541
542 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300543 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300544 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200545
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200546 l2cap_chan_lock(chan);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300547 __clear_chan_timer(chan);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300548 l2cap_chan_close(chan, ECONNRESET);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200549 l2cap_chan_unlock(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200550
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300551 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300552 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300553}
554
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300555void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300556{
557 struct l2cap_conn *conn = chan->conn;
558 struct sock *sk = chan->sk;
559
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200560 BT_DBG("chan %p state %s sk %p", chan,
561 state_to_string(chan->state), sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300562
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300563 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300564 case BT_LISTEN:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200565 lock_sock(sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300566 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300567
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200568 __l2cap_state_change(chan, BT_CLOSED);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300569 sock_set_flag(sk, SOCK_ZAPPED);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200570 release_sock(sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300571 break;
572
573 case BT_CONNECTED:
574 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300575 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300576 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300577 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300578 l2cap_send_disconn_req(conn, chan, reason);
579 } else
580 l2cap_chan_del(chan, reason);
581 break;
582
583 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300584 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300585 conn->hcon->type == ACL_LINK) {
586 struct l2cap_conn_rsp rsp;
587 __u16 result;
588
589 if (bt_sk(sk)->defer_setup)
590 result = L2CAP_CR_SEC_BLOCK;
591 else
592 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300593 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300594
595 rsp.scid = cpu_to_le16(chan->dcid);
596 rsp.dcid = cpu_to_le16(chan->scid);
597 rsp.result = cpu_to_le16(result);
598 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
599 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
600 sizeof(rsp), &rsp);
601 }
602
603 l2cap_chan_del(chan, reason);
604 break;
605
606 case BT_CONNECT:
607 case BT_DISCONN:
608 l2cap_chan_del(chan, reason);
609 break;
610
611 default:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200612 lock_sock(sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300613 sock_set_flag(sk, SOCK_ZAPPED);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200614 release_sock(sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300615 break;
616 }
617}
618
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300619static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530620{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300621 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300622 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530623 case BT_SECURITY_HIGH:
624 return HCI_AT_DEDICATED_BONDING_MITM;
625 case BT_SECURITY_MEDIUM:
626 return HCI_AT_DEDICATED_BONDING;
627 default:
628 return HCI_AT_NO_BONDING;
629 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300630 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300631 if (chan->sec_level == BT_SECURITY_LOW)
632 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530633
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300634 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530635 return HCI_AT_NO_BONDING_MITM;
636 else
637 return HCI_AT_NO_BONDING;
638 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300639 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530640 case BT_SECURITY_HIGH:
641 return HCI_AT_GENERAL_BONDING_MITM;
642 case BT_SECURITY_MEDIUM:
643 return HCI_AT_GENERAL_BONDING;
644 default:
645 return HCI_AT_NO_BONDING;
646 }
647 }
648}
649
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200650/* Service level security */
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200651int l2cap_chan_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200652{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300653 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100654 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200655
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300656 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100657
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300658 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200659}
660
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200661static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200662{
663 u8 id;
664
665 /* Get next available identificator.
666 * 1 - 128 are used by kernel.
667 * 129 - 199 are reserved.
668 * 200 - 254 are used by utilities like l2ping, etc.
669 */
670
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200671 spin_lock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200672
673 if (++conn->tx_ident > 128)
674 conn->tx_ident = 1;
675
676 id = conn->tx_ident;
677
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200678 spin_unlock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200679
680 return id;
681}
682
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300683static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200684{
685 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200686 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200687
688 BT_DBG("code 0x%2.2x", code);
689
690 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300691 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200692
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200693 if (lmp_no_flush_capable(conn->hcon->hdev))
694 flags = ACL_START_NO_FLUSH;
695 else
696 flags = ACL_START;
697
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700698 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +0200699 skb->priority = HCI_PRIO_MAX;
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700700
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200701 hci_send_acl(conn->hchan, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200702}
703
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200704static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
705{
706 struct hci_conn *hcon = chan->conn->hcon;
707 u16 flags;
708
709 BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
710 skb->priority);
711
712 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
713 lmp_no_flush_capable(hcon->hdev))
714 flags = ACL_START_NO_FLUSH;
715 else
716 flags = ACL_START;
717
718 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
719 hci_send_acl(chan->conn->hchan, skb, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720}
721
Mat Martineaub5c6aae2012-04-25 16:36:15 -0700722static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
723{
724 control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
725 control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
726
727 if (enh & L2CAP_CTRL_FRAME_TYPE) {
728 /* S-Frame */
729 control->sframe = 1;
730 control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
731 control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
732
733 control->sar = 0;
734 control->txseq = 0;
735 } else {
736 /* I-Frame */
737 control->sframe = 0;
738 control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
739 control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
740
741 control->poll = 0;
742 control->super = 0;
743 }
744}
745
746static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
747{
748 control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
749 control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
750
751 if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
752 /* S-Frame */
753 control->sframe = 1;
754 control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
755 control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
756
757 control->sar = 0;
758 control->txseq = 0;
759 } else {
760 /* I-Frame */
761 control->sframe = 0;
762 control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
763 control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
764
765 control->poll = 0;
766 control->super = 0;
767 }
768}
769
770static inline void __unpack_control(struct l2cap_chan *chan,
771 struct sk_buff *skb)
772{
773 if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
774 __unpack_extended_control(get_unaligned_le32(skb->data),
775 &bt_cb(skb)->control);
776 } else {
777 __unpack_enhanced_control(get_unaligned_le16(skb->data),
778 &bt_cb(skb)->control);
779 }
780}
781
782static u32 __pack_extended_control(struct l2cap_ctrl *control)
783{
784 u32 packed;
785
786 packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
787 packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
788
789 if (control->sframe) {
790 packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
791 packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
792 packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
793 } else {
794 packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
795 packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
796 }
797
798 return packed;
799}
800
801static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
802{
803 u16 packed;
804
805 packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
806 packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
807
808 if (control->sframe) {
809 packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
810 packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
811 packed |= L2CAP_CTRL_FRAME_TYPE;
812 } else {
813 packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
814 packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
815 }
816
817 return packed;
818}
819
820static inline void __pack_control(struct l2cap_chan *chan,
821 struct l2cap_ctrl *control,
822 struct sk_buff *skb)
823{
824 if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
825 put_unaligned_le32(__pack_extended_control(control),
826 skb->data + L2CAP_HDR_SIZE);
827 } else {
828 put_unaligned_le16(__pack_enhanced_control(control),
829 skb->data + L2CAP_HDR_SIZE);
830 }
831}
832
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300833static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300834{
835 struct sk_buff *skb;
836 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300837 struct l2cap_conn *conn = chan->conn;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300838 int count, hlen;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300839
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300840 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300841 return;
842
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300843 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
844 hlen = L2CAP_EXT_HDR_SIZE;
845 else
846 hlen = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300847
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300848 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300849 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300850
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300851 BT_DBG("chan %p, control 0x%8.8x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300852
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300853 count = min_t(unsigned int, conn->mtu, hlen);
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +0300854
855 control |= __set_sframe(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300856
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300857 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +0300858 control |= __set_ctrl_final(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300859
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300860 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +0300861 control |= __set_ctrl_poll(chan);
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300862
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300863 skb = bt_skb_alloc(count, GFP_ATOMIC);
864 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300865 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300866
867 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300868 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300869 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300870
871 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300872
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300873 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300874 u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
875 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300876 }
877
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200878 skb->priority = HCI_PRIO_MAX;
879 l2cap_do_send(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300880}
881
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300882static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300883{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300884 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300885 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300886 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300887 } else
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300888 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300889
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300890 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300891
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300892 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300893}
894
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300895static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300896{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300897 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300898}
899
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +0200900static void l2cap_send_conn_req(struct l2cap_chan *chan)
901{
902 struct l2cap_conn *conn = chan->conn;
903 struct l2cap_conn_req req;
904
905 req.scid = cpu_to_le16(chan->scid);
906 req.psm = chan->psm;
907
908 chan->ident = l2cap_get_ident(conn);
909
910 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
911
912 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
913}
914
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300915static void l2cap_chan_ready(struct l2cap_chan *chan)
916{
917 struct sock *sk = chan->sk;
918 struct sock *parent;
919
920 lock_sock(sk);
921
922 parent = bt_sk(sk)->parent;
923
924 BT_DBG("sk %p, parent %p", sk, parent);
925
926 chan->conf_state = 0;
927 __clear_chan_timer(chan);
928
929 __l2cap_state_change(chan, BT_CONNECTED);
930 sk->sk_state_change(sk);
931
932 if (parent)
933 parent->sk_data_ready(parent, 0);
934
935 release_sock(sk);
936}
937
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300938static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200939{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300940 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200941
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300942 if (conn->hcon->type == LE_LINK) {
943 l2cap_chan_ready(chan);
944 return;
945 }
946
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200947 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100948 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
949 return;
950
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200951 if (l2cap_chan_check_security(chan) &&
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +0200952 __l2cap_no_conn_pending(chan))
953 l2cap_send_conn_req(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200954 } else {
955 struct l2cap_info_req req;
956 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
957
958 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
959 conn->info_ident = l2cap_get_ident(conn);
960
Marcel Holtmannba13ccd2012-03-01 14:25:33 -0800961 schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200962
963 l2cap_send_cmd(conn, conn->info_ident,
964 L2CAP_INFO_REQ, sizeof(req), &req);
965 }
966}
967
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300968static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
969{
970 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300971 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300972 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
973
974 switch (mode) {
975 case L2CAP_MODE_ERTM:
976 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
977 case L2CAP_MODE_STREAMING:
978 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
979 default:
980 return 0x00;
981 }
982}
983
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300984static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300985{
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200986 struct sock *sk = chan->sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300987 struct l2cap_disconn_req req;
988
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300989 if (!conn)
990 return;
991
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300992 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300993 __clear_retrans_timer(chan);
994 __clear_monitor_timer(chan);
995 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300996 }
997
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300998 req.dcid = cpu_to_le16(chan->dcid);
999 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -03001000 l2cap_send_cmd(conn, l2cap_get_ident(conn),
1001 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001002
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001003 lock_sock(sk);
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001004 __l2cap_state_change(chan, BT_DISCONN);
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +02001005 __l2cap_chan_set_err(chan, err);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001006 release_sock(sk);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -03001007}
1008
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001010static void l2cap_conn_start(struct l2cap_conn *conn)
1011{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001012 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001013
1014 BT_DBG("conn %p", conn);
1015
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001016 mutex_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001017
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001018 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001019 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001020
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001021 l2cap_chan_lock(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001022
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001023 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001024 l2cap_chan_unlock(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001025 continue;
1026 }
1027
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001028 if (chan->state == BT_CONNECT) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001029 if (!l2cap_chan_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001030 !__l2cap_no_conn_pending(chan)) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001031 l2cap_chan_unlock(chan);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -03001032 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02001033 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -03001034
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001035 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1036 && test_bit(CONF_STATE2_DEVICE,
1037 &chan->conf_state)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001038 l2cap_chan_close(chan, ECONNRESET);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001039 l2cap_chan_unlock(chan);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -03001040 continue;
1041 }
1042
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +02001043 l2cap_send_conn_req(chan);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -03001044
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001045 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001046 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001047 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001048 rsp.scid = cpu_to_le16(chan->dcid);
1049 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001050
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001051 if (l2cap_chan_check_security(chan)) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001052 lock_sock(sk);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001053 if (bt_sk(sk)->defer_setup) {
1054 struct sock *parent = bt_sk(sk)->parent;
1055 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1056 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00001057 if (parent)
1058 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001059
1060 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001061 __l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001062 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1063 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1064 }
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001065 release_sock(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001066 } else {
1067 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1068 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
1069 }
1070
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001071 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1072 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001073
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001074 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001075 rsp.result != L2CAP_CR_SUCCESS) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001076 l2cap_chan_unlock(chan);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001077 continue;
1078 }
1079
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001080 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001081 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001082 l2cap_build_conf_req(chan, buf), buf);
1083 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001084 }
1085
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001086 l2cap_chan_unlock(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001087 }
1088
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001089 mutex_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001090}
1091
Ido Yarivc2287682012-04-20 15:46:07 -03001092/* Find socket with cid and source/destination bdaddr.
Ville Tervob62f3282011-02-10 22:38:50 -03001093 * Returns closest match, locked.
1094 */
Andrei Emeltchenkod9b88702012-03-12 12:13:08 +02001095static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
Ido Yarivc2287682012-04-20 15:46:07 -03001096 bdaddr_t *src,
1097 bdaddr_t *dst)
Ville Tervob62f3282011-02-10 22:38:50 -03001098{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001099 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -03001100
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001101 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -03001102
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001103 list_for_each_entry(c, &chan_list, global_l) {
1104 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001105
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001106 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -03001107 continue;
1108
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001109 if (c->scid == cid) {
Ido Yarivc2287682012-04-20 15:46:07 -03001110 int src_match, dst_match;
1111 int src_any, dst_any;
1112
Ville Tervob62f3282011-02-10 22:38:50 -03001113 /* Exact match. */
Ido Yarivc2287682012-04-20 15:46:07 -03001114 src_match = !bacmp(&bt_sk(sk)->src, src);
1115 dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1116 if (src_match && dst_match) {
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001117 read_unlock(&chan_list_lock);
1118 return c;
1119 }
Ville Tervob62f3282011-02-10 22:38:50 -03001120
1121 /* Closest match */
Ido Yarivc2287682012-04-20 15:46:07 -03001122 src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1123 dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1124 if ((src_match && dst_any) || (src_any && dst_match) ||
1125 (src_any && dst_any))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001126 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -03001127 }
1128 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -03001129
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001130 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -03001131
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001132 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -03001133}
1134
1135static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1136{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -03001137 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001138 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -03001139
1140 BT_DBG("");
1141
1142 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001143 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ido Yarivc2287682012-04-20 15:46:07 -03001144 conn->src, conn->dst);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001145 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -03001146 return;
1147
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001148 parent = pchan->sk;
1149
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001150 lock_sock(parent);
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -03001151
Ville Tervob62f3282011-02-10 22:38:50 -03001152 /* Check for backlog size */
1153 if (sk_acceptq_is_full(parent)) {
1154 BT_DBG("backlog full %d", parent->sk_ack_backlog);
1155 goto clean;
1156 }
1157
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03001158 chan = pchan->ops->new_connection(pchan->data);
1159 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -03001160 goto clean;
1161
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03001162 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001163
Ville Tervob62f3282011-02-10 22:38:50 -03001164 hci_conn_hold(conn->hcon);
1165
Ville Tervob62f3282011-02-10 22:38:50 -03001166 bacpy(&bt_sk(sk)->src, conn->src);
1167 bacpy(&bt_sk(sk)->dst, conn->dst);
1168
Gustavo F. Padovand1010242011-03-25 00:39:48 -03001169 bt_accept_enqueue(parent, sk);
1170
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001171 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001172
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001173 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -03001174
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001175 __l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -03001176 parent->sk_data_ready(parent, 0);
1177
Ville Tervob62f3282011-02-10 22:38:50 -03001178clean:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001179 release_sock(parent);
Ville Tervob62f3282011-02-10 22:38:50 -03001180}
1181
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001182static void l2cap_conn_ready(struct l2cap_conn *conn)
1183{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001184 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001185
1186 BT_DBG("conn %p", conn);
1187
Ville Tervob62f3282011-02-10 22:38:50 -03001188 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
1189 l2cap_le_conn_ready(conn);
1190
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03001191 if (conn->hcon->out && conn->hcon->type == LE_LINK)
1192 smp_conn_security(conn, conn->hcon->pending_sec_level);
1193
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001194 mutex_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001195
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001196 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001197
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001198 l2cap_chan_lock(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001199
Vinicius Costa Gomes63128452011-06-17 22:46:26 -03001200 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -03001201 if (smp_conn_security(conn, chan->sec_level))
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02001202 l2cap_chan_ready(chan);
Ville Tervoacd7d372011-02-10 22:38:49 -03001203
Vinicius Costa Gomes63128452011-06-17 22:46:26 -03001204 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001205 struct sock *sk = chan->sk;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001206 __clear_chan_timer(chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001207 lock_sock(sk);
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001208 __l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001209 sk->sk_state_change(sk);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001210 release_sock(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -03001211
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001212 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001213 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001214
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001215 l2cap_chan_unlock(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001216 }
1217
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001218 mutex_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001219}
1220
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001221/* Notify sockets that we cannot guaranty reliability anymore */
1222static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
1223{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001224 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001225
1226 BT_DBG("conn %p", conn);
1227
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001228 mutex_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001229
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001230 list_for_each_entry(chan, &conn->chan_l, list) {
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +03001231 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +02001232 __l2cap_chan_set_err(chan, err);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001233 }
1234
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001235 mutex_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001236}
1237
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -02001238static void l2cap_info_timeout(struct work_struct *work)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001239{
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -02001240 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02001241 info_timer.work);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001242
Marcel Holtmann984947d2009-02-06 23:35:19 +01001243 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01001244 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01001245
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001246 l2cap_conn_start(conn);
1247}
1248
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001249static void l2cap_conn_del(struct hci_conn *hcon, int err)
1250{
1251 struct l2cap_conn *conn = hcon->l2cap_data;
1252 struct l2cap_chan *chan, *l;
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001253
1254 if (!conn)
1255 return;
1256
1257 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
1258
1259 kfree_skb(conn->rx_skb);
1260
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001261 mutex_lock(&conn->chan_lock);
1262
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001263 /* Kill channels */
1264 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Mat Martineau61d6ef32012-04-27 16:50:50 -07001265 l2cap_chan_hold(chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001266 l2cap_chan_lock(chan);
1267
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001268 l2cap_chan_del(chan, err);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001269
1270 l2cap_chan_unlock(chan);
1271
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001272 chan->ops->close(chan->data);
Mat Martineau61d6ef32012-04-27 16:50:50 -07001273 l2cap_chan_put(chan);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001274 }
1275
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001276 mutex_unlock(&conn->chan_lock);
1277
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001278 hci_chan_del(conn->hchan);
1279
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001280 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
Ulisses Furquim127074b2012-01-30 18:26:29 -02001281 cancel_delayed_work_sync(&conn->info_timer);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001282
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001283 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
Ulisses Furquim127074b2012-01-30 18:26:29 -02001284 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001285 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001286 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001287
1288 hcon->l2cap_data = NULL;
1289 kfree(conn);
1290}
1291
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001292static void security_timeout(struct work_struct *work)
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001293{
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001294 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1295 security_timer.work);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001296
1297 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1298}
1299
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1301{
Marcel Holtmann01394182006-07-03 10:02:46 +02001302 struct l2cap_conn *conn = hcon->l2cap_data;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001303 struct hci_chan *hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304
Marcel Holtmann01394182006-07-03 10:02:46 +02001305 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 return conn;
1307
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001308 hchan = hci_chan_create(hcon);
1309 if (!hchan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001312 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1313 if (!conn) {
1314 hci_chan_del(hchan);
1315 return NULL;
1316 }
1317
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 hcon->l2cap_data = conn;
1319 conn->hcon = hcon;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001320 conn->hchan = hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001322 BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
Marcel Holtmann01394182006-07-03 10:02:46 +02001323
Ville Tervoacd7d372011-02-10 22:38:49 -03001324 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1325 conn->mtu = hcon->hdev->le_mtu;
1326 else
1327 conn->mtu = hcon->hdev->acl_mtu;
1328
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 conn->src = &hcon->hdev->bdaddr;
1330 conn->dst = &hcon->dst;
1331
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001332 conn->feat_mask = 0;
1333
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 spin_lock_init(&conn->lock);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001335 mutex_init(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001336
1337 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001339 if (hcon->type == LE_LINK)
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001340 INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001341 else
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02001342 INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
Dave Young45054dc2009-10-18 20:28:30 +00001343
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001344 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01001345
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 return conn;
1347}
1348
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350
Ido Yarivc2287682012-04-20 15:46:07 -03001351/* Find socket with psm and source / destination bdaddr.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 * Returns closest match.
1353 */
Ido Yarivc2287682012-04-20 15:46:07 -03001354static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1355 bdaddr_t *src,
1356 bdaddr_t *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001358 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001360 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001361
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001362 list_for_each_entry(c, &chan_list, global_l) {
1363 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001364
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001365 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 continue;
1367
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001368 if (c->psm == psm) {
Ido Yarivc2287682012-04-20 15:46:07 -03001369 int src_match, dst_match;
1370 int src_any, dst_any;
1371
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 /* Exact match. */
Ido Yarivc2287682012-04-20 15:46:07 -03001373 src_match = !bacmp(&bt_sk(sk)->src, src);
1374 dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1375 if (src_match && dst_match) {
Johannes Berga7567b22011-06-01 08:29:54 +02001376 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001377 return c;
1378 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379
1380 /* Closest match */
Ido Yarivc2287682012-04-20 15:46:07 -03001381 src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1382 dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1383 if ((src_match && dst_any) || (src_any && dst_match) ||
1384 (src_any && dst_any))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001385 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 }
1387 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001389 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001390
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001391 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392}
1393
Andre Guedes8e9f9892012-04-24 21:02:55 -03001394int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
1395 bdaddr_t *dst, u8 dst_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001397 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398 bdaddr_t *src = &bt_sk(sk)->src;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 struct l2cap_conn *conn;
1400 struct hci_conn *hcon;
1401 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001402 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001403 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404
Andre Guedes8e9f9892012-04-24 21:02:55 -03001405 BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst),
1406 dst_type, __le16_to_cpu(chan->psm));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001408 hdev = hci_get_route(dst, src);
1409 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 return -EHOSTUNREACH;
1411
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001412 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001414 l2cap_chan_lock(chan);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001415
1416 /* PSM must be odd and lsb of upper byte must be 0 */
1417 if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
1418 chan->chan_type != L2CAP_CHAN_RAW) {
1419 err = -EINVAL;
1420 goto done;
1421 }
1422
1423 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
1424 err = -EINVAL;
1425 goto done;
1426 }
1427
1428 switch (chan->mode) {
1429 case L2CAP_MODE_BASIC:
1430 break;
1431 case L2CAP_MODE_ERTM:
1432 case L2CAP_MODE_STREAMING:
1433 if (!disable_ertm)
1434 break;
1435 /* fall through */
1436 default:
1437 err = -ENOTSUPP;
1438 goto done;
1439 }
1440
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001441 lock_sock(sk);
1442
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001443 switch (sk->sk_state) {
1444 case BT_CONNECT:
1445 case BT_CONNECT2:
1446 case BT_CONFIG:
1447 /* Already connecting */
1448 err = 0;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001449 release_sock(sk);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001450 goto done;
1451
1452 case BT_CONNECTED:
1453 /* Already connected */
1454 err = -EISCONN;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001455 release_sock(sk);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001456 goto done;
1457
1458 case BT_OPEN:
1459 case BT_BOUND:
1460 /* Can connect */
1461 break;
1462
1463 default:
1464 err = -EBADFD;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001465 release_sock(sk);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001466 goto done;
1467 }
1468
1469 /* Set destination address and psm */
Gustavo F. Padovan9219b2a2012-01-02 20:08:04 -02001470 bacpy(&bt_sk(sk)->dst, dst);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001471
1472 release_sock(sk);
1473
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001474 chan->psm = psm;
1475 chan->dcid = cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001477 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001478
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001479 if (chan->dcid == L2CAP_CID_LE_DATA)
Andre Guedes8e9f9892012-04-24 21:02:55 -03001480 hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
Andre Guedesb12f62c2012-04-24 21:02:54 -03001481 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001482 else
Andre Guedes8e9f9892012-04-24 21:02:55 -03001483 hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
Andre Guedesb12f62c2012-04-24 21:02:54 -03001484 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001485
Ville Tervo30e76272011-02-22 16:10:53 -03001486 if (IS_ERR(hcon)) {
1487 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001489 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490
1491 conn = l2cap_conn_add(hcon, 0);
1492 if (!conn) {
1493 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001494 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 goto done;
1496 }
1497
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -03001498 if (hcon->type == LE_LINK) {
1499 err = 0;
1500
1501 if (!list_empty(&conn->chan_l)) {
1502 err = -EBUSY;
1503 hci_conn_put(hcon);
1504 }
1505
1506 if (err)
1507 goto done;
1508 }
1509
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 /* Update source addr of the socket */
1511 bacpy(src, conn->src);
1512
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001513 l2cap_chan_unlock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001514 l2cap_chan_add(conn, chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001515 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001516
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001517 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001518 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519
1520 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001521 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001522 __clear_chan_timer(chan);
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001523 if (l2cap_chan_check_security(chan))
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001524 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001525 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001526 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 }
1528
Ville Tervo30e76272011-02-22 16:10:53 -03001529 err = 0;
1530
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531done:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001532 l2cap_chan_unlock(chan);
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001533 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 hci_dev_put(hdev);
1535 return err;
1536}
1537
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001538int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001539{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001540 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001541 DECLARE_WAITQUEUE(wait, current);
1542 int err = 0;
1543 int timeo = HZ/5;
1544
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001545 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001546 set_current_state(TASK_INTERRUPTIBLE);
1547 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001548 if (!timeo)
1549 timeo = HZ/5;
1550
1551 if (signal_pending(current)) {
1552 err = sock_intr_errno(timeo);
1553 break;
1554 }
1555
1556 release_sock(sk);
1557 timeo = schedule_timeout(timeo);
1558 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001559 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001560
1561 err = sock_error(sk);
1562 if (err)
1563 break;
1564 }
1565 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001566 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001567 return err;
1568}
1569
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001570static void l2cap_monitor_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001571{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001572 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1573 monitor_timer.work);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001574
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001575 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001576
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001577 l2cap_chan_lock(chan);
1578
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001579 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001580 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001581 l2cap_chan_unlock(chan);
Andrei Emeltchenko8d7e1c72012-03-23 09:42:15 +02001582 l2cap_chan_put(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001583 return;
1584 }
1585
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001586 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001587 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001588
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001589 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001590 l2cap_chan_unlock(chan);
Andrei Emeltchenko8d7e1c72012-03-23 09:42:15 +02001591 l2cap_chan_put(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001592}
1593
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001594static void l2cap_retrans_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001595{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001596 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1597 retrans_timer.work);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001598
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001599 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001600
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001601 l2cap_chan_lock(chan);
1602
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001603 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001604 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001605
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001606 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001607
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001608 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001609
1610 l2cap_chan_unlock(chan);
Andrei Emeltchenko8d7e1c72012-03-23 09:42:15 +02001611 l2cap_chan_put(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001612}
1613
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001614static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001615{
1616 struct sk_buff *skb;
1617
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001618 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001619 chan->unacked_frames) {
Mat Martineau3ce35142012-04-25 16:36:14 -07001620 if (bt_cb(skb)->control.txseq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001621 break;
1622
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001623 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001624 kfree_skb(skb);
1625
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001626 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001627 }
1628
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001629 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001630 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001631}
1632
Szymon Janc67c9e842011-07-28 16:24:33 +02001633static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001634{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001635 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001636 u32 control;
1637 u16 fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001638
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001639 while ((skb = skb_dequeue(&chan->tx_q))) {
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001640 control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001641 control |= __set_txseq(chan, chan->next_tx_seq);
Mat Martineau94122bb2012-05-02 09:42:02 -07001642 control |= __set_ctrl_sar(chan, bt_cb(skb)->control.sar);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001643 __put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001644
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001645 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001646 fcs = crc16(0, (u8 *)skb->data,
1647 skb->len - L2CAP_FCS_SIZE);
1648 put_unaligned_le16(fcs,
1649 skb->data + skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001650 }
1651
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001652 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001653
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001654 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001655 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001656}
1657
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001658static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001659{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001660 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001661 u16 fcs;
1662 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001663
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001664 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001665 if (!skb)
1666 return;
1667
Mat Martineau3ce35142012-04-25 16:36:14 -07001668 while (bt_cb(skb)->control.txseq != tx_seq) {
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001669 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001670 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001671
Szymon Jancd1726b62011-11-16 09:32:20 +01001672 skb = skb_queue_next(&chan->tx_q, skb);
1673 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001674
Mat Martineau3ce35142012-04-25 16:36:14 -07001675 if (bt_cb(skb)->control.retries == chan->remote_max_tx &&
1676 chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001677 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001678 return;
1679 }
1680
1681 tx_skb = skb_clone(skb, GFP_ATOMIC);
Mat Martineau3ce35142012-04-25 16:36:14 -07001682 bt_cb(skb)->control.retries++;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001683
1684 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001685 control &= __get_sar_mask(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001686
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001687 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001688 control |= __set_ctrl_final(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001689
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001690 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001691 control |= __set_txseq(chan, tx_seq);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001692
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001693 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001694
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001695 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001696 fcs = crc16(0, (u8 *)tx_skb->data,
1697 tx_skb->len - L2CAP_FCS_SIZE);
1698 put_unaligned_le16(fcs,
1699 tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001700 }
1701
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001702 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001703}
1704
Szymon Janc67c9e842011-07-28 16:24:33 +02001705static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001706{
1707 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001708 u16 fcs;
1709 u32 control;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001710 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001711
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001712 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001713 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001714
Mat Martineau94122bb2012-05-02 09:42:02 -07001715 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
1716 return 0;
1717
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001718 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001719
Mat Martineau3ce35142012-04-25 16:36:14 -07001720 if (bt_cb(skb)->control.retries == chan->remote_max_tx &&
1721 chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001722 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001723 break;
1724 }
1725
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001726 tx_skb = skb_clone(skb, GFP_ATOMIC);
1727
Mat Martineau3ce35142012-04-25 16:36:14 -07001728 bt_cb(skb)->control.retries++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001729
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001730 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001731 control &= __get_sar_mask(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001732
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001733 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001734 control |= __set_ctrl_final(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001735
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001736 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001737 control |= __set_txseq(chan, chan->next_tx_seq);
Mat Martineau94122bb2012-05-02 09:42:02 -07001738 control |= __set_ctrl_sar(chan, bt_cb(skb)->control.sar);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001739
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001740 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001741
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001742 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001743 fcs = crc16(0, (u8 *)skb->data,
1744 tx_skb->len - L2CAP_FCS_SIZE);
1745 put_unaligned_le16(fcs, skb->data +
1746 tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001747 }
1748
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001749 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001750
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001751 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001752
Mat Martineau3ce35142012-04-25 16:36:14 -07001753 bt_cb(skb)->control.txseq = chan->next_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001754
1755 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001756
Mat Martineau3ce35142012-04-25 16:36:14 -07001757 if (bt_cb(skb)->control.retries == 1) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001758 chan->unacked_frames++;
Szymon Janc930fa4a2012-02-07 15:43:02 +01001759
1760 if (!nsent++)
1761 __clear_ack_timer(chan);
Szymon Janc8ed7a0a2012-02-07 15:43:01 +01001762 }
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301763
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001764 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001765
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001766 if (skb_queue_is_last(&chan->tx_q, skb))
1767 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001768 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001769 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001770 }
1771
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001772 return nsent;
1773}
1774
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001775static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001776{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001777 int ret;
1778
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001779 if (!skb_queue_empty(&chan->tx_q))
1780 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001781
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001782 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001783 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001784 return ret;
1785}
1786
Szymon Jancb17e73b2012-01-11 10:59:47 +01001787static void __l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001788{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001789 u32 control = 0;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001790
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001791 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001792
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001793 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001794 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001795 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001796 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001797 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001798 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001799
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001800 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001801 return;
1802
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001803 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001804 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001805}
1806
Szymon Jancb17e73b2012-01-11 10:59:47 +01001807static void l2cap_send_ack(struct l2cap_chan *chan)
1808{
1809 __clear_ack_timer(chan);
1810 __l2cap_send_ack(chan);
1811}
1812
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001813static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001814{
1815 struct srej_list *tail;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001816 u32 control;
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001817
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001818 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001819 control |= __set_ctrl_final(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001820
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001821 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001822 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001823
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001824 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001825}
1826
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001827static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
1828 struct msghdr *msg, int len,
1829 int count, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830{
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001831 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001832 struct sk_buff **frag;
Gustavo Padovan90338942012-04-06 20:15:47 -03001833 int sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001835 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001836 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837
1838 sent += count;
1839 len -= count;
1840
1841 /* Continuation fragments (no L2CAP header) */
1842 frag = &skb_shinfo(skb)->frag_list;
1843 while (len) {
Gustavo Padovanfbe00702012-05-15 13:22:55 -03001844 struct sk_buff *tmp;
1845
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 count = min_t(unsigned int, conn->mtu, len);
1847
Gustavo Padovanfbe00702012-05-15 13:22:55 -03001848 tmp = chan->ops->alloc_skb(chan, count,
1849 msg->msg_flags & MSG_DONTWAIT);
1850 if (IS_ERR(tmp))
1851 return PTR_ERR(tmp);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001852
Gustavo Padovanfbe00702012-05-15 13:22:55 -03001853 *frag = tmp;
1854
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001855 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1856 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001858 (*frag)->priority = skb->priority;
1859
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860 sent += count;
1861 len -= count;
1862
Gustavo Padovan2d0ed3d2012-05-11 13:16:12 -03001863 skb->len += (*frag)->len;
1864 skb->data_len += (*frag)->len;
1865
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866 frag = &(*frag)->next;
1867 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868
1869 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001870}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001872static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
1873 struct msghdr *msg, size_t len,
1874 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001875{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001876 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001877 struct sk_buff *skb;
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001878 int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001879 struct l2cap_hdr *lh;
1880
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001881 BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001882
1883 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001884
1885 skb = chan->ops->alloc_skb(chan, count + hlen,
Gustavo Padovan90338942012-04-06 20:15:47 -03001886 msg->msg_flags & MSG_DONTWAIT);
1887 if (IS_ERR(skb))
1888 return skb;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001889
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001890 skb->priority = priority;
1891
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001892 /* Create L2CAP header */
1893 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001894 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenkodaf6a78c2012-05-03 10:55:52 +03001895 lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
1896 put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001897
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001898 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001899 if (unlikely(err < 0)) {
1900 kfree_skb(skb);
1901 return ERR_PTR(err);
1902 }
1903 return skb;
1904}
1905
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001906static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
1907 struct msghdr *msg, size_t len,
1908 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001909{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001910 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001911 struct sk_buff *skb;
Gustavo Padovanf2ba7fa2012-05-03 04:54:21 -03001912 int err, count;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001913 struct l2cap_hdr *lh;
1914
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001915 BT_DBG("chan %p len %d", chan, (int)len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001916
Gustavo Padovanf2ba7fa2012-05-03 04:54:21 -03001917 count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001918
Gustavo Padovanf2ba7fa2012-05-03 04:54:21 -03001919 skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE,
Gustavo Padovan90338942012-04-06 20:15:47 -03001920 msg->msg_flags & MSG_DONTWAIT);
1921 if (IS_ERR(skb))
1922 return skb;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001923
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001924 skb->priority = priority;
1925
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001926 /* Create L2CAP header */
1927 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001928 lh->cid = cpu_to_le16(chan->dcid);
Gustavo Padovan6ff9b5e2012-05-02 11:56:17 -03001929 lh->len = cpu_to_le16(len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001930
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001931 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001932 if (unlikely(err < 0)) {
1933 kfree_skb(skb);
1934 return ERR_PTR(err);
1935 }
1936 return skb;
1937}
1938
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001939static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1940 struct msghdr *msg, size_t len,
Mat Martineau94122bb2012-05-02 09:42:02 -07001941 u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001942{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001943 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001944 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001945 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001946 struct l2cap_hdr *lh;
1947
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001948 BT_DBG("chan %p len %d", chan, (int)len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001949
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001950 if (!conn)
1951 return ERR_PTR(-ENOTCONN);
1952
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001953 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1954 hlen = L2CAP_EXT_HDR_SIZE;
1955 else
1956 hlen = L2CAP_ENH_HDR_SIZE;
1957
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001958 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001959 hlen += L2CAP_SDULEN_SIZE;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001960
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001961 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001962 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001963
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001964 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001965
1966 skb = chan->ops->alloc_skb(chan, count + hlen,
Gustavo Padovan90338942012-04-06 20:15:47 -03001967 msg->msg_flags & MSG_DONTWAIT);
1968 if (IS_ERR(skb))
1969 return skb;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001970
1971 /* Create L2CAP header */
1972 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001973 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001974 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001975
Mat Martineau94122bb2012-05-02 09:42:02 -07001976 __put_control(chan, 0, skb_put(skb, __ctrl_size(chan)));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001977
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001978 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001979 put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001980
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001981 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001982 if (unlikely(err < 0)) {
1983 kfree_skb(skb);
1984 return ERR_PTR(err);
1985 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001986
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001987 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001988 put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001989
Mat Martineau3ce35142012-04-25 16:36:14 -07001990 bt_cb(skb)->control.retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001991 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992}
1993
Mat Martineau94122bb2012-05-02 09:42:02 -07001994static int l2cap_segment_sdu(struct l2cap_chan *chan,
1995 struct sk_buff_head *seg_queue,
1996 struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001997{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001998 struct sk_buff *skb;
Mat Martineau94122bb2012-05-02 09:42:02 -07001999 u16 sdu_len;
2000 size_t pdu_len;
2001 int err = 0;
2002 u8 sar;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002003
Mat Martineau94122bb2012-05-02 09:42:02 -07002004 BT_DBG("chan %p, msg %p, len %d", chan, msg, (int)len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002005
Mat Martineau94122bb2012-05-02 09:42:02 -07002006 /* It is critical that ERTM PDUs fit in a single HCI fragment,
2007 * so fragmented skbs are not used. The HCI layer's handling
2008 * of fragmented skbs is not compatible with ERTM's queueing.
2009 */
2010
2011 /* PDU size is derived from the HCI MTU */
2012 pdu_len = chan->conn->mtu;
2013
2014 pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
2015
2016 /* Adjust for largest possible L2CAP overhead. */
2017 pdu_len -= L2CAP_EXT_HDR_SIZE + L2CAP_FCS_SIZE;
2018
2019 /* Remote device may have requested smaller PDUs */
2020 pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
2021
2022 if (len <= pdu_len) {
2023 sar = L2CAP_SAR_UNSEGMENTED;
2024 sdu_len = 0;
2025 pdu_len = len;
2026 } else {
2027 sar = L2CAP_SAR_START;
2028 sdu_len = len;
2029 pdu_len -= L2CAP_SDULEN_SIZE;
2030 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002031
2032 while (len > 0) {
Mat Martineau94122bb2012-05-02 09:42:02 -07002033 skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002034
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002035 if (IS_ERR(skb)) {
Mat Martineau94122bb2012-05-02 09:42:02 -07002036 __skb_queue_purge(seg_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002037 return PTR_ERR(skb);
2038 }
2039
Mat Martineau94122bb2012-05-02 09:42:02 -07002040 bt_cb(skb)->control.sar = sar;
2041 __skb_queue_tail(seg_queue, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002042
Mat Martineau94122bb2012-05-02 09:42:02 -07002043 len -= pdu_len;
2044 if (sdu_len) {
2045 sdu_len = 0;
2046 pdu_len += L2CAP_SDULEN_SIZE;
2047 }
2048
2049 if (len <= pdu_len) {
2050 sar = L2CAP_SAR_END;
2051 pdu_len = len;
2052 } else {
2053 sar = L2CAP_SAR_CONTINUE;
2054 }
2055 }
2056
2057 return err;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002058}
2059
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02002060int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
2061 u32 priority)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002062{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002063 struct sk_buff *skb;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002064 int err;
Mat Martineau94122bb2012-05-02 09:42:02 -07002065 struct sk_buff_head seg_queue;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002066
2067 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03002068 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02002069 skb = l2cap_create_connless_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002070 if (IS_ERR(skb))
2071 return PTR_ERR(skb);
2072
2073 l2cap_do_send(chan, skb);
2074 return len;
2075 }
2076
2077 switch (chan->mode) {
2078 case L2CAP_MODE_BASIC:
2079 /* Check outgoing MTU */
2080 if (len > chan->omtu)
2081 return -EMSGSIZE;
2082
2083 /* Create a basic PDU */
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02002084 skb = l2cap_create_basic_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002085 if (IS_ERR(skb))
2086 return PTR_ERR(skb);
2087
2088 l2cap_do_send(chan, skb);
2089 err = len;
2090 break;
2091
2092 case L2CAP_MODE_ERTM:
2093 case L2CAP_MODE_STREAMING:
Mat Martineau94122bb2012-05-02 09:42:02 -07002094 /* Check outgoing MTU */
2095 if (len > chan->omtu) {
2096 err = -EMSGSIZE;
2097 break;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002098 }
2099
Mat Martineau94122bb2012-05-02 09:42:02 -07002100 __skb_queue_head_init(&seg_queue);
2101
2102 /* Do segmentation before calling in to the state machine,
2103 * since it's possible to block while waiting for memory
2104 * allocation.
2105 */
2106 err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
2107
2108 /* The channel could have been closed while segmenting,
2109 * check that it is still connected.
2110 */
2111 if (chan->state != BT_CONNECTED) {
2112 __skb_queue_purge(&seg_queue);
2113 err = -ENOTCONN;
2114 }
2115
2116 if (err)
2117 break;
2118
Mat Martineau577cfae2012-05-14 11:24:33 -07002119 if (chan->mode == L2CAP_MODE_ERTM && chan->tx_send_head == NULL)
2120 chan->tx_send_head = seg_queue.next;
Mat Martineau94122bb2012-05-02 09:42:02 -07002121 skb_queue_splice_tail_init(&seg_queue, &chan->tx_q);
Mat Martineau577cfae2012-05-14 11:24:33 -07002122
Mat Martineau94122bb2012-05-02 09:42:02 -07002123 if (chan->mode == L2CAP_MODE_ERTM)
2124 err = l2cap_ertm_send(chan);
2125 else
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002126 l2cap_streaming_send(chan);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002127
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002128 if (err >= 0)
2129 err = len;
2130
Mat Martineau94122bb2012-05-02 09:42:02 -07002131 /* If the skbs were not queued for sending, they'll still be in
2132 * seg_queue and need to be purged.
2133 */
2134 __skb_queue_purge(&seg_queue);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002135 break;
2136
2137 default:
2138 BT_DBG("bad state %1.1x", chan->mode);
2139 err = -EBADFD;
2140 }
2141
2142 return err;
2143}
2144
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145/* Copy frame to all raw sockets on that connection */
2146static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
2147{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002149 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150
2151 BT_DBG("conn %p", conn);
2152
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002153 mutex_lock(&conn->chan_lock);
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02002154
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002155 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002156 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03002157 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 continue;
2159
2160 /* Don't send frame to the socket it came from */
2161 if (skb->sk == sk)
2162 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002163 nskb = skb_clone(skb, GFP_ATOMIC);
2164 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 continue;
2166
Gustavo F. Padovan23070492011-05-16 17:57:22 -03002167 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 kfree_skb(nskb);
2169 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02002170
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002171 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172}
2173
2174/* ---- L2CAP signalling commands ---- */
2175static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
2176 u8 code, u8 ident, u16 dlen, void *data)
2177{
2178 struct sk_buff *skb, **frag;
2179 struct l2cap_cmd_hdr *cmd;
2180 struct l2cap_hdr *lh;
2181 int len, count;
2182
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002183 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
2184 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185
2186 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
2187 count = min_t(unsigned int, conn->mtu, len);
2188
2189 skb = bt_skb_alloc(count, GFP_ATOMIC);
2190 if (!skb)
2191 return NULL;
2192
2193 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002194 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002195
2196 if (conn->hcon->type == LE_LINK)
2197 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
2198 else
2199 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200
2201 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
2202 cmd->code = code;
2203 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002204 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205
2206 if (dlen) {
2207 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
2208 memcpy(skb_put(skb, count), data, count);
2209 data += count;
2210 }
2211
2212 len -= skb->len;
2213
2214 /* Continuation fragments (no L2CAP header) */
2215 frag = &skb_shinfo(skb)->frag_list;
2216 while (len) {
2217 count = min_t(unsigned int, conn->mtu, len);
2218
2219 *frag = bt_skb_alloc(count, GFP_ATOMIC);
2220 if (!*frag)
2221 goto fail;
2222
2223 memcpy(skb_put(*frag, count), data, count);
2224
2225 len -= count;
2226 data += count;
2227
2228 frag = &(*frag)->next;
2229 }
2230
2231 return skb;
2232
2233fail:
2234 kfree_skb(skb);
2235 return NULL;
2236}
2237
2238static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
2239{
2240 struct l2cap_conf_opt *opt = *ptr;
2241 int len;
2242
2243 len = L2CAP_CONF_OPT_SIZE + opt->len;
2244 *ptr += len;
2245
2246 *type = opt->type;
2247 *olen = opt->len;
2248
2249 switch (opt->len) {
2250 case 1:
2251 *val = *((u8 *) opt->val);
2252 break;
2253
2254 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04002255 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 break;
2257
2258 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04002259 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260 break;
2261
2262 default:
2263 *val = (unsigned long) opt->val;
2264 break;
2265 }
2266
2267 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
2268 return len;
2269}
2270
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
2272{
2273 struct l2cap_conf_opt *opt = *ptr;
2274
2275 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
2276
2277 opt->type = type;
2278 opt->len = len;
2279
2280 switch (len) {
2281 case 1:
2282 *((u8 *) opt->val) = val;
2283 break;
2284
2285 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02002286 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 break;
2288
2289 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02002290 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 break;
2292
2293 default:
2294 memcpy(opt->val, (void *) val, len);
2295 break;
2296 }
2297
2298 *ptr += L2CAP_CONF_OPT_SIZE + len;
2299}
2300
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002301static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
2302{
2303 struct l2cap_conf_efs efs;
2304
Szymon Janc1ec918c2011-11-16 09:32:21 +01002305 switch (chan->mode) {
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002306 case L2CAP_MODE_ERTM:
2307 efs.id = chan->local_id;
2308 efs.stype = chan->local_stype;
2309 efs.msdu = cpu_to_le16(chan->local_msdu);
2310 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
2311 efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
2312 efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
2313 break;
2314
2315 case L2CAP_MODE_STREAMING:
2316 efs.id = 1;
2317 efs.stype = L2CAP_SERV_BESTEFFORT;
2318 efs.msdu = cpu_to_le16(chan->local_msdu);
2319 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
2320 efs.acc_lat = 0;
2321 efs.flush_to = 0;
2322 break;
2323
2324 default:
2325 return;
2326 }
2327
2328 l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
2329 (unsigned long) &efs);
2330}
2331
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002332static void l2cap_ack_timeout(struct work_struct *work)
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002333{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002334 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2335 ack_timer.work);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002336
Gustavo F. Padovan2fb9b3d2011-12-22 16:56:05 -02002337 BT_DBG("chan %p", chan);
2338
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02002339 l2cap_chan_lock(chan);
2340
Szymon Jancb17e73b2012-01-11 10:59:47 +01002341 __l2cap_send_ack(chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02002342
2343 l2cap_chan_unlock(chan);
Szymon Janc09bfb2e2012-01-11 10:59:49 +01002344
2345 l2cap_chan_put(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002346}
2347
Mat Martineau3c588192012-04-11 10:48:42 -07002348static inline int l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002349{
Mat Martineau3c588192012-04-11 10:48:42 -07002350 int err;
2351
Mat Martineau105bdf92012-04-27 16:50:48 -07002352 chan->next_tx_seq = 0;
2353 chan->expected_tx_seq = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002354 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002355 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002356 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002357 chan->num_acked = 0;
2358 chan->frames_sent = 0;
Mat Martineau105bdf92012-04-27 16:50:48 -07002359 chan->last_acked_seq = 0;
2360 chan->sdu = NULL;
2361 chan->sdu_last_frag = NULL;
2362 chan->sdu_len = 0;
2363
Mat Martineaud34c34f2012-05-14 14:49:27 -07002364 skb_queue_head_init(&chan->tx_q);
2365
Mat Martineau105bdf92012-04-27 16:50:48 -07002366 if (chan->mode != L2CAP_MODE_ERTM)
2367 return 0;
2368
2369 chan->rx_state = L2CAP_RX_STATE_RECV;
2370 chan->tx_state = L2CAP_TX_STATE_XMIT;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002371
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002372 INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2373 INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2374 INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002375
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002376 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002377
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03002378 INIT_LIST_HEAD(&chan->srej_l);
Mat Martineau3c588192012-04-11 10:48:42 -07002379 err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
2380 if (err < 0)
2381 return err;
2382
2383 return l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002384}
2385
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002386static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2387{
2388 switch (mode) {
2389 case L2CAP_MODE_STREAMING:
2390 case L2CAP_MODE_ERTM:
2391 if (l2cap_mode_supported(mode, remote_feat_mask))
2392 return mode;
2393 /* fall through */
2394 default:
2395 return L2CAP_MODE_BASIC;
2396 }
2397}
2398
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002399static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
2400{
2401 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
2402}
2403
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002404static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2405{
2406 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2407}
2408
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002409static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
2410{
2411 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002412 __l2cap_ews_supported(chan)) {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002413 /* use extended control field */
2414 set_bit(FLAG_EXT_CTRL, &chan->flags);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002415 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2416 } else {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002417 chan->tx_win = min_t(u16, chan->tx_win,
2418 L2CAP_DEFAULT_TX_WINDOW);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002419 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2420 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002421}
2422
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002423static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002426 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427 void *ptr = req->data;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002428 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002430 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002432 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002433 goto done;
2434
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002435 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002436 case L2CAP_MODE_STREAMING:
2437 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002438 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002439 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002440
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002441 if (__l2cap_efs_supported(chan))
2442 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2443
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002444 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002445 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002446 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002447 break;
2448 }
2449
2450done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002451 if (chan->imtu != L2CAP_DEFAULT_MTU)
2452 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002453
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002454 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002455 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002456 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2457 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002458 break;
2459
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002460 rfc.mode = L2CAP_MODE_BASIC;
2461 rfc.txwin_size = 0;
2462 rfc.max_transmit = 0;
2463 rfc.retrans_timeout = 0;
2464 rfc.monitor_timeout = 0;
2465 rfc.max_pdu_size = 0;
2466
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002467 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2468 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002469 break;
2470
2471 case L2CAP_MODE_ERTM:
2472 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002473 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002474 rfc.retrans_timeout = 0;
2475 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002476
2477 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2478 L2CAP_EXT_HDR_SIZE -
2479 L2CAP_SDULEN_SIZE -
2480 L2CAP_FCS_SIZE);
2481 rfc.max_pdu_size = cpu_to_le16(size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002482
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002483 l2cap_txwin_setup(chan);
2484
2485 rfc.txwin_size = min_t(u16, chan->tx_win,
2486 L2CAP_DEFAULT_TX_WINDOW);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002487
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002488 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2489 (unsigned long) &rfc);
2490
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002491 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2492 l2cap_add_opt_efs(&ptr, chan);
2493
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002494 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002495 break;
2496
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002497 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002498 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002499 chan->fcs = L2CAP_FCS_NONE;
2500 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002501 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002502
2503 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2504 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2505 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002506 break;
2507
2508 case L2CAP_MODE_STREAMING:
2509 rfc.mode = L2CAP_MODE_STREAMING;
2510 rfc.txwin_size = 0;
2511 rfc.max_transmit = 0;
2512 rfc.retrans_timeout = 0;
2513 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002514
2515 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2516 L2CAP_EXT_HDR_SIZE -
2517 L2CAP_SDULEN_SIZE -
2518 L2CAP_FCS_SIZE);
2519 rfc.max_pdu_size = cpu_to_le16(size);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002520
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002521 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2522 (unsigned long) &rfc);
2523
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002524 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2525 l2cap_add_opt_efs(&ptr, chan);
2526
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002527 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002528 break;
2529
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002530 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002531 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002532 chan->fcs = L2CAP_FCS_NONE;
2533 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002534 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002535 break;
2536 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002538 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002539 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540
2541 return ptr - data;
2542}
2543
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002544static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002546 struct l2cap_conf_rsp *rsp = data;
2547 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002548 void *req = chan->conf_req;
2549 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002550 int type, hint, olen;
2551 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002552 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002553 struct l2cap_conf_efs efs;
2554 u8 remote_efs = 0;
Marcel Holtmann861d6882007-10-20 13:37:06 +02002555 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002556 u16 result = L2CAP_CONF_SUCCESS;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002557 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002559 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002560
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002561 while (len >= L2CAP_CONF_OPT_SIZE) {
2562 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002564 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002565 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002566
2567 switch (type) {
2568 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002569 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002570 break;
2571
2572 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002573 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002574 break;
2575
2576 case L2CAP_CONF_QOS:
2577 break;
2578
Marcel Holtmann6464f352007-10-20 13:39:51 +02002579 case L2CAP_CONF_RFC:
2580 if (olen == sizeof(rfc))
2581 memcpy(&rfc, (void *) val, olen);
2582 break;
2583
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002584 case L2CAP_CONF_FCS:
2585 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002586 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002587 break;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002588
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002589 case L2CAP_CONF_EFS:
2590 remote_efs = 1;
2591 if (olen == sizeof(efs))
2592 memcpy(&efs, (void *) val, olen);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002593 break;
2594
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002595 case L2CAP_CONF_EWS:
2596 if (!enable_hs)
2597 return -ECONNREFUSED;
2598
2599 set_bit(FLAG_EXT_CTRL, &chan->flags);
2600 set_bit(CONF_EWS_RECV, &chan->conf_state);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002601 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002602 chan->remote_tx_win = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002603 break;
2604
2605 default:
2606 if (hint)
2607 break;
2608
2609 result = L2CAP_CONF_UNKNOWN;
2610 *((u8 *) ptr++) = type;
2611 break;
2612 }
2613 }
2614
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002615 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002616 goto done;
2617
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002618 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002619 case L2CAP_MODE_STREAMING:
2620 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002621 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002622 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002623 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002624 break;
2625 }
2626
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002627 if (remote_efs) {
2628 if (__l2cap_efs_supported(chan))
2629 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2630 else
2631 return -ECONNREFUSED;
2632 }
2633
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002634 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002635 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002636
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002637 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002638 }
2639
2640done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002641 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002642 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002643 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002644
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002645 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002646 return -ECONNREFUSED;
2647
2648 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2649 sizeof(rfc), (unsigned long) &rfc);
2650 }
2651
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002652 if (result == L2CAP_CONF_SUCCESS) {
2653 /* Configure output options and let the other side know
2654 * which ones we don't like. */
2655
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002656 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2657 result = L2CAP_CONF_UNACCEPT;
2658 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002659 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002660 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002661 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002662 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002663
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002664 if (remote_efs) {
2665 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2666 efs.stype != L2CAP_SERV_NOTRAFIC &&
2667 efs.stype != chan->local_stype) {
2668
2669 result = L2CAP_CONF_UNACCEPT;
2670
2671 if (chan->num_conf_req >= 1)
2672 return -ECONNREFUSED;
2673
2674 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002675 sizeof(efs),
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002676 (unsigned long) &efs);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002677 } else {
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002678 /* Send PENDING Conf Rsp */
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002679 result = L2CAP_CONF_PENDING;
2680 set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002681 }
2682 }
2683
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002684 switch (rfc.mode) {
2685 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002686 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002687 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002688 break;
2689
2690 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002691 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2692 chan->remote_tx_win = rfc.txwin_size;
2693 else
2694 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2695
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002696 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002697
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002698 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2699 chan->conn->mtu -
2700 L2CAP_EXT_HDR_SIZE -
2701 L2CAP_SDULEN_SIZE -
2702 L2CAP_FCS_SIZE);
2703 rfc.max_pdu_size = cpu_to_le16(size);
2704 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002705
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002706 rfc.retrans_timeout =
Andrei Emeltchenko4fd21a82012-03-12 12:13:10 +02002707 __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002708 rfc.monitor_timeout =
Andrei Emeltchenko4fd21a82012-03-12 12:13:10 +02002709 __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002710
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002711 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002712
2713 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2714 sizeof(rfc), (unsigned long) &rfc);
2715
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002716 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2717 chan->remote_id = efs.id;
2718 chan->remote_stype = efs.stype;
2719 chan->remote_msdu = le16_to_cpu(efs.msdu);
2720 chan->remote_flush_to =
2721 le32_to_cpu(efs.flush_to);
2722 chan->remote_acc_lat =
2723 le32_to_cpu(efs.acc_lat);
2724 chan->remote_sdu_itime =
2725 le32_to_cpu(efs.sdu_itime);
2726 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2727 sizeof(efs), (unsigned long) &efs);
2728 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002729 break;
2730
2731 case L2CAP_MODE_STREAMING:
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002732 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2733 chan->conn->mtu -
2734 L2CAP_EXT_HDR_SIZE -
2735 L2CAP_SDULEN_SIZE -
2736 L2CAP_FCS_SIZE);
2737 rfc.max_pdu_size = cpu_to_le16(size);
2738 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002739
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002740 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002741
2742 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2743 sizeof(rfc), (unsigned long) &rfc);
2744
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002745 break;
2746
2747 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002748 result = L2CAP_CONF_UNACCEPT;
2749
2750 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002751 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002752 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002753
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002754 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002755 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002756 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002757 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002758 rsp->result = cpu_to_le16(result);
2759 rsp->flags = cpu_to_le16(0x0000);
2760
2761 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762}
2763
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002764static 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 -03002765{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002766 struct l2cap_conf_req *req = data;
2767 void *ptr = req->data;
2768 int type, olen;
2769 unsigned long val;
Mat Martineau36e999a2011-12-08 17:23:21 -08002770 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002771 struct l2cap_conf_efs efs;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002772
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002773 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002774
2775 while (len >= L2CAP_CONF_OPT_SIZE) {
2776 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2777
2778 switch (type) {
2779 case L2CAP_CONF_MTU:
2780 if (val < L2CAP_DEFAULT_MIN_MTU) {
2781 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002782 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002783 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002784 chan->imtu = val;
2785 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002786 break;
2787
2788 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002789 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002790 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002791 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002792 break;
2793
2794 case L2CAP_CONF_RFC:
2795 if (olen == sizeof(rfc))
2796 memcpy(&rfc, (void *)val, olen);
2797
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002798 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002799 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002800 return -ECONNREFUSED;
2801
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002802 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002803
2804 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2805 sizeof(rfc), (unsigned long) &rfc);
2806 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002807
2808 case L2CAP_CONF_EWS:
2809 chan->tx_win = min_t(u16, val,
2810 L2CAP_DEFAULT_EXT_WINDOW);
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002811 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2812 chan->tx_win);
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002813 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002814
2815 case L2CAP_CONF_EFS:
2816 if (olen == sizeof(efs))
2817 memcpy(&efs, (void *)val, olen);
2818
2819 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2820 efs.stype != L2CAP_SERV_NOTRAFIC &&
2821 efs.stype != chan->local_stype)
2822 return -ECONNREFUSED;
2823
2824 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2825 sizeof(efs), (unsigned long) &efs);
2826 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002827 }
2828 }
2829
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002830 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002831 return -ECONNREFUSED;
2832
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002833 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002834
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002835 if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002836 switch (rfc.mode) {
2837 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002838 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2839 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2840 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002841
2842 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2843 chan->local_msdu = le16_to_cpu(efs.msdu);
2844 chan->local_sdu_itime =
2845 le32_to_cpu(efs.sdu_itime);
2846 chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
2847 chan->local_flush_to =
2848 le32_to_cpu(efs.flush_to);
2849 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002850 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002851
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002852 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002853 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002854 }
2855 }
2856
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002857 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002858 req->flags = cpu_to_le16(0x0000);
2859
2860 return ptr - data;
2861}
2862
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002863static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864{
2865 struct l2cap_conf_rsp *rsp = data;
2866 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002868 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002870 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002871 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002872 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002873
2874 return ptr - data;
2875}
2876
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002877void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002878{
2879 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002880 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002881 u8 buf[128];
2882
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002883 rsp.scid = cpu_to_le16(chan->dcid);
2884 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002885 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2886 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2887 l2cap_send_cmd(conn, chan->ident,
2888 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2889
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002890 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002891 return;
2892
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002893 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2894 l2cap_build_conf_req(chan, buf), buf);
2895 chan->num_conf_req++;
2896}
2897
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002898static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002899{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002900 int type, olen;
2901 unsigned long val;
2902 struct l2cap_conf_rfc rfc;
2903
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002904 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002905
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002906 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002907 return;
2908
2909 while (len >= L2CAP_CONF_OPT_SIZE) {
2910 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2911
2912 switch (type) {
2913 case L2CAP_CONF_RFC:
2914 if (olen == sizeof(rfc))
2915 memcpy(&rfc, (void *)val, olen);
2916 goto done;
2917 }
2918 }
2919
Mat Martineau36e999a2011-12-08 17:23:21 -08002920 /* Use sane default values in case a misbehaving remote device
2921 * did not send an RFC option.
2922 */
2923 rfc.mode = chan->mode;
2924 rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
2925 rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
2926 rfc.max_pdu_size = cpu_to_le16(chan->imtu);
2927
2928 BT_ERR("Expected RFC option was not found, using defaults");
2929
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002930done:
2931 switch (rfc.mode) {
2932 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002933 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2934 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2935 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002936 break;
2937 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002938 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002939 }
2940}
2941
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002942static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2943{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002944 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002945
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002946 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002947 return 0;
2948
2949 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2950 cmd->ident == conn->info_ident) {
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02002951 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002952
2953 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002954 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002955
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002956 l2cap_conn_start(conn);
2957 }
2958
2959 return 0;
2960}
2961
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2963{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2965 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002966 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002967 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002968 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969
2970 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002971 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972
Andrei Emeltchenko097db762012-03-09 14:16:17 +02002973 BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002974
2975 /* Check if we have socket listening on psm */
Ido Yarivc2287682012-04-20 15:46:07 -03002976 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002977 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978 result = L2CAP_CR_BAD_PSM;
2979 goto sendresp;
2980 }
2981
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002982 parent = pchan->sk;
2983
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002984 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002985 lock_sock(parent);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002986
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002987 /* Check if the ACL is secure enough (if not SDP) */
2988 if (psm != cpu_to_le16(0x0001) &&
2989 !hci_conn_check_link_mode(conn->hcon)) {
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002990 conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002991 result = L2CAP_CR_SEC_BLOCK;
2992 goto response;
2993 }
2994
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995 result = L2CAP_CR_NO_MEM;
2996
2997 /* Check for backlog size */
2998 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002999 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000 goto response;
3001 }
3002
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03003003 chan = pchan->ops->new_connection(pchan->data);
3004 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005 goto response;
3006
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03003007 sk = chan->sk;
3008
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003010 if (__l2cap_get_chan_by_dcid(conn, scid)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003011 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003012 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013 goto response;
3014 }
3015
3016 hci_conn_hold(conn->hcon);
3017
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018 bacpy(&bt_sk(sk)->src, conn->src);
3019 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003020 chan->psm = psm;
3021 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022
Gustavo F. Padovand1010242011-03-25 00:39:48 -03003023 bt_accept_enqueue(parent, sk);
3024
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003025 __l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003026
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003027 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03003029 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003031 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032
Marcel Holtmann984947d2009-02-06 23:35:19 +01003033 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02003034 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01003035 if (bt_sk(sk)->defer_setup) {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02003036 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01003037 result = L2CAP_CR_PEND;
3038 status = L2CAP_CS_AUTHOR_PEND;
3039 parent->sk_data_ready(parent, 0);
3040 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02003041 __l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01003042 result = L2CAP_CR_SUCCESS;
3043 status = L2CAP_CS_NO_INFO;
3044 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003045 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02003046 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003047 result = L2CAP_CR_PEND;
3048 status = L2CAP_CS_AUTHEN_PEND;
3049 }
3050 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02003051 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003052 result = L2CAP_CR_PEND;
3053 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054 }
3055
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056response:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003057 release_sock(parent);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003058 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059
3060sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003061 rsp.scid = cpu_to_le16(scid);
3062 rsp.dcid = cpu_to_le16(dcid);
3063 rsp.result = cpu_to_le16(result);
3064 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003066
3067 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
3068 struct l2cap_info_req info;
3069 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3070
3071 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
3072 conn->info_ident = l2cap_get_ident(conn);
3073
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08003074 schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003075
3076 l2cap_send_cmd(conn, conn->info_ident,
3077 L2CAP_INFO_REQ, sizeof(info), &info);
3078 }
3079
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003080 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003081 result == L2CAP_CR_SUCCESS) {
3082 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003083 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003084 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003085 l2cap_build_conf_req(chan, buf), buf);
3086 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003087 }
3088
Linus Torvalds1da177e2005-04-16 15:20:36 -07003089 return 0;
3090}
3091
3092static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3093{
3094 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
3095 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003096 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097 u8 req[128];
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003098 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099
3100 scid = __le16_to_cpu(rsp->scid);
3101 dcid = __le16_to_cpu(rsp->dcid);
3102 result = __le16_to_cpu(rsp->result);
3103 status = __le16_to_cpu(rsp->status);
3104
Andrei Emeltchenko1b009c92012-02-21 12:54:54 +02003105 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
3106 dcid, scid, result, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003108 mutex_lock(&conn->chan_lock);
3109
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110 if (scid) {
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003111 chan = __l2cap_get_chan_by_scid(conn, scid);
3112 if (!chan) {
3113 err = -EFAULT;
3114 goto unlock;
3115 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116 } else {
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003117 chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
3118 if (!chan) {
3119 err = -EFAULT;
3120 goto unlock;
3121 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122 }
3123
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003124 err = 0;
3125
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003126 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003127
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128 switch (result) {
3129 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003130 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003131 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003132 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003133 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003134
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003135 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003136 break;
3137
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003139 l2cap_build_conf_req(chan, req), req);
3140 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003141 break;
3142
3143 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003144 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003145 break;
3146
3147 default:
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003148 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003149 break;
3150 }
3151
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003152 l2cap_chan_unlock(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003153
3154unlock:
3155 mutex_unlock(&conn->chan_lock);
3156
3157 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158}
3159
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003160static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07003161{
3162 /* FCS is enabled only in ERTM or streaming mode, if one or both
3163 * sides request it.
3164 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003165 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003166 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003167 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003168 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07003169}
3170
Al Viro88219a02007-07-29 00:17:25 -07003171static 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 -07003172{
3173 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
3174 u16 dcid, flags;
3175 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003176 struct l2cap_chan *chan;
Mat Martineau3c588192012-04-11 10:48:42 -07003177 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178
3179 dcid = __le16_to_cpu(req->dcid);
3180 flags = __le16_to_cpu(req->flags);
3181
3182 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
3183
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003184 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003185 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186 return -ENOENT;
3187
David S. Miller033b1142011-07-21 13:38:42 -07003188 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003189 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003190
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003191 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
3192 rej.scid = cpu_to_le16(chan->scid);
3193 rej.dcid = cpu_to_le16(chan->dcid);
3194
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003195 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
3196 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003197 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003198 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003199
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003200 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07003201 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04003202 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003203 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003204 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003205 L2CAP_CONF_REJECT, flags), rsp);
3206 goto unlock;
3207 }
3208
3209 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003210 memcpy(chan->conf_req + chan->conf_len, req->data, len);
3211 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212
3213 if (flags & 0x0001) {
3214 /* Incomplete config. Send empty response. */
3215 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003216 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003217 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218 goto unlock;
3219 }
3220
3221 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003222 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003223 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003224 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003225 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003226 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003228 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003229 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003230
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003231 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003232 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003233
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003234 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02003235 goto unlock;
3236
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003237 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003238 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003239
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003240 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003241
Mat Martineau105bdf92012-04-27 16:50:48 -07003242 if (chan->mode == L2CAP_MODE_ERTM ||
3243 chan->mode == L2CAP_MODE_STREAMING)
Mat Martineau3c588192012-04-11 10:48:42 -07003244 err = l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003245
Mat Martineau3c588192012-04-11 10:48:42 -07003246 if (err < 0)
3247 l2cap_send_disconn_req(chan->conn, chan, -err);
3248 else
3249 l2cap_chan_ready(chan);
3250
Marcel Holtmann876d9482007-10-20 13:35:42 +02003251 goto unlock;
3252 }
3253
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003254 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003255 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003257 l2cap_build_conf_req(chan, buf), buf);
3258 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259 }
3260
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003261 /* Got Conf Rsp PENDING from remote side and asume we sent
3262 Conf Rsp PENDING in the code above */
3263 if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
3264 test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
3265
3266 /* check compatibility */
3267
3268 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
3269 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
3270
3271 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02003272 l2cap_build_conf_rsp(chan, rsp,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003273 L2CAP_CONF_SUCCESS, 0x0000), rsp);
3274 }
3275
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276unlock:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003277 l2cap_chan_unlock(chan);
Mat Martineau3c588192012-04-11 10:48:42 -07003278 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003279}
3280
3281static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3282{
3283 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
3284 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003285 struct l2cap_chan *chan;
Andrei Emeltchenko61386cb2012-03-12 12:13:07 +02003286 int len = le16_to_cpu(cmd->len) - sizeof(*rsp);
Mat Martineau3c588192012-04-11 10:48:42 -07003287 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003288
3289 scid = __le16_to_cpu(rsp->scid);
3290 flags = __le16_to_cpu(rsp->flags);
3291 result = __le16_to_cpu(rsp->result);
3292
Andrei Emeltchenko61386cb2012-03-12 12:13:07 +02003293 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
3294 result, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003295
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003296 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003297 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298 return 0;
3299
3300 switch (result) {
3301 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003302 l2cap_conf_rfc_get(chan, rsp->data, len);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003303 clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304 break;
3305
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003306 case L2CAP_CONF_PENDING:
3307 set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
3308
3309 if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
3310 char buf[64];
3311
3312 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
3313 buf, &result);
3314 if (len < 0) {
3315 l2cap_send_disconn_req(conn, chan, ECONNRESET);
3316 goto done;
3317 }
3318
3319 /* check compatibility */
3320
3321 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
3322 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
3323
3324 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02003325 l2cap_build_conf_rsp(chan, buf,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003326 L2CAP_CONF_SUCCESS, 0x0000), buf);
3327 }
3328 goto done;
3329
Linus Torvalds1da177e2005-04-16 15:20:36 -07003330 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003331 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003332 char req[64];
3333
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003334 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003335 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003336 goto done;
3337 }
3338
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003339 /* throw out any old stored conf requests */
3340 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003341 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
3342 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003343 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003344 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003345 goto done;
3346 }
3347
3348 l2cap_send_cmd(conn, l2cap_get_ident(conn),
3349 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003350 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003351 if (result != L2CAP_CONF_SUCCESS)
3352 goto done;
3353 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354 }
3355
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09003356 default:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003357 l2cap_chan_set_err(chan, ECONNRESET);
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +02003358
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08003359 __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003360 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361 goto done;
3362 }
3363
3364 if (flags & 0x01)
3365 goto done;
3366
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003367 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003369 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003370 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003371
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003372 l2cap_state_change(chan, BT_CONNECTED);
Mat Martineau105bdf92012-04-27 16:50:48 -07003373 if (chan->mode == L2CAP_MODE_ERTM ||
3374 chan->mode == L2CAP_MODE_STREAMING)
Mat Martineau3c588192012-04-11 10:48:42 -07003375 err = l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003376
Mat Martineau3c588192012-04-11 10:48:42 -07003377 if (err < 0)
3378 l2cap_send_disconn_req(chan->conn, chan, -err);
3379 else
3380 l2cap_chan_ready(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381 }
3382
3383done:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003384 l2cap_chan_unlock(chan);
Mat Martineau3c588192012-04-11 10:48:42 -07003385 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003386}
3387
3388static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3389{
3390 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3391 struct l2cap_disconn_rsp rsp;
3392 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003393 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003394 struct sock *sk;
3395
3396 scid = __le16_to_cpu(req->scid);
3397 dcid = __le16_to_cpu(req->dcid);
3398
3399 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3400
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003401 mutex_lock(&conn->chan_lock);
3402
3403 chan = __l2cap_get_chan_by_scid(conn, dcid);
3404 if (!chan) {
3405 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003406 return 0;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003407 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003409 l2cap_chan_lock(chan);
3410
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003411 sk = chan->sk;
3412
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003413 rsp.dcid = cpu_to_le16(chan->scid);
3414 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3416
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003417 lock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003418 sk->sk_shutdown = SHUTDOWN_MASK;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003419 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420
Mat Martineau61d6ef32012-04-27 16:50:50 -07003421 l2cap_chan_hold(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003422 l2cap_chan_del(chan, ECONNRESET);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003423
3424 l2cap_chan_unlock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003425
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003426 chan->ops->close(chan->data);
Mat Martineau61d6ef32012-04-27 16:50:50 -07003427 l2cap_chan_put(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003428
3429 mutex_unlock(&conn->chan_lock);
3430
Linus Torvalds1da177e2005-04-16 15:20:36 -07003431 return 0;
3432}
3433
3434static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3435{
3436 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3437 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003438 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003439
3440 scid = __le16_to_cpu(rsp->scid);
3441 dcid = __le16_to_cpu(rsp->dcid);
3442
3443 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3444
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003445 mutex_lock(&conn->chan_lock);
3446
3447 chan = __l2cap_get_chan_by_scid(conn, scid);
3448 if (!chan) {
3449 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003450 return 0;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003451 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003452
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003453 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003454
Mat Martineau61d6ef32012-04-27 16:50:50 -07003455 l2cap_chan_hold(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003456 l2cap_chan_del(chan, 0);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003457
3458 l2cap_chan_unlock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003459
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003460 chan->ops->close(chan->data);
Mat Martineau61d6ef32012-04-27 16:50:50 -07003461 l2cap_chan_put(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003462
3463 mutex_unlock(&conn->chan_lock);
3464
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465 return 0;
3466}
3467
3468static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3469{
3470 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003471 u16 type;
3472
3473 type = __le16_to_cpu(req->type);
3474
3475 BT_DBG("type 0x%4.4x", type);
3476
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003477 if (type == L2CAP_IT_FEAT_MASK) {
3478 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003479 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003480 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3481 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3482 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003483 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003484 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3485 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003486 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003487 feat_mask |= L2CAP_FEAT_EXT_FLOW
3488 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003489
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003490 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003491 l2cap_send_cmd(conn, cmd->ident,
3492 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003493 } else if (type == L2CAP_IT_FIXED_CHAN) {
3494 u8 buf[12];
3495 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
Mat Martineau50a147c2011-11-02 16:18:34 -07003496
3497 if (enable_hs)
3498 l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
3499 else
3500 l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
3501
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003502 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3503 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003504 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003505 l2cap_send_cmd(conn, cmd->ident,
3506 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003507 } else {
3508 struct l2cap_info_rsp rsp;
3509 rsp.type = cpu_to_le16(type);
3510 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3511 l2cap_send_cmd(conn, cmd->ident,
3512 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3513 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514
3515 return 0;
3516}
3517
3518static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3519{
3520 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3521 u16 type, result;
3522
3523 type = __le16_to_cpu(rsp->type);
3524 result = __le16_to_cpu(rsp->result);
3525
3526 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3527
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003528 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3529 if (cmd->ident != conn->info_ident ||
3530 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3531 return 0;
3532
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02003533 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003534
Ville Tervoadb08ed2010-08-04 09:43:33 +03003535 if (result != L2CAP_IR_SUCCESS) {
3536 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3537 conn->info_ident = 0;
3538
3539 l2cap_conn_start(conn);
3540
3541 return 0;
3542 }
3543
Andrei Emeltchenko978c93b2012-02-29 10:41:41 +02003544 switch (type) {
3545 case L2CAP_IT_FEAT_MASK:
Harvey Harrison83985312008-05-02 16:25:46 -07003546 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003547
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003548 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003549 struct l2cap_info_req req;
3550 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3551
3552 conn->info_ident = l2cap_get_ident(conn);
3553
3554 l2cap_send_cmd(conn, conn->info_ident,
3555 L2CAP_INFO_REQ, sizeof(req), &req);
3556 } else {
3557 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3558 conn->info_ident = 0;
3559
3560 l2cap_conn_start(conn);
3561 }
Andrei Emeltchenko978c93b2012-02-29 10:41:41 +02003562 break;
3563
3564 case L2CAP_IT_FIXED_CHAN:
3565 conn->fixed_chan_mask = rsp->data[0];
Marcel Holtmann984947d2009-02-06 23:35:19 +01003566 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003567 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003568
3569 l2cap_conn_start(conn);
Andrei Emeltchenko978c93b2012-02-29 10:41:41 +02003570 break;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003571 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003572
Linus Torvalds1da177e2005-04-16 15:20:36 -07003573 return 0;
3574}
3575
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003576static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3577 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3578 void *data)
3579{
3580 struct l2cap_create_chan_req *req = data;
3581 struct l2cap_create_chan_rsp rsp;
3582 u16 psm, scid;
3583
3584 if (cmd_len != sizeof(*req))
3585 return -EPROTO;
3586
3587 if (!enable_hs)
3588 return -EINVAL;
3589
3590 psm = le16_to_cpu(req->psm);
3591 scid = le16_to_cpu(req->scid);
3592
3593 BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3594
3595 /* Placeholder: Always reject */
3596 rsp.dcid = 0;
3597 rsp.scid = cpu_to_le16(scid);
Andrei Emeltchenko8ce0c492012-03-12 12:13:09 +02003598 rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
3599 rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003600
3601 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3602 sizeof(rsp), &rsp);
3603
3604 return 0;
3605}
3606
3607static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3608 struct l2cap_cmd_hdr *cmd, void *data)
3609{
3610 BT_DBG("conn %p", conn);
3611
3612 return l2cap_connect_rsp(conn, cmd, data);
3613}
3614
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003615static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
3616 u16 icid, u16 result)
3617{
3618 struct l2cap_move_chan_rsp rsp;
3619
3620 BT_DBG("icid %d, result %d", icid, result);
3621
3622 rsp.icid = cpu_to_le16(icid);
3623 rsp.result = cpu_to_le16(result);
3624
3625 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
3626}
3627
3628static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
3629 struct l2cap_chan *chan, u16 icid, u16 result)
3630{
3631 struct l2cap_move_chan_cfm cfm;
3632 u8 ident;
3633
3634 BT_DBG("icid %d, result %d", icid, result);
3635
3636 ident = l2cap_get_ident(conn);
3637 if (chan)
3638 chan->ident = ident;
3639
3640 cfm.icid = cpu_to_le16(icid);
3641 cfm.result = cpu_to_le16(result);
3642
3643 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
3644}
3645
3646static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
3647 u16 icid)
3648{
3649 struct l2cap_move_chan_cfm_rsp rsp;
3650
3651 BT_DBG("icid %d", icid);
3652
3653 rsp.icid = cpu_to_le16(icid);
3654 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
3655}
3656
3657static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
3658 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3659{
3660 struct l2cap_move_chan_req *req = data;
3661 u16 icid = 0;
3662 u16 result = L2CAP_MR_NOT_ALLOWED;
3663
3664 if (cmd_len != sizeof(*req))
3665 return -EPROTO;
3666
3667 icid = le16_to_cpu(req->icid);
3668
3669 BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
3670
3671 if (!enable_hs)
3672 return -EINVAL;
3673
3674 /* Placeholder: Always refuse */
3675 l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
3676
3677 return 0;
3678}
3679
3680static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
3681 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3682{
3683 struct l2cap_move_chan_rsp *rsp = data;
3684 u16 icid, result;
3685
3686 if (cmd_len != sizeof(*rsp))
3687 return -EPROTO;
3688
3689 icid = le16_to_cpu(rsp->icid);
3690 result = le16_to_cpu(rsp->result);
3691
3692 BT_DBG("icid %d, result %d", icid, result);
3693
3694 /* Placeholder: Always unconfirmed */
3695 l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
3696
3697 return 0;
3698}
3699
3700static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
3701 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3702{
3703 struct l2cap_move_chan_cfm *cfm = data;
3704 u16 icid, result;
3705
3706 if (cmd_len != sizeof(*cfm))
3707 return -EPROTO;
3708
3709 icid = le16_to_cpu(cfm->icid);
3710 result = le16_to_cpu(cfm->result);
3711
3712 BT_DBG("icid %d, result %d", icid, result);
3713
3714 l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
3715
3716 return 0;
3717}
3718
3719static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
3720 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3721{
3722 struct l2cap_move_chan_cfm_rsp *rsp = data;
3723 u16 icid;
3724
3725 if (cmd_len != sizeof(*rsp))
3726 return -EPROTO;
3727
3728 icid = le16_to_cpu(rsp->icid);
3729
3730 BT_DBG("icid %d", icid);
3731
3732 return 0;
3733}
3734
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003735static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02003736 u16 to_multiplier)
3737{
3738 u16 max_latency;
3739
3740 if (min > max || min < 6 || max > 3200)
3741 return -EINVAL;
3742
3743 if (to_multiplier < 10 || to_multiplier > 3200)
3744 return -EINVAL;
3745
3746 if (max >= to_multiplier * 8)
3747 return -EINVAL;
3748
3749 max_latency = (to_multiplier * 8 / max) - 1;
3750 if (latency > 499 || latency > max_latency)
3751 return -EINVAL;
3752
3753 return 0;
3754}
3755
3756static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3757 struct l2cap_cmd_hdr *cmd, u8 *data)
3758{
3759 struct hci_conn *hcon = conn->hcon;
3760 struct l2cap_conn_param_update_req *req;
3761 struct l2cap_conn_param_update_rsp rsp;
3762 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003763 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02003764
3765 if (!(hcon->link_mode & HCI_LM_MASTER))
3766 return -EINVAL;
3767
3768 cmd_len = __le16_to_cpu(cmd->len);
3769 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3770 return -EPROTO;
3771
3772 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003773 min = __le16_to_cpu(req->min);
3774 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02003775 latency = __le16_to_cpu(req->latency);
3776 to_multiplier = __le16_to_cpu(req->to_multiplier);
3777
3778 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3779 min, max, latency, to_multiplier);
3780
3781 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003782
3783 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
3784 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02003785 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3786 else
3787 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3788
3789 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3790 sizeof(rsp), &rsp);
3791
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003792 if (!err)
3793 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
3794
Claudio Takahaside731152011-02-11 19:28:55 -02003795 return 0;
3796}
3797
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003798static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
3799 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
3800{
3801 int err = 0;
3802
3803 switch (cmd->code) {
3804 case L2CAP_COMMAND_REJ:
3805 l2cap_command_rej(conn, cmd, data);
3806 break;
3807
3808 case L2CAP_CONN_REQ:
3809 err = l2cap_connect_req(conn, cmd, data);
3810 break;
3811
3812 case L2CAP_CONN_RSP:
3813 err = l2cap_connect_rsp(conn, cmd, data);
3814 break;
3815
3816 case L2CAP_CONF_REQ:
3817 err = l2cap_config_req(conn, cmd, cmd_len, data);
3818 break;
3819
3820 case L2CAP_CONF_RSP:
3821 err = l2cap_config_rsp(conn, cmd, data);
3822 break;
3823
3824 case L2CAP_DISCONN_REQ:
3825 err = l2cap_disconnect_req(conn, cmd, data);
3826 break;
3827
3828 case L2CAP_DISCONN_RSP:
3829 err = l2cap_disconnect_rsp(conn, cmd, data);
3830 break;
3831
3832 case L2CAP_ECHO_REQ:
3833 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3834 break;
3835
3836 case L2CAP_ECHO_RSP:
3837 break;
3838
3839 case L2CAP_INFO_REQ:
3840 err = l2cap_information_req(conn, cmd, data);
3841 break;
3842
3843 case L2CAP_INFO_RSP:
3844 err = l2cap_information_rsp(conn, cmd, data);
3845 break;
3846
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003847 case L2CAP_CREATE_CHAN_REQ:
3848 err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3849 break;
3850
3851 case L2CAP_CREATE_CHAN_RSP:
3852 err = l2cap_create_channel_rsp(conn, cmd, data);
3853 break;
3854
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003855 case L2CAP_MOVE_CHAN_REQ:
3856 err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
3857 break;
3858
3859 case L2CAP_MOVE_CHAN_RSP:
3860 err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
3861 break;
3862
3863 case L2CAP_MOVE_CHAN_CFM:
3864 err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
3865 break;
3866
3867 case L2CAP_MOVE_CHAN_CFM_RSP:
3868 err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
3869 break;
3870
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003871 default:
3872 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3873 err = -EINVAL;
3874 break;
3875 }
3876
3877 return err;
3878}
3879
3880static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3881 struct l2cap_cmd_hdr *cmd, u8 *data)
3882{
3883 switch (cmd->code) {
3884 case L2CAP_COMMAND_REJ:
3885 return 0;
3886
3887 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003888 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003889
3890 case L2CAP_CONN_PARAM_UPDATE_RSP:
3891 return 0;
3892
3893 default:
3894 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3895 return -EINVAL;
3896 }
3897}
3898
3899static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3900 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901{
3902 u8 *data = skb->data;
3903 int len = skb->len;
3904 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003905 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003906
3907 l2cap_raw_recv(conn, skb);
3908
3909 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003910 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3912 data += L2CAP_CMD_HDR_SIZE;
3913 len -= L2CAP_CMD_HDR_SIZE;
3914
Al Viro88219a02007-07-29 00:17:25 -07003915 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916
Al Viro88219a02007-07-29 00:17:25 -07003917 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 -07003918
Al Viro88219a02007-07-29 00:17:25 -07003919 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920 BT_DBG("corrupted command");
3921 break;
3922 }
3923
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003924 if (conn->hcon->type == LE_LINK)
3925 err = l2cap_le_sig_cmd(conn, &cmd, data);
3926 else
3927 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928
3929 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003930 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003931
3932 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933
3934 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003935 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003936 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3937 }
3938
Al Viro88219a02007-07-29 00:17:25 -07003939 data += cmd_len;
3940 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941 }
3942
3943 kfree_skb(skb);
3944}
3945
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003946static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003947{
3948 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003949 int hdr_size;
3950
3951 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3952 hdr_size = L2CAP_EXT_HDR_SIZE;
3953 else
3954 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003955
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003956 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003957 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003958 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3959 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3960
3961 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003962 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003963 }
3964 return 0;
3965}
3966
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003967static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003968{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003969 u32 control = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003970
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003971 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003972
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003973 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003974
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003975 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003976 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003977 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003978 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003979 }
3980
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003981 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003982 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003983
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003984 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003985
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003986 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003987 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003988 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003989 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003990 }
3991}
3992
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003993static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u16 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003994{
3995 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003996 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003997
Mat Martineau3ce35142012-04-25 16:36:14 -07003998 bt_cb(skb)->control.txseq = tx_seq;
3999 bt_cb(skb)->control.sar = sar;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004000
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004001 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004002
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004003 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03004004
Szymon Janc039d9572011-11-16 09:32:19 +01004005 while (next_skb) {
Mat Martineau3ce35142012-04-25 16:36:14 -07004006 if (bt_cb(next_skb)->control.txseq == tx_seq)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004007 return -EINVAL;
4008
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004009 next_tx_seq_offset = __seq_offset(chan,
Mat Martineau3ce35142012-04-25 16:36:14 -07004010 bt_cb(next_skb)->control.txseq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03004011
4012 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004013 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004014 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004015 }
4016
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004017 if (skb_queue_is_last(&chan->srej_q, next_skb))
Szymon Janc039d9572011-11-16 09:32:19 +01004018 next_skb = NULL;
4019 else
4020 next_skb = skb_queue_next(&chan->srej_q, next_skb);
4021 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004022
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004023 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004024
4025 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004026}
4027
Mat Martineau84084a32011-07-22 14:54:00 -07004028static void append_skb_frag(struct sk_buff *skb,
4029 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004030{
Mat Martineau84084a32011-07-22 14:54:00 -07004031 /* skb->len reflects data in skb as well as all fragments
4032 * skb->data_len reflects only data in fragments
4033 */
4034 if (!skb_has_frag_list(skb))
4035 skb_shinfo(skb)->frag_list = new_frag;
4036
4037 new_frag->next = NULL;
4038
4039 (*last_frag)->next = new_frag;
4040 *last_frag = new_frag;
4041
4042 skb->len += new_frag->len;
4043 skb->data_len += new_frag->len;
4044 skb->truesize += new_frag->truesize;
4045}
4046
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004047static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
Mat Martineau84084a32011-07-22 14:54:00 -07004048{
4049 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004050
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004051 switch (__get_ctrl_sar(chan, control)) {
4052 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07004053 if (chan->sdu)
4054 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004055
Mat Martineau84084a32011-07-22 14:54:00 -07004056 err = chan->ops->recv(chan->data, skb);
4057 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004058
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004059 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07004060 if (chan->sdu)
4061 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004062
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03004063 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004064 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004065
Mat Martineau84084a32011-07-22 14:54:00 -07004066 if (chan->sdu_len > chan->imtu) {
4067 err = -EMSGSIZE;
4068 break;
4069 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004070
Mat Martineau84084a32011-07-22 14:54:00 -07004071 if (skb->len >= chan->sdu_len)
4072 break;
4073
4074 chan->sdu = skb;
4075 chan->sdu_last_frag = skb;
4076
4077 skb = NULL;
4078 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004079 break;
4080
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004081 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03004082 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07004083 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004084
Mat Martineau84084a32011-07-22 14:54:00 -07004085 append_skb_frag(chan->sdu, skb,
4086 &chan->sdu_last_frag);
4087 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004088
Mat Martineau84084a32011-07-22 14:54:00 -07004089 if (chan->sdu->len >= chan->sdu_len)
4090 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03004091
Mat Martineau84084a32011-07-22 14:54:00 -07004092 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004093 break;
4094
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004095 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03004096 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07004097 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004098
Mat Martineau84084a32011-07-22 14:54:00 -07004099 append_skb_frag(chan->sdu, skb,
4100 &chan->sdu_last_frag);
4101 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004102
Mat Martineau84084a32011-07-22 14:54:00 -07004103 if (chan->sdu->len != chan->sdu_len)
4104 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004105
Mat Martineau84084a32011-07-22 14:54:00 -07004106 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03004107
Mat Martineau84084a32011-07-22 14:54:00 -07004108 if (!err) {
4109 /* Reassembly complete */
4110 chan->sdu = NULL;
4111 chan->sdu_last_frag = NULL;
4112 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004113 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004114 break;
4115 }
4116
Mat Martineau84084a32011-07-22 14:54:00 -07004117 if (err) {
4118 kfree_skb(skb);
4119 kfree_skb(chan->sdu);
4120 chan->sdu = NULL;
4121 chan->sdu_last_frag = NULL;
4122 chan->sdu_len = 0;
4123 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004124
Mat Martineau84084a32011-07-22 14:54:00 -07004125 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004126}
4127
Mat Martineau26f880d2011-07-07 09:39:01 -07004128static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004129{
Mat Martineau26f880d2011-07-07 09:39:01 -07004130 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004131
Mat Martineau26f880d2011-07-07 09:39:01 -07004132 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
Mat Martineau3c588192012-04-11 10:48:42 -07004133 l2cap_seq_list_clear(&chan->srej_list);
Mat Martineau26f880d2011-07-07 09:39:01 -07004134
Szymon Janc77f918b2012-01-11 10:59:48 +01004135 __set_ack_timer(chan);
Mat Martineau26f880d2011-07-07 09:39:01 -07004136}
4137
4138static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
4139{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004140 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004141
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004142 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004143 goto done;
4144
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004145 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004146 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004147 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004148 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004149 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004150
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004151 __clear_retrans_timer(chan);
4152 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004153
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004154 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004155
4156done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004157 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
4158 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004159
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004160 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03004161}
4162
Mat Martineaue3281402011-07-07 09:39:02 -07004163void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03004164{
Mat Martineaue3281402011-07-07 09:39:02 -07004165 if (chan->mode == L2CAP_MODE_ERTM) {
4166 if (busy)
4167 l2cap_ertm_enter_local_busy(chan);
4168 else
4169 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03004170 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004171}
4172
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004173static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004174{
4175 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004176 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004177
Mat Martineaue3281402011-07-07 09:39:02 -07004178 while ((skb = skb_peek(&chan->srej_q)) &&
4179 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4180 int err;
4181
Mat Martineau3ce35142012-04-25 16:36:14 -07004182 if (bt_cb(skb)->control.txseq != tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004183 break;
4184
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004185 skb = skb_dequeue(&chan->srej_q);
Mat Martineau3ce35142012-04-25 16:36:14 -07004186 control = __set_ctrl_sar(chan, bt_cb(skb)->control.sar);
Mat Martineau84084a32011-07-22 14:54:00 -07004187 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07004188
4189 if (err < 0) {
4190 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4191 break;
4192 }
4193
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004194 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
4195 tx_seq = __next_seq(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004196 }
4197}
4198
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004199static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004200{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004201 struct srej_list *l, *tmp;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004202 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004203
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004204 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004205 if (l->tx_seq == tx_seq) {
4206 list_del(&l->list);
4207 kfree(l);
4208 return;
4209 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004210 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004211 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004212 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004213 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004214 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004215 }
4216}
4217
Szymon Jancaef89f22011-11-16 09:32:18 +01004218static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004219{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004220 struct srej_list *new;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004221 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004222
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004223 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004224 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004225 control |= __set_reqseq(chan, chan->expected_tx_seq);
Mat Martineau3c588192012-04-11 10:48:42 -07004226 l2cap_seq_list_append(&chan->srej_list, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004227 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004228
4229 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Szymon Jancaef89f22011-11-16 09:32:18 +01004230 if (!new)
4231 return -ENOMEM;
4232
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004233 new->tx_seq = chan->expected_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004234
4235 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
4236
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004237 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004238 }
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004239
4240 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Szymon Jancaef89f22011-11-16 09:32:18 +01004241
4242 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004243}
4244
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004245static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004246{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004247 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004248 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004249 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03004250 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004251 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004252 int err = 0;
4253
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004254 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%8.8x", chan, skb->len,
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004255 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004256
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004257 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004258 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004259 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004260 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004261 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004262 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004263 }
4264
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004265 chan->expected_ack_seq = req_seq;
4266 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03004267
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004268 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004269
4270 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004271 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004272 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004273 goto drop;
4274 }
4275
Szymon Janc77f918b2012-01-11 10:59:48 +01004276 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4277 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
4278 l2cap_send_ack(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004279 goto drop;
Szymon Janc77f918b2012-01-11 10:59:48 +01004280 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004281
Mat Martineau02f1b642011-06-29 14:35:19 -07004282 if (tx_seq == chan->expected_tx_seq)
4283 goto expected;
4284
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004285 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004286 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004287
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004288 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004289 struct srej_list, list);
4290 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004291 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004292 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004293
4294 list_del(&first->list);
4295 kfree(first);
4296
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004297 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004298 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004299 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004300 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004301 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004302 }
4303 } else {
4304 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004305
4306 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004307 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004308 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004309
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004310 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004311 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004312 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004313 return 0;
4314 }
4315 }
Szymon Jancaef89f22011-11-16 09:32:18 +01004316
4317 err = l2cap_send_srejframe(chan, tx_seq);
4318 if (err < 0) {
4319 l2cap_send_disconn_req(chan->conn, chan, -err);
4320 return err;
4321 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004322 }
4323 } else {
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004324 expected_tx_seq_offset = __seq_offset(chan,
4325 chan->expected_tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004326
4327 /* duplicated tx_seq */
4328 if (tx_seq_offset < expected_tx_seq_offset)
4329 goto drop;
4330
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004331 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004332
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004333 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004334
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004335 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004336 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004337
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004338 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004339 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004340
Szymon Janc0ef3ef02012-01-11 10:59:46 +01004341 /* Set P-bit only if there are some I-frames to ack. */
4342 if (__clear_ack_timer(chan))
4343 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03004344
Szymon Jancaef89f22011-11-16 09:32:18 +01004345 err = l2cap_send_srejframe(chan, tx_seq);
4346 if (err < 0) {
4347 l2cap_send_disconn_req(chan->conn, chan, -err);
4348 return err;
4349 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004350 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004351 return 0;
4352
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004353expected:
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004354 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004355
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004356 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Mat Martineau3ce35142012-04-25 16:36:14 -07004357 bt_cb(skb)->control.txseq = tx_seq;
4358 bt_cb(skb)->control.sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004359 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004360 return 0;
4361 }
4362
Mat Martineau84084a32011-07-22 14:54:00 -07004363 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004364 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
4365
Mat Martineaue3281402011-07-07 09:39:02 -07004366 if (err < 0) {
4367 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4368 return err;
4369 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03004370
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004371 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004372 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004373 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03004374 }
4375
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03004376
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004377 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
4378 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004379 l2cap_send_ack(chan);
Gustavo F. Padovan4d611e42011-06-23 19:30:48 -03004380 else
4381 __set_ack_timer(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03004382
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004383 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004384
4385drop:
4386 kfree_skb(skb);
4387 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004388}
4389
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004390static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004391{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004392 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004393 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004394
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004395 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004396 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004397
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004398 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004399 set_bit(CONN_SEND_FBIT, &chan->conn_state);
4400 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
4401 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004402 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004403 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004404
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004405 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004406 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004407 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004408 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004409 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004410
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004411 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004412 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004413
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004414 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004415 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004416
4417 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004418 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004419 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004420 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004421
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004422 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4423 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004424 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02004425 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004426 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004427 }
4428}
4429
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004430static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004431{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004432 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004433
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004434 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004435
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004436 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004437
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004438 chan->expected_ack_seq = tx_seq;
4439 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004440
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004441 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004442 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004443 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004444 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004445 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004446
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004447 if (test_bit(CONN_WAIT_F, &chan->conn_state))
4448 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004449 }
4450}
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004451static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004452{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004453 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004454
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004455 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004456
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004457 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004458
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004459 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004460 chan->expected_ack_seq = tx_seq;
4461 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004462
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004463 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004464 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004465
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004466 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004467
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004468 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004469 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004470 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004471 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004472 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004473 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004474 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004475 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004476 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004477 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004478 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004479 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004480 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004481 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004482 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004483 }
4484 }
4485}
4486
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004487static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004488{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004489 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004490
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004491 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004492
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004493 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004494 chan->expected_ack_seq = tx_seq;
4495 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004496
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004497 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004498 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004499
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004500 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004501 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004502 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004503 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004504 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004505 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004506
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004507 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004508 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004509 } else {
4510 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4511 l2cap_send_sframe(chan, rx_control);
4512 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004513}
4514
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004515static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004516{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004517 BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004518
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004519 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004520 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004521 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004522 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004523 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004524 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004525 }
4526
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004527 switch (__get_ctrl_super(chan, rx_control)) {
4528 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004529 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004530 break;
4531
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004532 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004533 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004534 break;
4535
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004536 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004537 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004538 break;
4539
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004540 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004541 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004542 break;
4543 }
4544
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004545 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004546 return 0;
4547}
4548
Szymon Janccad8f1d02012-01-23 10:06:05 +01004549static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004550{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004551 u32 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004552 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004553 int len, next_tx_seq_offset, req_seq_offset;
4554
Mat Martineaub76bbd62012-04-11 10:48:43 -07004555 __unpack_control(chan, skb);
4556
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004557 control = __get_control(chan, skb->data);
4558 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004559 len = skb->len;
4560
4561 /*
4562 * We can just drop the corrupted I-frame here.
4563 * Receiver will miss it and start proper recovery
4564 * procedures and ask retransmission.
4565 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004566 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004567 goto drop;
4568
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004569 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004570 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004571
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004572 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004573 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004574
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004575 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004576 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004577 goto drop;
4578 }
4579
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004580 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004581
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004582 req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4583
4584 next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4585 chan->expected_ack_seq);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004586
4587 /* check for invalid req-seq */
4588 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004589 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004590 goto drop;
4591 }
4592
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004593 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004594 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004595 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004596 goto drop;
4597 }
4598
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004599 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004600 } else {
4601 if (len != 0) {
4602 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004603 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004604 goto drop;
4605 }
4606
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004607 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004608 }
4609
4610 return 0;
4611
4612drop:
4613 kfree_skb(skb);
4614 return 0;
4615}
4616
Linus Torvalds1da177e2005-04-16 15:20:36 -07004617static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4618{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004619 struct l2cap_chan *chan;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004620 u32 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004621 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004622 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004623
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004624 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004625 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004626 BT_DBG("unknown cid 0x%4.4x", cid);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004627 /* Drop packet and return */
Dan Carpenter33790132012-02-28 09:52:46 +03004628 kfree_skb(skb);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004629 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004630 }
4631
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004632 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004633
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004634 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004635 goto drop;
4636
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004637 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004638 case L2CAP_MODE_BASIC:
4639 /* If socket recv buffers overflows we drop data here
4640 * which is *bad* because L2CAP has to be reliable.
4641 * But we don't have any other choice. L2CAP doesn't
4642 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004643
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004644 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004645 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004646
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004647 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004648 goto done;
4649 break;
4650
4651 case L2CAP_MODE_ERTM:
Andrei Emeltchenko5ef8cb92012-01-13 17:21:42 +02004652 l2cap_ertm_data_rcv(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004653
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004654 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004655
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004656 case L2CAP_MODE_STREAMING:
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004657 control = __get_control(chan, skb->data);
4658 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004659 len = skb->len;
4660
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004661 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004662 goto drop;
4663
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004664 if (__is_sar_start(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004665 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004666
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004667 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004668 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004669
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004670 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004671 goto drop;
4672
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004673 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004674
Mat Martineau84084a32011-07-22 14:54:00 -07004675 if (chan->expected_tx_seq != tx_seq) {
4676 /* Frame(s) missing - must discard partial SDU */
4677 kfree_skb(chan->sdu);
4678 chan->sdu = NULL;
4679 chan->sdu_last_frag = NULL;
4680 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004681
Mat Martineau84084a32011-07-22 14:54:00 -07004682 /* TODO: Notify userland of missing data */
4683 }
4684
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004685 chan->expected_tx_seq = __next_seq(chan, tx_seq);
Mat Martineau84084a32011-07-22 14:54:00 -07004686
4687 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
4688 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004689
4690 goto done;
4691
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004692 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004693 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004694 break;
4695 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004696
4697drop:
4698 kfree_skb(skb);
4699
4700done:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004701 l2cap_chan_unlock(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +02004702
Linus Torvalds1da177e2005-04-16 15:20:36 -07004703 return 0;
4704}
4705
Al Viro8e036fc2007-07-29 00:16:36 -07004706static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004707{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004708 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004709
Ido Yarivc2287682012-04-20 15:46:07 -03004710 chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004711 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004712 goto drop;
4713
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02004714 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004715
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004716 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004717 goto drop;
4718
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004719 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004720 goto drop;
4721
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004722 if (!chan->ops->recv(chan->data, skb))
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02004723 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004724
4725drop:
4726 kfree_skb(skb);
4727
Linus Torvalds1da177e2005-04-16 15:20:36 -07004728 return 0;
4729}
4730
Andrei Emeltchenkod9b88702012-03-12 12:13:08 +02004731static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid,
4732 struct sk_buff *skb)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004733{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004734 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004735
Ido Yarivc2287682012-04-20 15:46:07 -03004736 chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004737 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004738 goto drop;
4739
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02004740 BT_DBG("chan %p, len %d", chan, skb->len);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004741
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004742 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004743 goto drop;
4744
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004745 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004746 goto drop;
4747
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004748 if (!chan->ops->recv(chan->data, skb))
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02004749 return 0;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004750
4751drop:
4752 kfree_skb(skb);
4753
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004754 return 0;
4755}
4756
Linus Torvalds1da177e2005-04-16 15:20:36 -07004757static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4758{
4759 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004760 u16 cid, len;
4761 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004762
4763 skb_pull(skb, L2CAP_HDR_SIZE);
4764 cid = __le16_to_cpu(lh->cid);
4765 len = __le16_to_cpu(lh->len);
4766
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004767 if (len != skb->len) {
4768 kfree_skb(skb);
4769 return;
4770 }
4771
Linus Torvalds1da177e2005-04-16 15:20:36 -07004772 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4773
4774 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004775 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004776 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004777 l2cap_sig_channel(conn, skb);
4778 break;
4779
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004780 case L2CAP_CID_CONN_LESS:
Andrei Emeltchenko097db762012-03-09 14:16:17 +02004781 psm = get_unaligned((__le16 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004782 skb_pull(skb, 2);
4783 l2cap_conless_channel(conn, psm, skb);
4784 break;
4785
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004786 case L2CAP_CID_LE_DATA:
4787 l2cap_att_channel(conn, cid, skb);
4788 break;
4789
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004790 case L2CAP_CID_SMP:
4791 if (smp_sig_channel(conn, skb))
4792 l2cap_conn_del(conn->hcon, EACCES);
4793 break;
4794
Linus Torvalds1da177e2005-04-16 15:20:36 -07004795 default:
4796 l2cap_data_channel(conn, cid, skb);
4797 break;
4798 }
4799}
4800
4801/* ---- L2CAP interface with lower layer (HCI) ---- */
4802
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004803int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004804{
4805 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004806 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004807
Linus Torvalds1da177e2005-04-16 15:20:36 -07004808 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4809
4810 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004811 read_lock(&chan_list_lock);
4812 list_for_each_entry(c, &chan_list, global_l) {
4813 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004814
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004815 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004816 continue;
4817
4818 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004819 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004820 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004821 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004822 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004823 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4824 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004825 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004826 lm2 |= HCI_LM_MASTER;
4827 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004828 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004829 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004830
4831 return exact ? lm1 : lm2;
4832}
4833
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004834int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004835{
Marcel Holtmann01394182006-07-03 10:02:46 +02004836 struct l2cap_conn *conn;
4837
Linus Torvalds1da177e2005-04-16 15:20:36 -07004838 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4839
Linus Torvalds1da177e2005-04-16 15:20:36 -07004840 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004841 conn = l2cap_conn_add(hcon, status);
4842 if (conn)
4843 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004844 } else
Joe Perchese1750722011-06-29 18:18:29 -07004845 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004846
4847 return 0;
4848}
4849
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004850int l2cap_disconn_ind(struct hci_conn *hcon)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004851{
4852 struct l2cap_conn *conn = hcon->l2cap_data;
4853
4854 BT_DBG("hcon %p", hcon);
4855
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004856 if (!conn)
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02004857 return HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01004858 return conn->disc_reason;
4859}
4860
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004861int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004862{
4863 BT_DBG("hcon %p reason %d", hcon, reason);
4864
Joe Perchese1750722011-06-29 18:18:29 -07004865 l2cap_conn_del(hcon, bt_to_errno(reason));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004866 return 0;
4867}
4868
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004869static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004870{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004871 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004872 return;
4873
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004874 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004875 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08004876 __set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004877 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004878 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004879 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004880 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004881 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004882 }
4883}
4884
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004885int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004886{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004887 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004888 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004889
Marcel Holtmann01394182006-07-03 10:02:46 +02004890 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004891 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004892
Linus Torvalds1da177e2005-04-16 15:20:36 -07004893 BT_DBG("conn %p", conn);
4894
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004895 if (hcon->type == LE_LINK) {
Hemant Gupta35d4adcc2012-04-18 14:46:26 +05304896 if (!status && encrypt)
4897 smp_distribute_keys(conn, 0);
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02004898 cancel_delayed_work(&conn->security_timer);
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004899 }
4900
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004901 mutex_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004902
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004903 list_for_each_entry(chan, &conn->chan_l, list) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004904 l2cap_chan_lock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004905
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004906 BT_DBG("chan->scid %d", chan->scid);
4907
4908 if (chan->scid == L2CAP_CID_LE_DATA) {
4909 if (!status && encrypt) {
4910 chan->sec_level = hcon->sec_level;
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02004911 l2cap_chan_ready(chan);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004912 }
4913
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004914 l2cap_chan_unlock(chan);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004915 continue;
4916 }
4917
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004918 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004919 l2cap_chan_unlock(chan);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004920 continue;
4921 }
4922
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004923 if (!status && (chan->state == BT_CONNECTED ||
4924 chan->state == BT_CONFIG)) {
Gustavo Padovana7d77232012-05-13 03:20:07 -03004925 struct sock *sk = chan->sk;
4926
4927 bt_sk(sk)->suspended = false;
4928 sk->sk_state_change(sk);
4929
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004930 l2cap_check_encryption(chan, encrypt);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004931 l2cap_chan_unlock(chan);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004932 continue;
4933 }
4934
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004935 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004936 if (!status) {
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +02004937 l2cap_send_conn_req(chan);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004938 } else {
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08004939 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004940 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004941 } else if (chan->state == BT_CONNECT2) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004942 struct sock *sk = chan->sk;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004943 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004944 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004945
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004946 lock_sock(sk);
4947
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004948 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004949 if (bt_sk(sk)->defer_setup) {
4950 struct sock *parent = bt_sk(sk)->parent;
4951 res = L2CAP_CR_PEND;
4952 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004953 if (parent)
4954 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004955 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02004956 __l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004957 res = L2CAP_CR_SUCCESS;
4958 stat = L2CAP_CS_NO_INFO;
4959 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004960 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02004961 __l2cap_state_change(chan, BT_DISCONN);
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08004962 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004963 res = L2CAP_CR_SEC_BLOCK;
4964 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004965 }
4966
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004967 release_sock(sk);
4968
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004969 rsp.scid = cpu_to_le16(chan->dcid);
4970 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004971 rsp.result = cpu_to_le16(res);
4972 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004973 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4974 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004975 }
4976
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004977 l2cap_chan_unlock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004978 }
4979
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004980 mutex_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004981
Linus Torvalds1da177e2005-04-16 15:20:36 -07004982 return 0;
4983}
4984
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004985int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004986{
4987 struct l2cap_conn *conn = hcon->l2cap_data;
4988
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004989 if (!conn)
4990 conn = l2cap_conn_add(hcon, 0);
4991
4992 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004993 goto drop;
4994
4995 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4996
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004997 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004998 struct l2cap_hdr *hdr;
4999 int len;
5000
5001 if (conn->rx_len) {
5002 BT_ERR("Unexpected start frame (len %d)", skb->len);
5003 kfree_skb(conn->rx_skb);
5004 conn->rx_skb = NULL;
5005 conn->rx_len = 0;
5006 l2cap_conn_unreliable(conn, ECOMM);
5007 }
5008
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03005009 /* Start fragment always begin with Basic L2CAP header */
5010 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005011 BT_ERR("Frame is too short (len %d)", skb->len);
5012 l2cap_conn_unreliable(conn, ECOMM);
5013 goto drop;
5014 }
5015
5016 hdr = (struct l2cap_hdr *) skb->data;
5017 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
5018
5019 if (len == skb->len) {
5020 /* Complete frame received */
5021 l2cap_recv_frame(conn, skb);
5022 return 0;
5023 }
5024
5025 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
5026
5027 if (skb->len > len) {
5028 BT_ERR("Frame is too long (len %d, expected len %d)",
5029 skb->len, len);
5030 l2cap_conn_unreliable(conn, ECOMM);
5031 goto drop;
5032 }
5033
5034 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03005035 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
5036 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005037 goto drop;
5038
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03005039 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01005040 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005041 conn->rx_len = len - skb->len;
5042 } else {
5043 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
5044
5045 if (!conn->rx_len) {
5046 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
5047 l2cap_conn_unreliable(conn, ECOMM);
5048 goto drop;
5049 }
5050
5051 if (skb->len > conn->rx_len) {
5052 BT_ERR("Fragment is too long (len %d, expected %d)",
5053 skb->len, conn->rx_len);
5054 kfree_skb(conn->rx_skb);
5055 conn->rx_skb = NULL;
5056 conn->rx_len = 0;
5057 l2cap_conn_unreliable(conn, ECOMM);
5058 goto drop;
5059 }
5060
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03005061 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01005062 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005063 conn->rx_len -= skb->len;
5064
5065 if (!conn->rx_len) {
5066 /* Complete frame received */
5067 l2cap_recv_frame(conn, conn->rx_skb);
5068 conn->rx_skb = NULL;
5069 }
5070 }
5071
5072drop:
5073 kfree_skb(skb);
5074 return 0;
5075}
5076
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005077static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005078{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005079 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005080
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02005081 read_lock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005082
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005083 list_for_each_entry(c, &chan_list, global_l) {
5084 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005085
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02005086 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 +01005087 batostr(&bt_sk(sk)->src),
5088 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03005089 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005090 c->scid, c->dcid, c->imtu, c->omtu,
5091 c->sec_level, c->mode);
Andrei Emeltchenko61e1b4b2012-01-19 11:19:50 +02005092 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005093
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02005094 read_unlock(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08005095
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005096 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005097}
5098
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005099static int l2cap_debugfs_open(struct inode *inode, struct file *file)
5100{
5101 return single_open(file, l2cap_debugfs_show, inode->i_private);
5102}
5103
5104static const struct file_operations l2cap_debugfs_fops = {
5105 .open = l2cap_debugfs_open,
5106 .read = seq_read,
5107 .llseek = seq_lseek,
5108 .release = single_release,
5109};
5110
5111static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005112
Gustavo F. Padovan64274512011-02-07 20:08:52 -02005113int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005114{
5115 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08005116
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02005117 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005118 if (err < 0)
5119 return err;
5120
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005121 if (bt_debugfs) {
5122 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
5123 bt_debugfs, NULL, &l2cap_debugfs_fops);
5124 if (!l2cap_debugfs)
5125 BT_ERR("Failed to create L2CAP debug file");
5126 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005127
Linus Torvalds1da177e2005-04-16 15:20:36 -07005128 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005129}
5130
Gustavo F. Padovan64274512011-02-07 20:08:52 -02005131void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005132{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005133 debugfs_remove(l2cap_debugfs);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02005134 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005135}
5136
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03005137module_param(disable_ertm, bool, 0644);
5138MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");