blob: 041ebed9e64773ce798787346451b3da7b660659 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Gustavo F. Padovan590051d2011-12-18 13:39:33 -02006 Copyright (C) 2011 ProFUSION Embedded Systems
Linus Torvalds1da177e2005-04-16 15:20:36 -07007
8 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License version 2 as
12 published by the Free Software Foundation;
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
17 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090018 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090023 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
24 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070025 SOFTWARE IS DISCLAIMED.
26*/
27
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020028/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070029
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/module.h>
31
32#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080033#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/errno.h>
35#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/sched.h>
37#include <linux/slab.h>
38#include <linux/poll.h>
39#include <linux/fcntl.h>
40#include <linux/init.h>
41#include <linux/interrupt.h>
42#include <linux/socket.h>
43#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080045#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010046#include <linux/debugfs.h>
47#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030048#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030049#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#include <net/sock.h>
51
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
Anderson Brigliab501d6a2011-06-07 18:46:31 -030057#include <net/bluetooth/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
Rusty Russelleb939922011-12-19 14:08:01 +000059bool disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020060
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070061static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Mat Martineau50a147c2011-11-02 16:18:34 -070062static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
Johannes Bergb5ad8b72011-06-01 08:54:45 +020064static LIST_HEAD(chan_list);
65static DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
Linus Torvalds1da177e2005-04-16 15:20:36 -070067static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
68 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030069static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
70 void *data);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -030071static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030072static void l2cap_send_disconn_req(struct l2cap_conn *conn,
73 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Marcel Holtmann01394182006-07-03 10:02:46 +020075/* ---- L2CAP channels ---- */
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -030076
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030077static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020078{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020079 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030080
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020081 list_for_each_entry(c, &conn->chan_l, list) {
82 if (c->dcid == cid)
83 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020084 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020085 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +020086}
87
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030088static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020089{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020090 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030091
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020092 list_for_each_entry(c, &conn->chan_l, list) {
93 if (c->scid == cid)
94 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020095 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020096 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +020097}
98
99/* Find channel with given SCID.
100 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300101static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200102{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300103 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300104
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200105 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300106 c = __l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200107 mutex_unlock(&conn->chan_lock);
108
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300109 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200110}
111
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300112static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200113{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200114 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300115
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200116 list_for_each_entry(c, &conn->chan_l, list) {
117 if (c->ident == ident)
118 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200119 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200120 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200121}
122
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300123static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200124{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300125 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300126
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200127 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300128 c = __l2cap_get_chan_by_ident(conn, ident);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200129 mutex_unlock(&conn->chan_lock);
130
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300131 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200132}
133
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300134static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300135{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300136 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300137
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300138 list_for_each_entry(c, &chan_list, global_l) {
139 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Szymon Janc250938c2011-11-16 09:32:22 +0100140 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300141 }
Szymon Janc250938c2011-11-16 09:32:22 +0100142 return NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300143}
144
145int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
146{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300147 int err;
148
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200149 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300150
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300151 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300152 err = -EADDRINUSE;
153 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300154 }
155
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300156 if (psm) {
157 chan->psm = psm;
158 chan->sport = psm;
159 err = 0;
160 } else {
161 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300162
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300163 err = -EINVAL;
164 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300165 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300166 chan->psm = cpu_to_le16(p);
167 chan->sport = cpu_to_le16(p);
168 err = 0;
169 break;
170 }
171 }
172
173done:
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200174 write_unlock(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300175 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300176}
177
178int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
179{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200180 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300181
182 chan->scid = scid;
183
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200184 write_unlock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300185
186 return 0;
187}
188
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300189static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200190{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300191 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200192
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300193 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300194 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200195 return cid;
196 }
197
198 return 0;
199}
200
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200201static void __l2cap_state_change(struct l2cap_chan *chan, int state)
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300202{
Andrei Emeltchenko42d2d872012-02-17 11:40:57 +0200203 BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
Gustavo F. Padovanbadaaa02011-11-23 20:11:46 -0200204 state_to_string(state));
205
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300206 chan->state = state;
207 chan->ops->state_change(chan->data, state);
208}
209
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200210static void l2cap_state_change(struct l2cap_chan *chan, int state)
211{
212 struct sock *sk = chan->sk;
213
214 lock_sock(sk);
215 __l2cap_state_change(chan, state);
216 release_sock(sk);
217}
218
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +0200219static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err)
220{
221 struct sock *sk = chan->sk;
222
223 sk->sk_err = err;
224}
225
226static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
227{
228 struct sock *sk = chan->sk;
229
230 lock_sock(sk);
231 __l2cap_chan_set_err(chan, err);
232 release_sock(sk);
233}
234
Mat Martineau3c588192012-04-11 10:48:42 -0700235/* ---- L2CAP sequence number lists ---- */
236
237/* For ERTM, ordered lists of sequence numbers must be tracked for
238 * SREJ requests that are received and for frames that are to be
239 * retransmitted. These seq_list functions implement a singly-linked
240 * list in an array, where membership in the list can also be checked
241 * in constant time. Items can also be added to the tail of the list
242 * and removed from the head in constant time, without further memory
243 * allocs or frees.
244 */
245
246static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
247{
248 size_t alloc_size, i;
249
250 /* Allocated size is a power of 2 to map sequence numbers
251 * (which may be up to 14 bits) in to a smaller array that is
252 * sized for the negotiated ERTM transmit windows.
253 */
254 alloc_size = roundup_pow_of_two(size);
255
256 seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL);
257 if (!seq_list->list)
258 return -ENOMEM;
259
260 seq_list->mask = alloc_size - 1;
261 seq_list->head = L2CAP_SEQ_LIST_CLEAR;
262 seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
263 for (i = 0; i < alloc_size; i++)
264 seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
265
266 return 0;
267}
268
269static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
270{
271 kfree(seq_list->list);
272}
273
274static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
275 u16 seq)
276{
277 /* Constant-time check for list membership */
278 return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
279}
280
281static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq)
282{
283 u16 mask = seq_list->mask;
284
285 if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) {
286 /* In case someone tries to pop the head of an empty list */
287 return L2CAP_SEQ_LIST_CLEAR;
288 } else if (seq_list->head == seq) {
289 /* Head can be removed in constant time */
290 seq_list->head = seq_list->list[seq & mask];
291 seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
292
293 if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
294 seq_list->head = L2CAP_SEQ_LIST_CLEAR;
295 seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
296 }
297 } else {
298 /* Walk the list to find the sequence number */
299 u16 prev = seq_list->head;
300 while (seq_list->list[prev & mask] != seq) {
301 prev = seq_list->list[prev & mask];
302 if (prev == L2CAP_SEQ_LIST_TAIL)
303 return L2CAP_SEQ_LIST_CLEAR;
304 }
305
306 /* Unlink the number from the list and clear it */
307 seq_list->list[prev & mask] = seq_list->list[seq & mask];
308 seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
309 if (seq_list->tail == seq)
310 seq_list->tail = prev;
311 }
312 return seq;
313}
314
315static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
316{
317 /* Remove the head in constant time */
318 return l2cap_seq_list_remove(seq_list, seq_list->head);
319}
320
321static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
322{
323 if (seq_list->head != L2CAP_SEQ_LIST_CLEAR) {
324 u16 i;
325 for (i = 0; i <= seq_list->mask; i++)
326 seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
327
328 seq_list->head = L2CAP_SEQ_LIST_CLEAR;
329 seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
330 }
331}
332
333static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
334{
335 u16 mask = seq_list->mask;
336
337 /* All appends happen in constant time */
338
339 if (seq_list->list[seq & mask] == L2CAP_SEQ_LIST_CLEAR) {
340 if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
341 seq_list->head = seq;
342 else
343 seq_list->list[seq_list->tail & mask] = seq;
344
345 seq_list->tail = seq;
346 seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
347 }
348}
349
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300350static void l2cap_chan_timeout(struct work_struct *work)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300351{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300352 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
353 chan_timer.work);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200354 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300355 int reason;
356
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200357 BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300358
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200359 mutex_lock(&conn->chan_lock);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200360 l2cap_chan_lock(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300361
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300362 if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300363 reason = ECONNREFUSED;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300364 else if (chan->state == BT_CONNECT &&
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300365 chan->sec_level != BT_SECURITY_SDP)
366 reason = ECONNREFUSED;
367 else
368 reason = ETIMEDOUT;
369
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300370 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300371
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200372 l2cap_chan_unlock(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300373
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300374 chan->ops->close(chan->data);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200375 mutex_unlock(&conn->chan_lock);
376
Ulisses Furquim371fd832011-12-21 20:02:36 -0200377 l2cap_chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300378}
379
Gustavo Padovaneef1d9b2012-03-25 13:59:16 -0300380struct l2cap_chan *l2cap_chan_create(void)
Marcel Holtmann01394182006-07-03 10:02:46 +0200381{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300382 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200383
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300384 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
385 if (!chan)
386 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200387
Andrei Emeltchenkoc03b3552012-02-21 12:54:56 +0200388 mutex_init(&chan->lock);
389
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200390 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300391 list_add(&chan->global_l, &chan_list);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200392 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300393
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300394 INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300395
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300396 chan->state = BT_OPEN;
397
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300398 atomic_set(&chan->refcnt, 1);
399
Gustavo Padovaneef1d9b2012-03-25 13:59:16 -0300400 BT_DBG("chan %p", chan);
Szymon Jancabc545b2011-11-03 16:05:44 +0100401
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300402 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200403}
404
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300405void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300406{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200407 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300408 list_del(&chan->global_l);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200409 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300410
Ulisses Furquim371fd832011-12-21 20:02:36 -0200411 l2cap_chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300412}
413
Andrei Emeltchenkobd4b1652012-03-28 16:31:25 +0300414void l2cap_chan_set_defaults(struct l2cap_chan *chan)
415{
416 chan->fcs = L2CAP_FCS_CRC16;
417 chan->max_tx = L2CAP_DEFAULT_MAX_TX;
418 chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
419 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
420 chan->sec_level = BT_SECURITY_LOW;
421
422 set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
423}
424
Andrei Emeltchenko14a28492012-03-23 16:31:49 +0200425static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200426{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300427 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Andrei Emeltchenko097db762012-03-09 14:16:17 +0200428 __le16_to_cpu(chan->psm), chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200429
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +0200430 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +0100431
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300432 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200433
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200434 switch (chan->chan_type) {
435 case L2CAP_CHAN_CONN_ORIENTED:
Ville Tervob62f3282011-02-10 22:38:50 -0300436 if (conn->hcon->type == LE_LINK) {
437 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300438 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300439 chan->scid = L2CAP_CID_LE_DATA;
440 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300441 } else {
442 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300443 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300444 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300445 }
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200446 break;
447
448 case L2CAP_CHAN_CONN_LESS:
Marcel Holtmann01394182006-07-03 10:02:46 +0200449 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300450 chan->scid = L2CAP_CID_CONN_LESS;
451 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300452 chan->omtu = L2CAP_DEFAULT_MTU;
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200453 break;
454
455 default:
Marcel Holtmann01394182006-07-03 10:02:46 +0200456 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300457 chan->scid = L2CAP_CID_SIGNALING;
458 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300459 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200460 }
461
Andrei Emeltchenko8f7975b2011-10-13 16:18:54 +0300462 chan->local_id = L2CAP_BESTEFFORT_ID;
463 chan->local_stype = L2CAP_SERV_BESTEFFORT;
464 chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
465 chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
466 chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
467 chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
468
Ulisses Furquim371fd832011-12-21 20:02:36 -0200469 l2cap_chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300470
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200471 list_add(&chan->list, &conn->chan_l);
Andrei Emeltchenko643162a2012-02-22 17:11:55 +0200472}
473
Andrei Emeltchenko14a28492012-03-23 16:31:49 +0200474static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Andrei Emeltchenko643162a2012-02-22 17:11:55 +0200475{
476 mutex_lock(&conn->chan_lock);
477 __l2cap_chan_add(conn, chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200478 mutex_unlock(&conn->chan_lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200479}
480
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300481static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200482{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300483 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300484 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200485 struct sock *parent = bt_sk(sk)->parent;
486
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300487 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200488
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300489 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200490
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900491 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300492 /* Delete from channel list */
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200493 list_del(&chan->list);
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200494
Ulisses Furquim371fd832011-12-21 20:02:36 -0200495 l2cap_chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300496
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300497 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200498 hci_conn_put(conn->hcon);
499 }
500
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200501 lock_sock(sk);
502
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200503 __l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200504 sock_set_flag(sk, SOCK_ZAPPED);
505
506 if (err)
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +0200507 __l2cap_chan_set_err(chan, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200508
509 if (parent) {
510 bt_accept_unlink(sk);
511 parent->sk_data_ready(parent, 0);
512 } else
513 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300514
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200515 release_sock(sk);
516
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300517 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
518 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300519 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300520
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300521 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300522
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300523 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300524 struct srej_list *l, *tmp;
525
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300526 __clear_retrans_timer(chan);
527 __clear_monitor_timer(chan);
528 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300529
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300530 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300531
Mat Martineau3c588192012-04-11 10:48:42 -0700532 l2cap_seq_list_free(&chan->srej_list);
533 l2cap_seq_list_free(&chan->retrans_list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300534 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300535 list_del(&l->list);
536 kfree(l);
537 }
538 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200539}
540
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300541static void l2cap_chan_cleanup_listen(struct sock *parent)
542{
543 struct sock *sk;
544
545 BT_DBG("parent %p", parent);
546
547 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300548 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300549 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200550
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200551 l2cap_chan_lock(chan);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300552 __clear_chan_timer(chan);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300553 l2cap_chan_close(chan, ECONNRESET);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200554 l2cap_chan_unlock(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200555
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300556 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300557 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300558}
559
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300560void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300561{
562 struct l2cap_conn *conn = chan->conn;
563 struct sock *sk = chan->sk;
564
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200565 BT_DBG("chan %p state %s sk %p", chan,
566 state_to_string(chan->state), sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300567
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300568 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300569 case BT_LISTEN:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200570 lock_sock(sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300571 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300572
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200573 __l2cap_state_change(chan, BT_CLOSED);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300574 sock_set_flag(sk, SOCK_ZAPPED);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200575 release_sock(sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300576 break;
577
578 case BT_CONNECTED:
579 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300580 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300581 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300582 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300583 l2cap_send_disconn_req(conn, chan, reason);
584 } else
585 l2cap_chan_del(chan, reason);
586 break;
587
588 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300589 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300590 conn->hcon->type == ACL_LINK) {
591 struct l2cap_conn_rsp rsp;
592 __u16 result;
593
594 if (bt_sk(sk)->defer_setup)
595 result = L2CAP_CR_SEC_BLOCK;
596 else
597 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300598 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300599
600 rsp.scid = cpu_to_le16(chan->dcid);
601 rsp.dcid = cpu_to_le16(chan->scid);
602 rsp.result = cpu_to_le16(result);
603 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
604 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
605 sizeof(rsp), &rsp);
606 }
607
608 l2cap_chan_del(chan, reason);
609 break;
610
611 case BT_CONNECT:
612 case BT_DISCONN:
613 l2cap_chan_del(chan, reason);
614 break;
615
616 default:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200617 lock_sock(sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300618 sock_set_flag(sk, SOCK_ZAPPED);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200619 release_sock(sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300620 break;
621 }
622}
623
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300624static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530625{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300626 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300627 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530628 case BT_SECURITY_HIGH:
629 return HCI_AT_DEDICATED_BONDING_MITM;
630 case BT_SECURITY_MEDIUM:
631 return HCI_AT_DEDICATED_BONDING;
632 default:
633 return HCI_AT_NO_BONDING;
634 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300635 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300636 if (chan->sec_level == BT_SECURITY_LOW)
637 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530638
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300639 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530640 return HCI_AT_NO_BONDING_MITM;
641 else
642 return HCI_AT_NO_BONDING;
643 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300644 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530645 case BT_SECURITY_HIGH:
646 return HCI_AT_GENERAL_BONDING_MITM;
647 case BT_SECURITY_MEDIUM:
648 return HCI_AT_GENERAL_BONDING;
649 default:
650 return HCI_AT_NO_BONDING;
651 }
652 }
653}
654
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200655/* Service level security */
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200656int l2cap_chan_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200657{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300658 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100659 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200660
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300661 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100662
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300663 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200664}
665
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200666static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200667{
668 u8 id;
669
670 /* Get next available identificator.
671 * 1 - 128 are used by kernel.
672 * 129 - 199 are reserved.
673 * 200 - 254 are used by utilities like l2ping, etc.
674 */
675
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200676 spin_lock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200677
678 if (++conn->tx_ident > 128)
679 conn->tx_ident = 1;
680
681 id = conn->tx_ident;
682
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200683 spin_unlock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200684
685 return id;
686}
687
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300688static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200689{
690 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200691 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200692
693 BT_DBG("code 0x%2.2x", code);
694
695 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300696 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200697
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200698 if (lmp_no_flush_capable(conn->hcon->hdev))
699 flags = ACL_START_NO_FLUSH;
700 else
701 flags = ACL_START;
702
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700703 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +0200704 skb->priority = HCI_PRIO_MAX;
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700705
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200706 hci_send_acl(conn->hchan, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200707}
708
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200709static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
710{
711 struct hci_conn *hcon = chan->conn->hcon;
712 u16 flags;
713
714 BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
715 skb->priority);
716
717 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
718 lmp_no_flush_capable(hcon->hdev))
719 flags = ACL_START_NO_FLUSH;
720 else
721 flags = ACL_START;
722
723 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
724 hci_send_acl(chan->conn->hchan, skb, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725}
726
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300727static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300728{
729 struct sk_buff *skb;
730 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300731 struct l2cap_conn *conn = chan->conn;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300732 int count, hlen;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300733
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300734 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300735 return;
736
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300737 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
738 hlen = L2CAP_EXT_HDR_SIZE;
739 else
740 hlen = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300741
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300742 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300743 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300744
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300745 BT_DBG("chan %p, control 0x%8.8x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300746
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300747 count = min_t(unsigned int, conn->mtu, hlen);
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +0300748
749 control |= __set_sframe(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300750
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300751 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +0300752 control |= __set_ctrl_final(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300753
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300754 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +0300755 control |= __set_ctrl_poll(chan);
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300756
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300757 skb = bt_skb_alloc(count, GFP_ATOMIC);
758 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300759 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300760
761 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300762 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300763 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300764
765 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300766
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300767 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300768 u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
769 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300770 }
771
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200772 skb->priority = HCI_PRIO_MAX;
773 l2cap_do_send(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300774}
775
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300776static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300777{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300778 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300779 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300780 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300781 } else
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300782 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300783
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300784 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300785
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300786 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300787}
788
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300789static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300790{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300791 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300792}
793
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +0200794static void l2cap_send_conn_req(struct l2cap_chan *chan)
795{
796 struct l2cap_conn *conn = chan->conn;
797 struct l2cap_conn_req req;
798
799 req.scid = cpu_to_le16(chan->scid);
800 req.psm = chan->psm;
801
802 chan->ident = l2cap_get_ident(conn);
803
804 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
805
806 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
807}
808
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300809static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200810{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300811 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200812
813 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100814 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
815 return;
816
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200817 if (l2cap_chan_check_security(chan) &&
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +0200818 __l2cap_no_conn_pending(chan))
819 l2cap_send_conn_req(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200820 } else {
821 struct l2cap_info_req req;
822 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
823
824 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
825 conn->info_ident = l2cap_get_ident(conn);
826
Marcel Holtmannba13ccd2012-03-01 14:25:33 -0800827 schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200828
829 l2cap_send_cmd(conn, conn->info_ident,
830 L2CAP_INFO_REQ, sizeof(req), &req);
831 }
832}
833
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300834static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
835{
836 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300837 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300838 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
839
840 switch (mode) {
841 case L2CAP_MODE_ERTM:
842 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
843 case L2CAP_MODE_STREAMING:
844 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
845 default:
846 return 0x00;
847 }
848}
849
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300850static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300851{
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200852 struct sock *sk = chan->sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300853 struct l2cap_disconn_req req;
854
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300855 if (!conn)
856 return;
857
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300858 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300859 __clear_retrans_timer(chan);
860 __clear_monitor_timer(chan);
861 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300862 }
863
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300864 req.dcid = cpu_to_le16(chan->dcid);
865 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300866 l2cap_send_cmd(conn, l2cap_get_ident(conn),
867 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300868
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200869 lock_sock(sk);
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200870 __l2cap_state_change(chan, BT_DISCONN);
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +0200871 __l2cap_chan_set_err(chan, err);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200872 release_sock(sk);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300873}
874
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200876static void l2cap_conn_start(struct l2cap_conn *conn)
877{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200878 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200879
880 BT_DBG("conn %p", conn);
881
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200882 mutex_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200883
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200884 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300885 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300886
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200887 l2cap_chan_lock(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200888
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300889 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200890 l2cap_chan_unlock(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200891 continue;
892 }
893
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300894 if (chan->state == BT_CONNECT) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200895 if (!l2cap_chan_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300896 !__l2cap_no_conn_pending(chan)) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200897 l2cap_chan_unlock(chan);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300898 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200899 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300900
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300901 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
902 && test_bit(CONF_STATE2_DEVICE,
903 &chan->conf_state)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300904 l2cap_chan_close(chan, ECONNRESET);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200905 l2cap_chan_unlock(chan);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300906 continue;
907 }
908
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +0200909 l2cap_send_conn_req(chan);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300910
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300911 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200912 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300913 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300914 rsp.scid = cpu_to_le16(chan->dcid);
915 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200916
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200917 if (l2cap_chan_check_security(chan)) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200918 lock_sock(sk);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100919 if (bt_sk(sk)->defer_setup) {
920 struct sock *parent = bt_sk(sk)->parent;
921 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
922 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +0000923 if (parent)
924 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100925
926 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200927 __l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100928 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
929 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
930 }
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200931 release_sock(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200932 } else {
933 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
934 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
935 }
936
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300937 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
938 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300939
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300940 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300941 rsp.result != L2CAP_CR_SUCCESS) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200942 l2cap_chan_unlock(chan);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300943 continue;
944 }
945
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300946 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300947 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300948 l2cap_build_conf_req(chan, buf), buf);
949 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200950 }
951
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200952 l2cap_chan_unlock(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200953 }
954
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200955 mutex_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200956}
957
Ville Tervob62f3282011-02-10 22:38:50 -0300958/* Find socket with cid and source bdaddr.
959 * Returns closest match, locked.
960 */
Andrei Emeltchenkod9b88702012-03-12 12:13:08 +0200961static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
962 bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300963{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300964 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300965
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300966 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300967
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300968 list_for_each_entry(c, &chan_list, global_l) {
969 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300970
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300971 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300972 continue;
973
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300974 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300975 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300976 if (!bacmp(&bt_sk(sk)->src, src)) {
977 read_unlock(&chan_list_lock);
978 return c;
979 }
Ville Tervob62f3282011-02-10 22:38:50 -0300980
981 /* Closest match */
982 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300983 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300984 }
985 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300986
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300987 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300988
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300989 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300990}
991
992static void l2cap_le_conn_ready(struct l2cap_conn *conn)
993{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300994 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300995 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300996
997 BT_DBG("");
998
999 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001000 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -03001001 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001002 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -03001003 return;
1004
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001005 parent = pchan->sk;
1006
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001007 lock_sock(parent);
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -03001008
Ville Tervob62f3282011-02-10 22:38:50 -03001009 /* Check for backlog size */
1010 if (sk_acceptq_is_full(parent)) {
1011 BT_DBG("backlog full %d", parent->sk_ack_backlog);
1012 goto clean;
1013 }
1014
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03001015 chan = pchan->ops->new_connection(pchan->data);
1016 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -03001017 goto clean;
1018
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03001019 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001020
Ville Tervob62f3282011-02-10 22:38:50 -03001021 hci_conn_hold(conn->hcon);
1022
Ville Tervob62f3282011-02-10 22:38:50 -03001023 bacpy(&bt_sk(sk)->src, conn->src);
1024 bacpy(&bt_sk(sk)->dst, conn->dst);
1025
Gustavo F. Padovand1010242011-03-25 00:39:48 -03001026 bt_accept_enqueue(parent, sk);
1027
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001028 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001029
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001030 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -03001031
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001032 __l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -03001033 parent->sk_data_ready(parent, 0);
1034
Ville Tervob62f3282011-02-10 22:38:50 -03001035clean:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001036 release_sock(parent);
Ville Tervob62f3282011-02-10 22:38:50 -03001037}
1038
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02001039static void l2cap_chan_ready(struct l2cap_chan *chan)
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03001040{
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02001041 struct sock *sk = chan->sk;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001042 struct sock *parent;
1043
1044 lock_sock(sk);
1045
1046 parent = bt_sk(sk)->parent;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03001047
1048 BT_DBG("sk %p, parent %p", sk, parent);
1049
1050 chan->conf_state = 0;
1051 __clear_chan_timer(chan);
1052
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001053 __l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03001054 sk->sk_state_change(sk);
1055
1056 if (parent)
1057 parent->sk_data_ready(parent, 0);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001058
1059 release_sock(sk);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03001060}
1061
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001062static void l2cap_conn_ready(struct l2cap_conn *conn)
1063{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001064 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001065
1066 BT_DBG("conn %p", conn);
1067
Ville Tervob62f3282011-02-10 22:38:50 -03001068 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
1069 l2cap_le_conn_ready(conn);
1070
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03001071 if (conn->hcon->out && conn->hcon->type == LE_LINK)
1072 smp_conn_security(conn, conn->hcon->pending_sec_level);
1073
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001074 mutex_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001075
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001076 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001077
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001078 l2cap_chan_lock(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001079
Vinicius Costa Gomes63128452011-06-17 22:46:26 -03001080 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -03001081 if (smp_conn_security(conn, chan->sec_level))
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02001082 l2cap_chan_ready(chan);
Ville Tervoacd7d372011-02-10 22:38:49 -03001083
Vinicius Costa Gomes63128452011-06-17 22:46:26 -03001084 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001085 struct sock *sk = chan->sk;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001086 __clear_chan_timer(chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001087 lock_sock(sk);
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001088 __l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001089 sk->sk_state_change(sk);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001090 release_sock(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -03001091
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001092 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001093 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001094
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001095 l2cap_chan_unlock(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001096 }
1097
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001098 mutex_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001099}
1100
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001101/* Notify sockets that we cannot guaranty reliability anymore */
1102static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
1103{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001104 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001105
1106 BT_DBG("conn %p", conn);
1107
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001108 mutex_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001109
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001110 list_for_each_entry(chan, &conn->chan_l, list) {
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +03001111 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +02001112 __l2cap_chan_set_err(chan, err);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001113 }
1114
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001115 mutex_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001116}
1117
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -02001118static void l2cap_info_timeout(struct work_struct *work)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001119{
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -02001120 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02001121 info_timer.work);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001122
Marcel Holtmann984947d2009-02-06 23:35:19 +01001123 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01001124 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01001125
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001126 l2cap_conn_start(conn);
1127}
1128
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001129static void l2cap_conn_del(struct hci_conn *hcon, int err)
1130{
1131 struct l2cap_conn *conn = hcon->l2cap_data;
1132 struct l2cap_chan *chan, *l;
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001133
1134 if (!conn)
1135 return;
1136
1137 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
1138
1139 kfree_skb(conn->rx_skb);
1140
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001141 mutex_lock(&conn->chan_lock);
1142
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001143 /* Kill channels */
1144 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001145 l2cap_chan_lock(chan);
1146
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001147 l2cap_chan_del(chan, err);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001148
1149 l2cap_chan_unlock(chan);
1150
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001151 chan->ops->close(chan->data);
1152 }
1153
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001154 mutex_unlock(&conn->chan_lock);
1155
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001156 hci_chan_del(conn->hchan);
1157
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001158 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
Ulisses Furquim127074b2012-01-30 18:26:29 -02001159 cancel_delayed_work_sync(&conn->info_timer);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001160
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001161 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
Ulisses Furquim127074b2012-01-30 18:26:29 -02001162 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001163 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001164 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001165
1166 hcon->l2cap_data = NULL;
1167 kfree(conn);
1168}
1169
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001170static void security_timeout(struct work_struct *work)
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001171{
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001172 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1173 security_timer.work);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001174
1175 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1176}
1177
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1179{
Marcel Holtmann01394182006-07-03 10:02:46 +02001180 struct l2cap_conn *conn = hcon->l2cap_data;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001181 struct hci_chan *hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182
Marcel Holtmann01394182006-07-03 10:02:46 +02001183 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 return conn;
1185
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001186 hchan = hci_chan_create(hcon);
1187 if (!hchan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001190 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1191 if (!conn) {
1192 hci_chan_del(hchan);
1193 return NULL;
1194 }
1195
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 hcon->l2cap_data = conn;
1197 conn->hcon = hcon;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001198 conn->hchan = hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001200 BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
Marcel Holtmann01394182006-07-03 10:02:46 +02001201
Ville Tervoacd7d372011-02-10 22:38:49 -03001202 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1203 conn->mtu = hcon->hdev->le_mtu;
1204 else
1205 conn->mtu = hcon->hdev->acl_mtu;
1206
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 conn->src = &hcon->hdev->bdaddr;
1208 conn->dst = &hcon->dst;
1209
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001210 conn->feat_mask = 0;
1211
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 spin_lock_init(&conn->lock);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001213 mutex_init(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001214
1215 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001217 if (hcon->type == LE_LINK)
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001218 INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001219 else
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02001220 INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
Dave Young45054dc2009-10-18 20:28:30 +00001221
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001222 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01001223
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 return conn;
1225}
1226
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228
1229/* Find socket with psm and source bdaddr.
1230 * Returns closest match.
1231 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001232static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001234 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001236 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001237
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001238 list_for_each_entry(c, &chan_list, global_l) {
1239 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001240
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001241 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 continue;
1243
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001244 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001246 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001247 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001248 return c;
1249 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250
1251 /* Closest match */
1252 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001253 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 }
1255 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001257 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001258
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001259 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260}
1261
Johan Hedbergcbe8fed2012-01-08 22:51:16 +02001262int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001264 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 bdaddr_t *src = &bt_sk(sk)->src;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 struct l2cap_conn *conn;
1267 struct hci_conn *hcon;
1268 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001269 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001270 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001272 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Andrei Emeltchenko097db762012-03-09 14:16:17 +02001273 __le16_to_cpu(chan->psm));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001275 hdev = hci_get_route(dst, src);
1276 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 return -EHOSTUNREACH;
1278
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001279 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001281 l2cap_chan_lock(chan);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001282
1283 /* PSM must be odd and lsb of upper byte must be 0 */
1284 if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
1285 chan->chan_type != L2CAP_CHAN_RAW) {
1286 err = -EINVAL;
1287 goto done;
1288 }
1289
1290 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
1291 err = -EINVAL;
1292 goto done;
1293 }
1294
1295 switch (chan->mode) {
1296 case L2CAP_MODE_BASIC:
1297 break;
1298 case L2CAP_MODE_ERTM:
1299 case L2CAP_MODE_STREAMING:
1300 if (!disable_ertm)
1301 break;
1302 /* fall through */
1303 default:
1304 err = -ENOTSUPP;
1305 goto done;
1306 }
1307
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001308 lock_sock(sk);
1309
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001310 switch (sk->sk_state) {
1311 case BT_CONNECT:
1312 case BT_CONNECT2:
1313 case BT_CONFIG:
1314 /* Already connecting */
1315 err = 0;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001316 release_sock(sk);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001317 goto done;
1318
1319 case BT_CONNECTED:
1320 /* Already connected */
1321 err = -EISCONN;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001322 release_sock(sk);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001323 goto done;
1324
1325 case BT_OPEN:
1326 case BT_BOUND:
1327 /* Can connect */
1328 break;
1329
1330 default:
1331 err = -EBADFD;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001332 release_sock(sk);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001333 goto done;
1334 }
1335
1336 /* Set destination address and psm */
Gustavo F. Padovan9219b2a2012-01-02 20:08:04 -02001337 bacpy(&bt_sk(sk)->dst, dst);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001338
1339 release_sock(sk);
1340
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001341 chan->psm = psm;
1342 chan->dcid = cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001344 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001345
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001346 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001347 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001348 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001349 else
1350 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001351 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001352
Ville Tervo30e76272011-02-22 16:10:53 -03001353 if (IS_ERR(hcon)) {
1354 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001356 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357
1358 conn = l2cap_conn_add(hcon, 0);
1359 if (!conn) {
1360 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001361 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 goto done;
1363 }
1364
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 /* Update source addr of the socket */
1366 bacpy(src, conn->src);
1367
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001368 l2cap_chan_unlock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001369 l2cap_chan_add(conn, chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001370 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001371
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001372 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001373 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374
1375 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001376 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001377 __clear_chan_timer(chan);
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001378 if (l2cap_chan_check_security(chan))
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001379 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001380 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001381 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 }
1383
Ville Tervo30e76272011-02-22 16:10:53 -03001384 err = 0;
1385
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386done:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001387 l2cap_chan_unlock(chan);
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001388 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 hci_dev_put(hdev);
1390 return err;
1391}
1392
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001393int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001394{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001395 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001396 DECLARE_WAITQUEUE(wait, current);
1397 int err = 0;
1398 int timeo = HZ/5;
1399
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001400 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001401 set_current_state(TASK_INTERRUPTIBLE);
1402 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001403 if (!timeo)
1404 timeo = HZ/5;
1405
1406 if (signal_pending(current)) {
1407 err = sock_intr_errno(timeo);
1408 break;
1409 }
1410
1411 release_sock(sk);
1412 timeo = schedule_timeout(timeo);
1413 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001414 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001415
1416 err = sock_error(sk);
1417 if (err)
1418 break;
1419 }
1420 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001421 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001422 return err;
1423}
1424
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001425static void l2cap_monitor_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001426{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001427 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1428 monitor_timer.work);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001429
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001430 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001431
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001432 l2cap_chan_lock(chan);
1433
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001434 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001435 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001436 l2cap_chan_unlock(chan);
Andrei Emeltchenko8d7e1c72012-03-23 09:42:15 +02001437 l2cap_chan_put(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001438 return;
1439 }
1440
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001441 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001442 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001443
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001444 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001445 l2cap_chan_unlock(chan);
Andrei Emeltchenko8d7e1c72012-03-23 09:42:15 +02001446 l2cap_chan_put(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001447}
1448
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001449static void l2cap_retrans_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001450{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001451 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1452 retrans_timer.work);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001453
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001454 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001455
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001456 l2cap_chan_lock(chan);
1457
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001458 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001459 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001460
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001461 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001462
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001463 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001464
1465 l2cap_chan_unlock(chan);
Andrei Emeltchenko8d7e1c72012-03-23 09:42:15 +02001466 l2cap_chan_put(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001467}
1468
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001469static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001470{
1471 struct sk_buff *skb;
1472
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001473 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001474 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001475 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001476 break;
1477
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001478 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001479 kfree_skb(skb);
1480
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001481 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001482 }
1483
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001484 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001485 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001486}
1487
Szymon Janc67c9e842011-07-28 16:24:33 +02001488static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001489{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001490 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001491 u32 control;
1492 u16 fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001493
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001494 while ((skb = skb_dequeue(&chan->tx_q))) {
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001495 control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001496 control |= __set_txseq(chan, chan->next_tx_seq);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001497 __put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001498
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001499 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001500 fcs = crc16(0, (u8 *)skb->data,
1501 skb->len - L2CAP_FCS_SIZE);
1502 put_unaligned_le16(fcs,
1503 skb->data + skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001504 }
1505
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001506 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001507
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001508 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001509 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001510}
1511
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001512static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001513{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001514 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001515 u16 fcs;
1516 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001517
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001518 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001519 if (!skb)
1520 return;
1521
Szymon Jancd1726b62011-11-16 09:32:20 +01001522 while (bt_cb(skb)->tx_seq != tx_seq) {
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001523 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001524 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001525
Szymon Jancd1726b62011-11-16 09:32:20 +01001526 skb = skb_queue_next(&chan->tx_q, skb);
1527 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001528
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001529 if (chan->remote_max_tx &&
1530 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001531 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001532 return;
1533 }
1534
1535 tx_skb = skb_clone(skb, GFP_ATOMIC);
1536 bt_cb(skb)->retries++;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001537
1538 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001539 control &= __get_sar_mask(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001540
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001541 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001542 control |= __set_ctrl_final(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001543
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001544 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001545 control |= __set_txseq(chan, tx_seq);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001546
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001547 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001548
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001549 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001550 fcs = crc16(0, (u8 *)tx_skb->data,
1551 tx_skb->len - L2CAP_FCS_SIZE);
1552 put_unaligned_le16(fcs,
1553 tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001554 }
1555
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001556 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001557}
1558
Szymon Janc67c9e842011-07-28 16:24:33 +02001559static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001560{
1561 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001562 u16 fcs;
1563 u32 control;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001564 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001565
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001566 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001567 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001568
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001569 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001570
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001571 if (chan->remote_max_tx &&
1572 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001573 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001574 break;
1575 }
1576
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001577 tx_skb = skb_clone(skb, GFP_ATOMIC);
1578
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001579 bt_cb(skb)->retries++;
1580
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001581 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001582 control &= __get_sar_mask(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001583
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001584 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001585 control |= __set_ctrl_final(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001586
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001587 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001588 control |= __set_txseq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001589
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001590 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001591
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001592 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001593 fcs = crc16(0, (u8 *)skb->data,
1594 tx_skb->len - L2CAP_FCS_SIZE);
1595 put_unaligned_le16(fcs, skb->data +
1596 tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001597 }
1598
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001599 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001600
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001601 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001602
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001603 bt_cb(skb)->tx_seq = chan->next_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001604
1605 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001606
Szymon Janc8ed7a0a2012-02-07 15:43:01 +01001607 if (bt_cb(skb)->retries == 1) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001608 chan->unacked_frames++;
Szymon Janc930fa4a2012-02-07 15:43:02 +01001609
1610 if (!nsent++)
1611 __clear_ack_timer(chan);
Szymon Janc8ed7a0a2012-02-07 15:43:01 +01001612 }
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301613
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001614 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001615
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001616 if (skb_queue_is_last(&chan->tx_q, skb))
1617 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001618 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001619 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001620 }
1621
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001622 return nsent;
1623}
1624
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001625static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001626{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001627 int ret;
1628
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001629 if (!skb_queue_empty(&chan->tx_q))
1630 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001631
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001632 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001633 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001634 return ret;
1635}
1636
Szymon Jancb17e73b2012-01-11 10:59:47 +01001637static void __l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001638{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001639 u32 control = 0;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001640
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001641 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001642
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001643 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001644 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001645 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001646 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001647 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001648 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001649
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001650 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001651 return;
1652
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001653 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001654 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001655}
1656
Szymon Jancb17e73b2012-01-11 10:59:47 +01001657static void l2cap_send_ack(struct l2cap_chan *chan)
1658{
1659 __clear_ack_timer(chan);
1660 __l2cap_send_ack(chan);
1661}
1662
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001663static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001664{
1665 struct srej_list *tail;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001666 u32 control;
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001667
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001668 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001669 control |= __set_ctrl_final(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001670
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001671 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001672 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001673
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001674 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001675}
1676
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001677static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
1678 struct msghdr *msg, int len,
1679 int count, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680{
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001681 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001682 struct sk_buff **frag;
Gustavo Padovan90338942012-04-06 20:15:47 -03001683 int sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001685 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001686 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687
1688 sent += count;
1689 len -= count;
1690
1691 /* Continuation fragments (no L2CAP header) */
1692 frag = &skb_shinfo(skb)->frag_list;
1693 while (len) {
1694 count = min_t(unsigned int, conn->mtu, len);
1695
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001696 *frag = chan->ops->alloc_skb(chan, count,
Gustavo Padovan90338942012-04-06 20:15:47 -03001697 msg->msg_flags & MSG_DONTWAIT);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001698
Gustavo Padovan90338942012-04-06 20:15:47 -03001699 if (IS_ERR(*frag))
1700 return PTR_ERR(*frag);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001701 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1702 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001704 (*frag)->priority = skb->priority;
1705
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 sent += count;
1707 len -= count;
1708
1709 frag = &(*frag)->next;
1710 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711
1712 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001713}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001715static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
1716 struct msghdr *msg, size_t len,
1717 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001718{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001719 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001720 struct sk_buff *skb;
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001721 int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001722 struct l2cap_hdr *lh;
1723
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001724 BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001725
1726 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001727
1728 skb = chan->ops->alloc_skb(chan, count + hlen,
Gustavo Padovan90338942012-04-06 20:15:47 -03001729 msg->msg_flags & MSG_DONTWAIT);
1730 if (IS_ERR(skb))
1731 return skb;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001732
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001733 skb->priority = priority;
1734
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001735 /* Create L2CAP header */
1736 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001737 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001738 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko097db762012-03-09 14:16:17 +02001739 put_unaligned(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001740
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001741 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001742 if (unlikely(err < 0)) {
1743 kfree_skb(skb);
1744 return ERR_PTR(err);
1745 }
1746 return skb;
1747}
1748
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001749static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
1750 struct msghdr *msg, size_t len,
1751 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001752{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001753 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001754 struct sk_buff *skb;
1755 int err, count, hlen = L2CAP_HDR_SIZE;
1756 struct l2cap_hdr *lh;
1757
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001758 BT_DBG("chan %p len %d", chan, (int)len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001759
1760 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001761
1762 skb = chan->ops->alloc_skb(chan, count + hlen,
Gustavo Padovan90338942012-04-06 20:15:47 -03001763 msg->msg_flags & MSG_DONTWAIT);
1764 if (IS_ERR(skb))
1765 return skb;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001766
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001767 skb->priority = priority;
1768
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001769 /* Create L2CAP header */
1770 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001771 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001772 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1773
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001774 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001775 if (unlikely(err < 0)) {
1776 kfree_skb(skb);
1777 return ERR_PTR(err);
1778 }
1779 return skb;
1780}
1781
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001782static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1783 struct msghdr *msg, size_t len,
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001784 u32 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001785{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001786 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001787 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001788 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001789 struct l2cap_hdr *lh;
1790
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001791 BT_DBG("chan %p len %d", chan, (int)len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001792
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001793 if (!conn)
1794 return ERR_PTR(-ENOTCONN);
1795
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001796 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1797 hlen = L2CAP_EXT_HDR_SIZE;
1798 else
1799 hlen = L2CAP_ENH_HDR_SIZE;
1800
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001801 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001802 hlen += L2CAP_SDULEN_SIZE;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001803
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001804 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001805 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001806
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001807 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001808
1809 skb = chan->ops->alloc_skb(chan, count + hlen,
Gustavo Padovan90338942012-04-06 20:15:47 -03001810 msg->msg_flags & MSG_DONTWAIT);
1811 if (IS_ERR(skb))
1812 return skb;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001813
1814 /* Create L2CAP header */
1815 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001816 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001817 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001818
1819 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
1820
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001821 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001822 put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001823
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001824 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001825 if (unlikely(err < 0)) {
1826 kfree_skb(skb);
1827 return ERR_PTR(err);
1828 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001829
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001830 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001831 put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001832
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001833 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001834 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835}
1836
Szymon Janc67c9e842011-07-28 16:24:33 +02001837static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001838{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001839 struct sk_buff *skb;
1840 struct sk_buff_head sar_queue;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001841 u32 control;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001842 size_t size = 0;
1843
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001844 skb_queue_head_init(&sar_queue);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001845 control = __set_ctrl_sar(chan, L2CAP_SAR_START);
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001846 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001847 if (IS_ERR(skb))
1848 return PTR_ERR(skb);
1849
1850 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001851 len -= chan->remote_mps;
1852 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001853
1854 while (len > 0) {
1855 size_t buflen;
1856
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001857 if (len > chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001858 control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001859 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001860 } else {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001861 control = __set_ctrl_sar(chan, L2CAP_SAR_END);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001862 buflen = len;
1863 }
1864
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001865 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001866 if (IS_ERR(skb)) {
1867 skb_queue_purge(&sar_queue);
1868 return PTR_ERR(skb);
1869 }
1870
1871 __skb_queue_tail(&sar_queue, skb);
1872 len -= buflen;
1873 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001874 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001875 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1876 if (chan->tx_send_head == NULL)
1877 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001878
1879 return size;
1880}
1881
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001882int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
1883 u32 priority)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001884{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001885 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001886 u32 control;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001887 int err;
1888
1889 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001890 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001891 skb = l2cap_create_connless_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001892 if (IS_ERR(skb))
1893 return PTR_ERR(skb);
1894
1895 l2cap_do_send(chan, skb);
1896 return len;
1897 }
1898
1899 switch (chan->mode) {
1900 case L2CAP_MODE_BASIC:
1901 /* Check outgoing MTU */
1902 if (len > chan->omtu)
1903 return -EMSGSIZE;
1904
1905 /* Create a basic PDU */
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001906 skb = l2cap_create_basic_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001907 if (IS_ERR(skb))
1908 return PTR_ERR(skb);
1909
1910 l2cap_do_send(chan, skb);
1911 err = len;
1912 break;
1913
1914 case L2CAP_MODE_ERTM:
1915 case L2CAP_MODE_STREAMING:
1916 /* Entire SDU fits into one PDU */
1917 if (len <= chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001918 control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001919 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1920 0);
1921 if (IS_ERR(skb))
1922 return PTR_ERR(skb);
1923
1924 __skb_queue_tail(&chan->tx_q, skb);
1925
1926 if (chan->tx_send_head == NULL)
1927 chan->tx_send_head = skb;
1928
1929 } else {
1930 /* Segment SDU into multiples PDUs */
1931 err = l2cap_sar_segment_sdu(chan, msg, len);
1932 if (err < 0)
1933 return err;
1934 }
1935
1936 if (chan->mode == L2CAP_MODE_STREAMING) {
1937 l2cap_streaming_send(chan);
1938 err = len;
1939 break;
1940 }
1941
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001942 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1943 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001944 err = len;
1945 break;
1946 }
1947
1948 err = l2cap_ertm_send(chan);
1949 if (err >= 0)
1950 err = len;
1951
1952 break;
1953
1954 default:
1955 BT_DBG("bad state %1.1x", chan->mode);
1956 err = -EBADFD;
1957 }
1958
1959 return err;
1960}
1961
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962/* Copy frame to all raw sockets on that connection */
1963static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1964{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001966 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967
1968 BT_DBG("conn %p", conn);
1969
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001970 mutex_lock(&conn->chan_lock);
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001971
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001972 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001973 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001974 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975 continue;
1976
1977 /* Don't send frame to the socket it came from */
1978 if (skb->sk == sk)
1979 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001980 nskb = skb_clone(skb, GFP_ATOMIC);
1981 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982 continue;
1983
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001984 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 kfree_skb(nskb);
1986 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001987
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001988 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989}
1990
1991/* ---- L2CAP signalling commands ---- */
1992static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1993 u8 code, u8 ident, u16 dlen, void *data)
1994{
1995 struct sk_buff *skb, **frag;
1996 struct l2cap_cmd_hdr *cmd;
1997 struct l2cap_hdr *lh;
1998 int len, count;
1999
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002000 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
2001 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002
2003 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
2004 count = min_t(unsigned int, conn->mtu, len);
2005
2006 skb = bt_skb_alloc(count, GFP_ATOMIC);
2007 if (!skb)
2008 return NULL;
2009
2010 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002011 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002012
2013 if (conn->hcon->type == LE_LINK)
2014 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
2015 else
2016 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017
2018 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
2019 cmd->code = code;
2020 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002021 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022
2023 if (dlen) {
2024 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
2025 memcpy(skb_put(skb, count), data, count);
2026 data += count;
2027 }
2028
2029 len -= skb->len;
2030
2031 /* Continuation fragments (no L2CAP header) */
2032 frag = &skb_shinfo(skb)->frag_list;
2033 while (len) {
2034 count = min_t(unsigned int, conn->mtu, len);
2035
2036 *frag = bt_skb_alloc(count, GFP_ATOMIC);
2037 if (!*frag)
2038 goto fail;
2039
2040 memcpy(skb_put(*frag, count), data, count);
2041
2042 len -= count;
2043 data += count;
2044
2045 frag = &(*frag)->next;
2046 }
2047
2048 return skb;
2049
2050fail:
2051 kfree_skb(skb);
2052 return NULL;
2053}
2054
2055static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
2056{
2057 struct l2cap_conf_opt *opt = *ptr;
2058 int len;
2059
2060 len = L2CAP_CONF_OPT_SIZE + opt->len;
2061 *ptr += len;
2062
2063 *type = opt->type;
2064 *olen = opt->len;
2065
2066 switch (opt->len) {
2067 case 1:
2068 *val = *((u8 *) opt->val);
2069 break;
2070
2071 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04002072 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073 break;
2074
2075 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04002076 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 break;
2078
2079 default:
2080 *val = (unsigned long) opt->val;
2081 break;
2082 }
2083
2084 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
2085 return len;
2086}
2087
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
2089{
2090 struct l2cap_conf_opt *opt = *ptr;
2091
2092 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
2093
2094 opt->type = type;
2095 opt->len = len;
2096
2097 switch (len) {
2098 case 1:
2099 *((u8 *) opt->val) = val;
2100 break;
2101
2102 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02002103 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 break;
2105
2106 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02002107 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 break;
2109
2110 default:
2111 memcpy(opt->val, (void *) val, len);
2112 break;
2113 }
2114
2115 *ptr += L2CAP_CONF_OPT_SIZE + len;
2116}
2117
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002118static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
2119{
2120 struct l2cap_conf_efs efs;
2121
Szymon Janc1ec918c2011-11-16 09:32:21 +01002122 switch (chan->mode) {
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002123 case L2CAP_MODE_ERTM:
2124 efs.id = chan->local_id;
2125 efs.stype = chan->local_stype;
2126 efs.msdu = cpu_to_le16(chan->local_msdu);
2127 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
2128 efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
2129 efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
2130 break;
2131
2132 case L2CAP_MODE_STREAMING:
2133 efs.id = 1;
2134 efs.stype = L2CAP_SERV_BESTEFFORT;
2135 efs.msdu = cpu_to_le16(chan->local_msdu);
2136 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
2137 efs.acc_lat = 0;
2138 efs.flush_to = 0;
2139 break;
2140
2141 default:
2142 return;
2143 }
2144
2145 l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
2146 (unsigned long) &efs);
2147}
2148
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002149static void l2cap_ack_timeout(struct work_struct *work)
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002150{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002151 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2152 ack_timer.work);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002153
Gustavo F. Padovan2fb9b3d2011-12-22 16:56:05 -02002154 BT_DBG("chan %p", chan);
2155
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02002156 l2cap_chan_lock(chan);
2157
Szymon Jancb17e73b2012-01-11 10:59:47 +01002158 __l2cap_send_ack(chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02002159
2160 l2cap_chan_unlock(chan);
Szymon Janc09bfb2e2012-01-11 10:59:49 +01002161
2162 l2cap_chan_put(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002163}
2164
Mat Martineau3c588192012-04-11 10:48:42 -07002165static inline int l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002166{
Mat Martineau3c588192012-04-11 10:48:42 -07002167 int err;
2168
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002169 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002170 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002171 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002172 chan->num_acked = 0;
2173 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002174
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002175 INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2176 INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2177 INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002178
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002179 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002180
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03002181 INIT_LIST_HEAD(&chan->srej_l);
Mat Martineau3c588192012-04-11 10:48:42 -07002182 err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
2183 if (err < 0)
2184 return err;
2185
2186 return l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002187}
2188
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002189static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2190{
2191 switch (mode) {
2192 case L2CAP_MODE_STREAMING:
2193 case L2CAP_MODE_ERTM:
2194 if (l2cap_mode_supported(mode, remote_feat_mask))
2195 return mode;
2196 /* fall through */
2197 default:
2198 return L2CAP_MODE_BASIC;
2199 }
2200}
2201
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002202static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
2203{
2204 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
2205}
2206
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002207static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2208{
2209 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2210}
2211
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002212static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
2213{
2214 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002215 __l2cap_ews_supported(chan)) {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002216 /* use extended control field */
2217 set_bit(FLAG_EXT_CTRL, &chan->flags);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002218 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2219 } else {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002220 chan->tx_win = min_t(u16, chan->tx_win,
2221 L2CAP_DEFAULT_TX_WINDOW);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002222 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2223 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002224}
2225
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002226static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002229 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 void *ptr = req->data;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002231 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002233 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002235 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002236 goto done;
2237
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002238 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002239 case L2CAP_MODE_STREAMING:
2240 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002241 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002242 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002243
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002244 if (__l2cap_efs_supported(chan))
2245 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2246
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002247 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002248 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002249 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002250 break;
2251 }
2252
2253done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002254 if (chan->imtu != L2CAP_DEFAULT_MTU)
2255 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002256
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002257 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002258 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002259 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2260 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002261 break;
2262
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002263 rfc.mode = L2CAP_MODE_BASIC;
2264 rfc.txwin_size = 0;
2265 rfc.max_transmit = 0;
2266 rfc.retrans_timeout = 0;
2267 rfc.monitor_timeout = 0;
2268 rfc.max_pdu_size = 0;
2269
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002270 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2271 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002272 break;
2273
2274 case L2CAP_MODE_ERTM:
2275 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002276 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002277 rfc.retrans_timeout = 0;
2278 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002279
2280 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2281 L2CAP_EXT_HDR_SIZE -
2282 L2CAP_SDULEN_SIZE -
2283 L2CAP_FCS_SIZE);
2284 rfc.max_pdu_size = cpu_to_le16(size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002285
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002286 l2cap_txwin_setup(chan);
2287
2288 rfc.txwin_size = min_t(u16, chan->tx_win,
2289 L2CAP_DEFAULT_TX_WINDOW);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002290
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002291 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2292 (unsigned long) &rfc);
2293
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002294 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2295 l2cap_add_opt_efs(&ptr, chan);
2296
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002297 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002298 break;
2299
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002300 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002301 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002302 chan->fcs = L2CAP_FCS_NONE;
2303 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002304 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002305
2306 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2307 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2308 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002309 break;
2310
2311 case L2CAP_MODE_STREAMING:
2312 rfc.mode = L2CAP_MODE_STREAMING;
2313 rfc.txwin_size = 0;
2314 rfc.max_transmit = 0;
2315 rfc.retrans_timeout = 0;
2316 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002317
2318 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2319 L2CAP_EXT_HDR_SIZE -
2320 L2CAP_SDULEN_SIZE -
2321 L2CAP_FCS_SIZE);
2322 rfc.max_pdu_size = cpu_to_le16(size);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002323
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002324 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2325 (unsigned long) &rfc);
2326
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002327 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2328 l2cap_add_opt_efs(&ptr, chan);
2329
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002330 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002331 break;
2332
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002333 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002334 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002335 chan->fcs = L2CAP_FCS_NONE;
2336 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002337 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002338 break;
2339 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002341 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002342 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343
2344 return ptr - data;
2345}
2346
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002347static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002349 struct l2cap_conf_rsp *rsp = data;
2350 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002351 void *req = chan->conf_req;
2352 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002353 int type, hint, olen;
2354 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002355 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002356 struct l2cap_conf_efs efs;
2357 u8 remote_efs = 0;
Marcel Holtmann861d6882007-10-20 13:37:06 +02002358 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002359 u16 result = L2CAP_CONF_SUCCESS;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002360 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002362 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002363
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002364 while (len >= L2CAP_CONF_OPT_SIZE) {
2365 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002367 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002368 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002369
2370 switch (type) {
2371 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002372 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002373 break;
2374
2375 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002376 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002377 break;
2378
2379 case L2CAP_CONF_QOS:
2380 break;
2381
Marcel Holtmann6464f352007-10-20 13:39:51 +02002382 case L2CAP_CONF_RFC:
2383 if (olen == sizeof(rfc))
2384 memcpy(&rfc, (void *) val, olen);
2385 break;
2386
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002387 case L2CAP_CONF_FCS:
2388 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002389 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002390 break;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002391
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002392 case L2CAP_CONF_EFS:
2393 remote_efs = 1;
2394 if (olen == sizeof(efs))
2395 memcpy(&efs, (void *) val, olen);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002396 break;
2397
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002398 case L2CAP_CONF_EWS:
2399 if (!enable_hs)
2400 return -ECONNREFUSED;
2401
2402 set_bit(FLAG_EXT_CTRL, &chan->flags);
2403 set_bit(CONF_EWS_RECV, &chan->conf_state);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002404 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002405 chan->remote_tx_win = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002406 break;
2407
2408 default:
2409 if (hint)
2410 break;
2411
2412 result = L2CAP_CONF_UNKNOWN;
2413 *((u8 *) ptr++) = type;
2414 break;
2415 }
2416 }
2417
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002418 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002419 goto done;
2420
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002421 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002422 case L2CAP_MODE_STREAMING:
2423 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002424 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002425 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002426 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002427 break;
2428 }
2429
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002430 if (remote_efs) {
2431 if (__l2cap_efs_supported(chan))
2432 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2433 else
2434 return -ECONNREFUSED;
2435 }
2436
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002437 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002438 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002439
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002440 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002441 }
2442
2443done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002444 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002445 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002446 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002447
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002448 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002449 return -ECONNREFUSED;
2450
2451 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2452 sizeof(rfc), (unsigned long) &rfc);
2453 }
2454
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002455 if (result == L2CAP_CONF_SUCCESS) {
2456 /* Configure output options and let the other side know
2457 * which ones we don't like. */
2458
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002459 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2460 result = L2CAP_CONF_UNACCEPT;
2461 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002462 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002463 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002464 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002465 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002466
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002467 if (remote_efs) {
2468 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2469 efs.stype != L2CAP_SERV_NOTRAFIC &&
2470 efs.stype != chan->local_stype) {
2471
2472 result = L2CAP_CONF_UNACCEPT;
2473
2474 if (chan->num_conf_req >= 1)
2475 return -ECONNREFUSED;
2476
2477 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002478 sizeof(efs),
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002479 (unsigned long) &efs);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002480 } else {
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002481 /* Send PENDING Conf Rsp */
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002482 result = L2CAP_CONF_PENDING;
2483 set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002484 }
2485 }
2486
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002487 switch (rfc.mode) {
2488 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002489 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002490 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002491 break;
2492
2493 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002494 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2495 chan->remote_tx_win = rfc.txwin_size;
2496 else
2497 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2498
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002499 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002500
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002501 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2502 chan->conn->mtu -
2503 L2CAP_EXT_HDR_SIZE -
2504 L2CAP_SDULEN_SIZE -
2505 L2CAP_FCS_SIZE);
2506 rfc.max_pdu_size = cpu_to_le16(size);
2507 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002508
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002509 rfc.retrans_timeout =
Andrei Emeltchenko4fd21a82012-03-12 12:13:10 +02002510 __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002511 rfc.monitor_timeout =
Andrei Emeltchenko4fd21a82012-03-12 12:13:10 +02002512 __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002513
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002514 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002515
2516 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2517 sizeof(rfc), (unsigned long) &rfc);
2518
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002519 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2520 chan->remote_id = efs.id;
2521 chan->remote_stype = efs.stype;
2522 chan->remote_msdu = le16_to_cpu(efs.msdu);
2523 chan->remote_flush_to =
2524 le32_to_cpu(efs.flush_to);
2525 chan->remote_acc_lat =
2526 le32_to_cpu(efs.acc_lat);
2527 chan->remote_sdu_itime =
2528 le32_to_cpu(efs.sdu_itime);
2529 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2530 sizeof(efs), (unsigned long) &efs);
2531 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002532 break;
2533
2534 case L2CAP_MODE_STREAMING:
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002535 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2536 chan->conn->mtu -
2537 L2CAP_EXT_HDR_SIZE -
2538 L2CAP_SDULEN_SIZE -
2539 L2CAP_FCS_SIZE);
2540 rfc.max_pdu_size = cpu_to_le16(size);
2541 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002542
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002543 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002544
2545 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2546 sizeof(rfc), (unsigned long) &rfc);
2547
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002548 break;
2549
2550 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002551 result = L2CAP_CONF_UNACCEPT;
2552
2553 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002554 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002555 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002556
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002557 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002558 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002559 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002560 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002561 rsp->result = cpu_to_le16(result);
2562 rsp->flags = cpu_to_le16(0x0000);
2563
2564 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565}
2566
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002567static 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 -03002568{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002569 struct l2cap_conf_req *req = data;
2570 void *ptr = req->data;
2571 int type, olen;
2572 unsigned long val;
Mat Martineau36e999a2011-12-08 17:23:21 -08002573 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002574 struct l2cap_conf_efs efs;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002575
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002576 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002577
2578 while (len >= L2CAP_CONF_OPT_SIZE) {
2579 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2580
2581 switch (type) {
2582 case L2CAP_CONF_MTU:
2583 if (val < L2CAP_DEFAULT_MIN_MTU) {
2584 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002585 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002586 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002587 chan->imtu = val;
2588 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002589 break;
2590
2591 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002592 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002593 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002594 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002595 break;
2596
2597 case L2CAP_CONF_RFC:
2598 if (olen == sizeof(rfc))
2599 memcpy(&rfc, (void *)val, olen);
2600
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002601 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002602 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002603 return -ECONNREFUSED;
2604
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002605 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002606
2607 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2608 sizeof(rfc), (unsigned long) &rfc);
2609 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002610
2611 case L2CAP_CONF_EWS:
2612 chan->tx_win = min_t(u16, val,
2613 L2CAP_DEFAULT_EXT_WINDOW);
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002614 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2615 chan->tx_win);
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002616 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002617
2618 case L2CAP_CONF_EFS:
2619 if (olen == sizeof(efs))
2620 memcpy(&efs, (void *)val, olen);
2621
2622 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2623 efs.stype != L2CAP_SERV_NOTRAFIC &&
2624 efs.stype != chan->local_stype)
2625 return -ECONNREFUSED;
2626
2627 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2628 sizeof(efs), (unsigned long) &efs);
2629 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002630 }
2631 }
2632
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002633 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002634 return -ECONNREFUSED;
2635
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002636 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002637
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002638 if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002639 switch (rfc.mode) {
2640 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002641 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2642 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2643 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002644
2645 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2646 chan->local_msdu = le16_to_cpu(efs.msdu);
2647 chan->local_sdu_itime =
2648 le32_to_cpu(efs.sdu_itime);
2649 chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
2650 chan->local_flush_to =
2651 le32_to_cpu(efs.flush_to);
2652 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002653 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002654
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002655 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002656 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002657 }
2658 }
2659
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002660 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002661 req->flags = cpu_to_le16(0x0000);
2662
2663 return ptr - data;
2664}
2665
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002666static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667{
2668 struct l2cap_conf_rsp *rsp = data;
2669 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002671 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002673 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002674 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002675 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676
2677 return ptr - data;
2678}
2679
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002680void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002681{
2682 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002683 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002684 u8 buf[128];
2685
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002686 rsp.scid = cpu_to_le16(chan->dcid);
2687 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002688 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2689 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2690 l2cap_send_cmd(conn, chan->ident,
2691 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2692
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002693 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002694 return;
2695
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002696 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2697 l2cap_build_conf_req(chan, buf), buf);
2698 chan->num_conf_req++;
2699}
2700
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002701static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002702{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002703 int type, olen;
2704 unsigned long val;
2705 struct l2cap_conf_rfc rfc;
2706
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002707 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002708
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002709 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002710 return;
2711
2712 while (len >= L2CAP_CONF_OPT_SIZE) {
2713 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2714
2715 switch (type) {
2716 case L2CAP_CONF_RFC:
2717 if (olen == sizeof(rfc))
2718 memcpy(&rfc, (void *)val, olen);
2719 goto done;
2720 }
2721 }
2722
Mat Martineau36e999a2011-12-08 17:23:21 -08002723 /* Use sane default values in case a misbehaving remote device
2724 * did not send an RFC option.
2725 */
2726 rfc.mode = chan->mode;
2727 rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
2728 rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
2729 rfc.max_pdu_size = cpu_to_le16(chan->imtu);
2730
2731 BT_ERR("Expected RFC option was not found, using defaults");
2732
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002733done:
2734 switch (rfc.mode) {
2735 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002736 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2737 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2738 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002739 break;
2740 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002741 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002742 }
2743}
2744
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002745static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2746{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002747 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002748
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002749 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002750 return 0;
2751
2752 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2753 cmd->ident == conn->info_ident) {
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02002754 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002755
2756 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002757 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002758
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002759 l2cap_conn_start(conn);
2760 }
2761
2762 return 0;
2763}
2764
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2766{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2768 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002769 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002770 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002771 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772
2773 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002774 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775
Andrei Emeltchenko097db762012-03-09 14:16:17 +02002776 BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777
2778 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002779 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2780 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781 result = L2CAP_CR_BAD_PSM;
2782 goto sendresp;
2783 }
2784
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002785 parent = pchan->sk;
2786
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002787 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002788 lock_sock(parent);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002789
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002790 /* Check if the ACL is secure enough (if not SDP) */
2791 if (psm != cpu_to_le16(0x0001) &&
2792 !hci_conn_check_link_mode(conn->hcon)) {
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002793 conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002794 result = L2CAP_CR_SEC_BLOCK;
2795 goto response;
2796 }
2797
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798 result = L2CAP_CR_NO_MEM;
2799
2800 /* Check for backlog size */
2801 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002802 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803 goto response;
2804 }
2805
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002806 chan = pchan->ops->new_connection(pchan->data);
2807 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808 goto response;
2809
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002810 sk = chan->sk;
2811
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002813 if (__l2cap_get_chan_by_dcid(conn, scid)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002815 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816 goto response;
2817 }
2818
2819 hci_conn_hold(conn->hcon);
2820
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821 bacpy(&bt_sk(sk)->src, conn->src);
2822 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002823 chan->psm = psm;
2824 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002826 bt_accept_enqueue(parent, sk);
2827
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02002828 __l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002829
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002830 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002832 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002834 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835
Marcel Holtmann984947d2009-02-06 23:35:19 +01002836 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02002837 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002838 if (bt_sk(sk)->defer_setup) {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02002839 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002840 result = L2CAP_CR_PEND;
2841 status = L2CAP_CS_AUTHOR_PEND;
2842 parent->sk_data_ready(parent, 0);
2843 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02002844 __l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002845 result = L2CAP_CR_SUCCESS;
2846 status = L2CAP_CS_NO_INFO;
2847 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002848 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02002849 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002850 result = L2CAP_CR_PEND;
2851 status = L2CAP_CS_AUTHEN_PEND;
2852 }
2853 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02002854 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002855 result = L2CAP_CR_PEND;
2856 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857 }
2858
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859response:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002860 release_sock(parent);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002861 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862
2863sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002864 rsp.scid = cpu_to_le16(scid);
2865 rsp.dcid = cpu_to_le16(dcid);
2866 rsp.result = cpu_to_le16(result);
2867 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002869
2870 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2871 struct l2cap_info_req info;
2872 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2873
2874 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2875 conn->info_ident = l2cap_get_ident(conn);
2876
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08002877 schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002878
2879 l2cap_send_cmd(conn, conn->info_ident,
2880 L2CAP_INFO_REQ, sizeof(info), &info);
2881 }
2882
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002883 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002884 result == L2CAP_CR_SUCCESS) {
2885 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002886 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002887 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002888 l2cap_build_conf_req(chan, buf), buf);
2889 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002890 }
2891
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892 return 0;
2893}
2894
2895static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2896{
2897 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2898 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002899 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002900 u8 req[128];
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002901 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902
2903 scid = __le16_to_cpu(rsp->scid);
2904 dcid = __le16_to_cpu(rsp->dcid);
2905 result = __le16_to_cpu(rsp->result);
2906 status = __le16_to_cpu(rsp->status);
2907
Andrei Emeltchenko1b009c92012-02-21 12:54:54 +02002908 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
2909 dcid, scid, result, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002911 mutex_lock(&conn->chan_lock);
2912
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913 if (scid) {
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002914 chan = __l2cap_get_chan_by_scid(conn, scid);
2915 if (!chan) {
2916 err = -EFAULT;
2917 goto unlock;
2918 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002919 } else {
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002920 chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
2921 if (!chan) {
2922 err = -EFAULT;
2923 goto unlock;
2924 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925 }
2926
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002927 err = 0;
2928
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02002929 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002930
Linus Torvalds1da177e2005-04-16 15:20:36 -07002931 switch (result) {
2932 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002933 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002934 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002935 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002936 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002937
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002938 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002939 break;
2940
Linus Torvalds1da177e2005-04-16 15:20:36 -07002941 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002942 l2cap_build_conf_req(chan, req), req);
2943 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002944 break;
2945
2946 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002947 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948 break;
2949
2950 default:
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002951 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952 break;
2953 }
2954
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02002955 l2cap_chan_unlock(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002956
2957unlock:
2958 mutex_unlock(&conn->chan_lock);
2959
2960 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002961}
2962
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002963static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002964{
2965 /* FCS is enabled only in ERTM or streaming mode, if one or both
2966 * sides request it.
2967 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002968 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002969 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002970 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002971 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002972}
2973
Al Viro88219a02007-07-29 00:17:25 -07002974static 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 -07002975{
2976 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2977 u16 dcid, flags;
2978 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002979 struct l2cap_chan *chan;
Mat Martineau3c588192012-04-11 10:48:42 -07002980 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981
2982 dcid = __le16_to_cpu(req->dcid);
2983 flags = __le16_to_cpu(req->flags);
2984
2985 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2986
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002987 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002988 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989 return -ENOENT;
2990
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02002991 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002992
David S. Miller033b1142011-07-21 13:38:42 -07002993 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002994 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002995
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002996 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2997 rej.scid = cpu_to_le16(chan->scid);
2998 rej.dcid = cpu_to_le16(chan->dcid);
2999
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003000 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
3001 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003002 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003003 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003004
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003005 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07003006 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04003007 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003008 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003009 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003010 L2CAP_CONF_REJECT, flags), rsp);
3011 goto unlock;
3012 }
3013
3014 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003015 memcpy(chan->conf_req + chan->conf_len, req->data, len);
3016 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017
3018 if (flags & 0x0001) {
3019 /* Incomplete config. Send empty response. */
3020 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003021 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003022 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023 goto unlock;
3024 }
3025
3026 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003027 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003028 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003029 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003031 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003033 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003034 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003035
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003036 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003037 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003038
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003039 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02003040 goto unlock;
3041
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003042 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003043 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003044
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003045 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003046
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003047 chan->next_tx_seq = 0;
3048 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03003049 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003050 if (chan->mode == L2CAP_MODE_ERTM)
Mat Martineau3c588192012-04-11 10:48:42 -07003051 err = l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003052
Mat Martineau3c588192012-04-11 10:48:42 -07003053 if (err < 0)
3054 l2cap_send_disconn_req(chan->conn, chan, -err);
3055 else
3056 l2cap_chan_ready(chan);
3057
Marcel Holtmann876d9482007-10-20 13:35:42 +02003058 goto unlock;
3059 }
3060
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003061 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003062 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003064 l2cap_build_conf_req(chan, buf), buf);
3065 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066 }
3067
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003068 /* Got Conf Rsp PENDING from remote side and asume we sent
3069 Conf Rsp PENDING in the code above */
3070 if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
3071 test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
3072
3073 /* check compatibility */
3074
3075 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
3076 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
3077
3078 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02003079 l2cap_build_conf_rsp(chan, rsp,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003080 L2CAP_CONF_SUCCESS, 0x0000), rsp);
3081 }
3082
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083unlock:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003084 l2cap_chan_unlock(chan);
Mat Martineau3c588192012-04-11 10:48:42 -07003085 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003086}
3087
3088static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3089{
3090 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
3091 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003092 struct l2cap_chan *chan;
Andrei Emeltchenko61386cb2012-03-12 12:13:07 +02003093 int len = le16_to_cpu(cmd->len) - sizeof(*rsp);
Mat Martineau3c588192012-04-11 10:48:42 -07003094 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095
3096 scid = __le16_to_cpu(rsp->scid);
3097 flags = __le16_to_cpu(rsp->flags);
3098 result = __le16_to_cpu(rsp->result);
3099
Andrei Emeltchenko61386cb2012-03-12 12:13:07 +02003100 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
3101 result, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003103 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003104 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105 return 0;
3106
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003107 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003108
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109 switch (result) {
3110 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003111 l2cap_conf_rfc_get(chan, rsp->data, len);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003112 clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113 break;
3114
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003115 case L2CAP_CONF_PENDING:
3116 set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
3117
3118 if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
3119 char buf[64];
3120
3121 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
3122 buf, &result);
3123 if (len < 0) {
3124 l2cap_send_disconn_req(conn, chan, ECONNRESET);
3125 goto done;
3126 }
3127
3128 /* check compatibility */
3129
3130 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
3131 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
3132
3133 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02003134 l2cap_build_conf_rsp(chan, buf,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003135 L2CAP_CONF_SUCCESS, 0x0000), buf);
3136 }
3137 goto done;
3138
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003140 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003141 char req[64];
3142
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003143 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003144 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003145 goto done;
3146 }
3147
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003148 /* throw out any old stored conf requests */
3149 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003150 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
3151 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003152 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003153 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003154 goto done;
3155 }
3156
3157 l2cap_send_cmd(conn, l2cap_get_ident(conn),
3158 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003159 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003160 if (result != L2CAP_CONF_SUCCESS)
3161 goto done;
3162 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003163 }
3164
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09003165 default:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003166 l2cap_chan_set_err(chan, ECONNRESET);
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +02003167
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08003168 __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003169 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170 goto done;
3171 }
3172
3173 if (flags & 0x01)
3174 goto done;
3175
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003176 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003178 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003179 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003180
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003181 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003182 chan->next_tx_seq = 0;
3183 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03003184 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003185 if (chan->mode == L2CAP_MODE_ERTM)
Mat Martineau3c588192012-04-11 10:48:42 -07003186 err = l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003187
Mat Martineau3c588192012-04-11 10:48:42 -07003188 if (err < 0)
3189 l2cap_send_disconn_req(chan->conn, chan, -err);
3190 else
3191 l2cap_chan_ready(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192 }
3193
3194done:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003195 l2cap_chan_unlock(chan);
Mat Martineau3c588192012-04-11 10:48:42 -07003196 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197}
3198
3199static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3200{
3201 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3202 struct l2cap_disconn_rsp rsp;
3203 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003204 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205 struct sock *sk;
3206
3207 scid = __le16_to_cpu(req->scid);
3208 dcid = __le16_to_cpu(req->dcid);
3209
3210 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3211
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003212 mutex_lock(&conn->chan_lock);
3213
3214 chan = __l2cap_get_chan_by_scid(conn, dcid);
3215 if (!chan) {
3216 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003217 return 0;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003218 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003219
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003220 l2cap_chan_lock(chan);
3221
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003222 sk = chan->sk;
3223
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003224 rsp.dcid = cpu_to_le16(chan->scid);
3225 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3227
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003228 lock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229 sk->sk_shutdown = SHUTDOWN_MASK;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003230 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003232 l2cap_chan_del(chan, ECONNRESET);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003233
3234 l2cap_chan_unlock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003236 chan->ops->close(chan->data);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003237
3238 mutex_unlock(&conn->chan_lock);
3239
Linus Torvalds1da177e2005-04-16 15:20:36 -07003240 return 0;
3241}
3242
3243static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3244{
3245 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3246 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003247 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248
3249 scid = __le16_to_cpu(rsp->scid);
3250 dcid = __le16_to_cpu(rsp->dcid);
3251
3252 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3253
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003254 mutex_lock(&conn->chan_lock);
3255
3256 chan = __l2cap_get_chan_by_scid(conn, scid);
3257 if (!chan) {
3258 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259 return 0;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003260 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003262 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003263
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003264 l2cap_chan_del(chan, 0);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003265
3266 l2cap_chan_unlock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003268 chan->ops->close(chan->data);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003269
3270 mutex_unlock(&conn->chan_lock);
3271
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272 return 0;
3273}
3274
3275static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3276{
3277 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003278 u16 type;
3279
3280 type = __le16_to_cpu(req->type);
3281
3282 BT_DBG("type 0x%4.4x", type);
3283
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003284 if (type == L2CAP_IT_FEAT_MASK) {
3285 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003286 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003287 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3288 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3289 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003290 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003291 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3292 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003293 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003294 feat_mask |= L2CAP_FEAT_EXT_FLOW
3295 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003296
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003297 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003298 l2cap_send_cmd(conn, cmd->ident,
3299 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003300 } else if (type == L2CAP_IT_FIXED_CHAN) {
3301 u8 buf[12];
3302 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
Mat Martineau50a147c2011-11-02 16:18:34 -07003303
3304 if (enable_hs)
3305 l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
3306 else
3307 l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
3308
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003309 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3310 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003311 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003312 l2cap_send_cmd(conn, cmd->ident,
3313 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003314 } else {
3315 struct l2cap_info_rsp rsp;
3316 rsp.type = cpu_to_le16(type);
3317 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3318 l2cap_send_cmd(conn, cmd->ident,
3319 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3320 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003321
3322 return 0;
3323}
3324
3325static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3326{
3327 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3328 u16 type, result;
3329
3330 type = __le16_to_cpu(rsp->type);
3331 result = __le16_to_cpu(rsp->result);
3332
3333 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3334
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003335 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3336 if (cmd->ident != conn->info_ident ||
3337 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3338 return 0;
3339
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02003340 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003341
Ville Tervoadb08ed2010-08-04 09:43:33 +03003342 if (result != L2CAP_IR_SUCCESS) {
3343 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3344 conn->info_ident = 0;
3345
3346 l2cap_conn_start(conn);
3347
3348 return 0;
3349 }
3350
Andrei Emeltchenko978c93b2012-02-29 10:41:41 +02003351 switch (type) {
3352 case L2CAP_IT_FEAT_MASK:
Harvey Harrison83985312008-05-02 16:25:46 -07003353 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003354
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003355 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003356 struct l2cap_info_req req;
3357 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3358
3359 conn->info_ident = l2cap_get_ident(conn);
3360
3361 l2cap_send_cmd(conn, conn->info_ident,
3362 L2CAP_INFO_REQ, sizeof(req), &req);
3363 } else {
3364 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3365 conn->info_ident = 0;
3366
3367 l2cap_conn_start(conn);
3368 }
Andrei Emeltchenko978c93b2012-02-29 10:41:41 +02003369 break;
3370
3371 case L2CAP_IT_FIXED_CHAN:
3372 conn->fixed_chan_mask = rsp->data[0];
Marcel Holtmann984947d2009-02-06 23:35:19 +01003373 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003374 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003375
3376 l2cap_conn_start(conn);
Andrei Emeltchenko978c93b2012-02-29 10:41:41 +02003377 break;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003378 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003379
Linus Torvalds1da177e2005-04-16 15:20:36 -07003380 return 0;
3381}
3382
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003383static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3384 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3385 void *data)
3386{
3387 struct l2cap_create_chan_req *req = data;
3388 struct l2cap_create_chan_rsp rsp;
3389 u16 psm, scid;
3390
3391 if (cmd_len != sizeof(*req))
3392 return -EPROTO;
3393
3394 if (!enable_hs)
3395 return -EINVAL;
3396
3397 psm = le16_to_cpu(req->psm);
3398 scid = le16_to_cpu(req->scid);
3399
3400 BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3401
3402 /* Placeholder: Always reject */
3403 rsp.dcid = 0;
3404 rsp.scid = cpu_to_le16(scid);
Andrei Emeltchenko8ce0c492012-03-12 12:13:09 +02003405 rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
3406 rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003407
3408 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3409 sizeof(rsp), &rsp);
3410
3411 return 0;
3412}
3413
3414static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3415 struct l2cap_cmd_hdr *cmd, void *data)
3416{
3417 BT_DBG("conn %p", conn);
3418
3419 return l2cap_connect_rsp(conn, cmd, data);
3420}
3421
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003422static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
3423 u16 icid, u16 result)
3424{
3425 struct l2cap_move_chan_rsp rsp;
3426
3427 BT_DBG("icid %d, result %d", icid, result);
3428
3429 rsp.icid = cpu_to_le16(icid);
3430 rsp.result = cpu_to_le16(result);
3431
3432 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
3433}
3434
3435static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
3436 struct l2cap_chan *chan, u16 icid, u16 result)
3437{
3438 struct l2cap_move_chan_cfm cfm;
3439 u8 ident;
3440
3441 BT_DBG("icid %d, result %d", icid, result);
3442
3443 ident = l2cap_get_ident(conn);
3444 if (chan)
3445 chan->ident = ident;
3446
3447 cfm.icid = cpu_to_le16(icid);
3448 cfm.result = cpu_to_le16(result);
3449
3450 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
3451}
3452
3453static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
3454 u16 icid)
3455{
3456 struct l2cap_move_chan_cfm_rsp rsp;
3457
3458 BT_DBG("icid %d", icid);
3459
3460 rsp.icid = cpu_to_le16(icid);
3461 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
3462}
3463
3464static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
3465 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3466{
3467 struct l2cap_move_chan_req *req = data;
3468 u16 icid = 0;
3469 u16 result = L2CAP_MR_NOT_ALLOWED;
3470
3471 if (cmd_len != sizeof(*req))
3472 return -EPROTO;
3473
3474 icid = le16_to_cpu(req->icid);
3475
3476 BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
3477
3478 if (!enable_hs)
3479 return -EINVAL;
3480
3481 /* Placeholder: Always refuse */
3482 l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
3483
3484 return 0;
3485}
3486
3487static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
3488 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3489{
3490 struct l2cap_move_chan_rsp *rsp = data;
3491 u16 icid, result;
3492
3493 if (cmd_len != sizeof(*rsp))
3494 return -EPROTO;
3495
3496 icid = le16_to_cpu(rsp->icid);
3497 result = le16_to_cpu(rsp->result);
3498
3499 BT_DBG("icid %d, result %d", icid, result);
3500
3501 /* Placeholder: Always unconfirmed */
3502 l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
3503
3504 return 0;
3505}
3506
3507static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
3508 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3509{
3510 struct l2cap_move_chan_cfm *cfm = data;
3511 u16 icid, result;
3512
3513 if (cmd_len != sizeof(*cfm))
3514 return -EPROTO;
3515
3516 icid = le16_to_cpu(cfm->icid);
3517 result = le16_to_cpu(cfm->result);
3518
3519 BT_DBG("icid %d, result %d", icid, result);
3520
3521 l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
3522
3523 return 0;
3524}
3525
3526static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
3527 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3528{
3529 struct l2cap_move_chan_cfm_rsp *rsp = data;
3530 u16 icid;
3531
3532 if (cmd_len != sizeof(*rsp))
3533 return -EPROTO;
3534
3535 icid = le16_to_cpu(rsp->icid);
3536
3537 BT_DBG("icid %d", icid);
3538
3539 return 0;
3540}
3541
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003542static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02003543 u16 to_multiplier)
3544{
3545 u16 max_latency;
3546
3547 if (min > max || min < 6 || max > 3200)
3548 return -EINVAL;
3549
3550 if (to_multiplier < 10 || to_multiplier > 3200)
3551 return -EINVAL;
3552
3553 if (max >= to_multiplier * 8)
3554 return -EINVAL;
3555
3556 max_latency = (to_multiplier * 8 / max) - 1;
3557 if (latency > 499 || latency > max_latency)
3558 return -EINVAL;
3559
3560 return 0;
3561}
3562
3563static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3564 struct l2cap_cmd_hdr *cmd, u8 *data)
3565{
3566 struct hci_conn *hcon = conn->hcon;
3567 struct l2cap_conn_param_update_req *req;
3568 struct l2cap_conn_param_update_rsp rsp;
3569 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003570 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02003571
3572 if (!(hcon->link_mode & HCI_LM_MASTER))
3573 return -EINVAL;
3574
3575 cmd_len = __le16_to_cpu(cmd->len);
3576 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3577 return -EPROTO;
3578
3579 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003580 min = __le16_to_cpu(req->min);
3581 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02003582 latency = __le16_to_cpu(req->latency);
3583 to_multiplier = __le16_to_cpu(req->to_multiplier);
3584
3585 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3586 min, max, latency, to_multiplier);
3587
3588 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003589
3590 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
3591 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02003592 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3593 else
3594 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3595
3596 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3597 sizeof(rsp), &rsp);
3598
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003599 if (!err)
3600 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
3601
Claudio Takahaside731152011-02-11 19:28:55 -02003602 return 0;
3603}
3604
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003605static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
3606 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
3607{
3608 int err = 0;
3609
3610 switch (cmd->code) {
3611 case L2CAP_COMMAND_REJ:
3612 l2cap_command_rej(conn, cmd, data);
3613 break;
3614
3615 case L2CAP_CONN_REQ:
3616 err = l2cap_connect_req(conn, cmd, data);
3617 break;
3618
3619 case L2CAP_CONN_RSP:
3620 err = l2cap_connect_rsp(conn, cmd, data);
3621 break;
3622
3623 case L2CAP_CONF_REQ:
3624 err = l2cap_config_req(conn, cmd, cmd_len, data);
3625 break;
3626
3627 case L2CAP_CONF_RSP:
3628 err = l2cap_config_rsp(conn, cmd, data);
3629 break;
3630
3631 case L2CAP_DISCONN_REQ:
3632 err = l2cap_disconnect_req(conn, cmd, data);
3633 break;
3634
3635 case L2CAP_DISCONN_RSP:
3636 err = l2cap_disconnect_rsp(conn, cmd, data);
3637 break;
3638
3639 case L2CAP_ECHO_REQ:
3640 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3641 break;
3642
3643 case L2CAP_ECHO_RSP:
3644 break;
3645
3646 case L2CAP_INFO_REQ:
3647 err = l2cap_information_req(conn, cmd, data);
3648 break;
3649
3650 case L2CAP_INFO_RSP:
3651 err = l2cap_information_rsp(conn, cmd, data);
3652 break;
3653
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003654 case L2CAP_CREATE_CHAN_REQ:
3655 err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3656 break;
3657
3658 case L2CAP_CREATE_CHAN_RSP:
3659 err = l2cap_create_channel_rsp(conn, cmd, data);
3660 break;
3661
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003662 case L2CAP_MOVE_CHAN_REQ:
3663 err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
3664 break;
3665
3666 case L2CAP_MOVE_CHAN_RSP:
3667 err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
3668 break;
3669
3670 case L2CAP_MOVE_CHAN_CFM:
3671 err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
3672 break;
3673
3674 case L2CAP_MOVE_CHAN_CFM_RSP:
3675 err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
3676 break;
3677
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003678 default:
3679 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3680 err = -EINVAL;
3681 break;
3682 }
3683
3684 return err;
3685}
3686
3687static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3688 struct l2cap_cmd_hdr *cmd, u8 *data)
3689{
3690 switch (cmd->code) {
3691 case L2CAP_COMMAND_REJ:
3692 return 0;
3693
3694 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003695 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003696
3697 case L2CAP_CONN_PARAM_UPDATE_RSP:
3698 return 0;
3699
3700 default:
3701 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3702 return -EINVAL;
3703 }
3704}
3705
3706static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3707 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708{
3709 u8 *data = skb->data;
3710 int len = skb->len;
3711 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003712 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003713
3714 l2cap_raw_recv(conn, skb);
3715
3716 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003717 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3719 data += L2CAP_CMD_HDR_SIZE;
3720 len -= L2CAP_CMD_HDR_SIZE;
3721
Al Viro88219a02007-07-29 00:17:25 -07003722 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723
Al Viro88219a02007-07-29 00:17:25 -07003724 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 -07003725
Al Viro88219a02007-07-29 00:17:25 -07003726 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727 BT_DBG("corrupted command");
3728 break;
3729 }
3730
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003731 if (conn->hcon->type == LE_LINK)
3732 err = l2cap_le_sig_cmd(conn, &cmd, data);
3733 else
3734 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735
3736 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003737 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003738
3739 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740
3741 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003742 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3744 }
3745
Al Viro88219a02007-07-29 00:17:25 -07003746 data += cmd_len;
3747 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003748 }
3749
3750 kfree_skb(skb);
3751}
3752
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003753static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003754{
3755 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003756 int hdr_size;
3757
3758 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3759 hdr_size = L2CAP_EXT_HDR_SIZE;
3760 else
3761 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003762
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003763 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003764 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003765 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3766 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3767
3768 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003769 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003770 }
3771 return 0;
3772}
3773
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003774static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003775{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003776 u32 control = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003777
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003778 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003779
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003780 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003781
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003782 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003783 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003784 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003785 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003786 }
3787
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003788 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003789 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003790
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003791 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003792
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003793 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003794 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003795 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003796 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003797 }
3798}
3799
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003800static 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 -03003801{
3802 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003803 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003804
3805 bt_cb(skb)->tx_seq = tx_seq;
3806 bt_cb(skb)->sar = sar;
3807
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003808 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003809
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003810 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003811
Szymon Janc039d9572011-11-16 09:32:19 +01003812 while (next_skb) {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003813 if (bt_cb(next_skb)->tx_seq == tx_seq)
3814 return -EINVAL;
3815
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003816 next_tx_seq_offset = __seq_offset(chan,
3817 bt_cb(next_skb)->tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003818
3819 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003820 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003821 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003822 }
3823
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003824 if (skb_queue_is_last(&chan->srej_q, next_skb))
Szymon Janc039d9572011-11-16 09:32:19 +01003825 next_skb = NULL;
3826 else
3827 next_skb = skb_queue_next(&chan->srej_q, next_skb);
3828 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003829
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003830 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003831
3832 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003833}
3834
Mat Martineau84084a32011-07-22 14:54:00 -07003835static void append_skb_frag(struct sk_buff *skb,
3836 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003837{
Mat Martineau84084a32011-07-22 14:54:00 -07003838 /* skb->len reflects data in skb as well as all fragments
3839 * skb->data_len reflects only data in fragments
3840 */
3841 if (!skb_has_frag_list(skb))
3842 skb_shinfo(skb)->frag_list = new_frag;
3843
3844 new_frag->next = NULL;
3845
3846 (*last_frag)->next = new_frag;
3847 *last_frag = new_frag;
3848
3849 skb->len += new_frag->len;
3850 skb->data_len += new_frag->len;
3851 skb->truesize += new_frag->truesize;
3852}
3853
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003854static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
Mat Martineau84084a32011-07-22 14:54:00 -07003855{
3856 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003857
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003858 switch (__get_ctrl_sar(chan, control)) {
3859 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003860 if (chan->sdu)
3861 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003862
Mat Martineau84084a32011-07-22 14:54:00 -07003863 err = chan->ops->recv(chan->data, skb);
3864 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003865
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003866 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003867 if (chan->sdu)
3868 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003869
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003870 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003871 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003872
Mat Martineau84084a32011-07-22 14:54:00 -07003873 if (chan->sdu_len > chan->imtu) {
3874 err = -EMSGSIZE;
3875 break;
3876 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003877
Mat Martineau84084a32011-07-22 14:54:00 -07003878 if (skb->len >= chan->sdu_len)
3879 break;
3880
3881 chan->sdu = skb;
3882 chan->sdu_last_frag = skb;
3883
3884 skb = NULL;
3885 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003886 break;
3887
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003888 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003889 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003890 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003891
Mat Martineau84084a32011-07-22 14:54:00 -07003892 append_skb_frag(chan->sdu, skb,
3893 &chan->sdu_last_frag);
3894 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003895
Mat Martineau84084a32011-07-22 14:54:00 -07003896 if (chan->sdu->len >= chan->sdu_len)
3897 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003898
Mat Martineau84084a32011-07-22 14:54:00 -07003899 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003900 break;
3901
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003902 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003903 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003904 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003905
Mat Martineau84084a32011-07-22 14:54:00 -07003906 append_skb_frag(chan->sdu, skb,
3907 &chan->sdu_last_frag);
3908 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003909
Mat Martineau84084a32011-07-22 14:54:00 -07003910 if (chan->sdu->len != chan->sdu_len)
3911 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003912
Mat Martineau84084a32011-07-22 14:54:00 -07003913 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003914
Mat Martineau84084a32011-07-22 14:54:00 -07003915 if (!err) {
3916 /* Reassembly complete */
3917 chan->sdu = NULL;
3918 chan->sdu_last_frag = NULL;
3919 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003920 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003921 break;
3922 }
3923
Mat Martineau84084a32011-07-22 14:54:00 -07003924 if (err) {
3925 kfree_skb(skb);
3926 kfree_skb(chan->sdu);
3927 chan->sdu = NULL;
3928 chan->sdu_last_frag = NULL;
3929 chan->sdu_len = 0;
3930 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003931
Mat Martineau84084a32011-07-22 14:54:00 -07003932 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003933}
3934
Mat Martineau26f880d2011-07-07 09:39:01 -07003935static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003936{
Mat Martineau26f880d2011-07-07 09:39:01 -07003937 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003938
Mat Martineau26f880d2011-07-07 09:39:01 -07003939 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
Mat Martineau3c588192012-04-11 10:48:42 -07003940 l2cap_seq_list_clear(&chan->srej_list);
Mat Martineau26f880d2011-07-07 09:39:01 -07003941
Szymon Janc77f918b2012-01-11 10:59:48 +01003942 __set_ack_timer(chan);
Mat Martineau26f880d2011-07-07 09:39:01 -07003943}
3944
3945static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3946{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003947 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003948
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003949 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003950 goto done;
3951
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003952 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003953 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003954 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003955 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003956 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003957
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003958 __clear_retrans_timer(chan);
3959 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003960
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003961 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003962
3963done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003964 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3965 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003966
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003967 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003968}
3969
Mat Martineaue3281402011-07-07 09:39:02 -07003970void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003971{
Mat Martineaue3281402011-07-07 09:39:02 -07003972 if (chan->mode == L2CAP_MODE_ERTM) {
3973 if (busy)
3974 l2cap_ertm_enter_local_busy(chan);
3975 else
3976 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003977 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003978}
3979
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003980static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003981{
3982 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003983 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003984
Mat Martineaue3281402011-07-07 09:39:02 -07003985 while ((skb = skb_peek(&chan->srej_q)) &&
3986 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3987 int err;
3988
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003989 if (bt_cb(skb)->tx_seq != tx_seq)
3990 break;
3991
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003992 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003993 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003994 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003995
3996 if (err < 0) {
3997 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3998 break;
3999 }
4000
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004001 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
4002 tx_seq = __next_seq(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004003 }
4004}
4005
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004006static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004007{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004008 struct srej_list *l, *tmp;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004009 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004010
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004011 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004012 if (l->tx_seq == tx_seq) {
4013 list_del(&l->list);
4014 kfree(l);
4015 return;
4016 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004017 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004018 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004019 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004020 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004021 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004022 }
4023}
4024
Szymon Jancaef89f22011-11-16 09:32:18 +01004025static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004026{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004027 struct srej_list *new;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004028 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004029
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004030 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004031 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004032 control |= __set_reqseq(chan, chan->expected_tx_seq);
Mat Martineau3c588192012-04-11 10:48:42 -07004033 l2cap_seq_list_append(&chan->srej_list, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004034 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004035
4036 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Szymon Jancaef89f22011-11-16 09:32:18 +01004037 if (!new)
4038 return -ENOMEM;
4039
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004040 new->tx_seq = chan->expected_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004041
4042 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
4043
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004044 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004045 }
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004046
4047 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Szymon Jancaef89f22011-11-16 09:32:18 +01004048
4049 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004050}
4051
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004052static 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 -03004053{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004054 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004055 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004056 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03004057 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004058 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004059 int err = 0;
4060
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004061 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 -03004062 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004063
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004064 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004065 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004066 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004067 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004068 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004069 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004070 }
4071
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004072 chan->expected_ack_seq = req_seq;
4073 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03004074
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004075 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004076
4077 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004078 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004079 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004080 goto drop;
4081 }
4082
Szymon Janc77f918b2012-01-11 10:59:48 +01004083 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4084 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
4085 l2cap_send_ack(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004086 goto drop;
Szymon Janc77f918b2012-01-11 10:59:48 +01004087 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004088
Mat Martineau02f1b642011-06-29 14:35:19 -07004089 if (tx_seq == chan->expected_tx_seq)
4090 goto expected;
4091
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004092 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004093 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004094
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004095 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004096 struct srej_list, list);
4097 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004098 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004099 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004100
4101 list_del(&first->list);
4102 kfree(first);
4103
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004104 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004105 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004106 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004107 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004108 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004109 }
4110 } else {
4111 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004112
4113 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004114 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004115 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004116
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004117 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004118 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004119 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004120 return 0;
4121 }
4122 }
Szymon Jancaef89f22011-11-16 09:32:18 +01004123
4124 err = l2cap_send_srejframe(chan, tx_seq);
4125 if (err < 0) {
4126 l2cap_send_disconn_req(chan->conn, chan, -err);
4127 return err;
4128 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004129 }
4130 } else {
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004131 expected_tx_seq_offset = __seq_offset(chan,
4132 chan->expected_tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004133
4134 /* duplicated tx_seq */
4135 if (tx_seq_offset < expected_tx_seq_offset)
4136 goto drop;
4137
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004138 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004139
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004140 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004141
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004142 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004143 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004144
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004145 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004146 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004147
Szymon Janc0ef3ef02012-01-11 10:59:46 +01004148 /* Set P-bit only if there are some I-frames to ack. */
4149 if (__clear_ack_timer(chan))
4150 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03004151
Szymon Jancaef89f22011-11-16 09:32:18 +01004152 err = l2cap_send_srejframe(chan, tx_seq);
4153 if (err < 0) {
4154 l2cap_send_disconn_req(chan->conn, chan, -err);
4155 return err;
4156 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004157 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004158 return 0;
4159
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004160expected:
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004161 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004162
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004163 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03004164 bt_cb(skb)->tx_seq = tx_seq;
4165 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004166 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004167 return 0;
4168 }
4169
Mat Martineau84084a32011-07-22 14:54:00 -07004170 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004171 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
4172
Mat Martineaue3281402011-07-07 09:39:02 -07004173 if (err < 0) {
4174 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4175 return err;
4176 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03004177
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004178 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004179 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004180 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03004181 }
4182
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03004183
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004184 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
4185 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004186 l2cap_send_ack(chan);
Gustavo F. Padovan4d611e42011-06-23 19:30:48 -03004187 else
4188 __set_ack_timer(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03004189
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004190 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004191
4192drop:
4193 kfree_skb(skb);
4194 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004195}
4196
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004197static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004198{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004199 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004200 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004201
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004202 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004203 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004204
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004205 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004206 set_bit(CONN_SEND_FBIT, &chan->conn_state);
4207 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
4208 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004209 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004210 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004211
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004212 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004213 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004214 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004215 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004216 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004217
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004218 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004219 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004220
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004221 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004222 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004223
4224 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004225 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004226 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004227 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004228
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004229 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4230 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004231 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02004232 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004233 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004234 }
4235}
4236
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004237static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004238{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004239 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004240
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004241 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004242
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004243 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004244
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004245 chan->expected_ack_seq = tx_seq;
4246 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004247
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004248 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004249 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004250 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004251 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004252 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004253
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004254 if (test_bit(CONN_WAIT_F, &chan->conn_state))
4255 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004256 }
4257}
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004258static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004259{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004260 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004261
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004262 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004263
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004264 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004265
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004266 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004267 chan->expected_ack_seq = tx_seq;
4268 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004269
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004270 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004271 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004272
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004273 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004274
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004275 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004276 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004277 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004278 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004279 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004280 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004281 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004282 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004283 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004284 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004285 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004286 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004287 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004288 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004289 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004290 }
4291 }
4292}
4293
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004294static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004295{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004296 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004297
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004298 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004299
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004300 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004301 chan->expected_ack_seq = tx_seq;
4302 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004303
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004304 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004305 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004306
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004307 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004308 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004309 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004310 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004311 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004312 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004313
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004314 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004315 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004316 } else {
4317 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4318 l2cap_send_sframe(chan, rx_control);
4319 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004320}
4321
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004322static 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 -03004323{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004324 BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004325
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004326 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004327 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004328 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004329 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004330 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004331 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004332 }
4333
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004334 switch (__get_ctrl_super(chan, rx_control)) {
4335 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004336 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004337 break;
4338
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004339 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004340 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004341 break;
4342
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004343 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004344 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004345 break;
4346
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004347 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004348 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004349 break;
4350 }
4351
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004352 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004353 return 0;
4354}
4355
Szymon Janccad8f1d02012-01-23 10:06:05 +01004356static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004357{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004358 u32 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004359 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004360 int len, next_tx_seq_offset, req_seq_offset;
4361
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004362 control = __get_control(chan, skb->data);
4363 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004364 len = skb->len;
4365
4366 /*
4367 * We can just drop the corrupted I-frame here.
4368 * Receiver will miss it and start proper recovery
4369 * procedures and ask retransmission.
4370 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004371 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004372 goto drop;
4373
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004374 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004375 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004376
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004377 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004378 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004379
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004380 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004381 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004382 goto drop;
4383 }
4384
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004385 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004386
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004387 req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4388
4389 next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4390 chan->expected_ack_seq);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004391
4392 /* check for invalid req-seq */
4393 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004394 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004395 goto drop;
4396 }
4397
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004398 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004399 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004400 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004401 goto drop;
4402 }
4403
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004404 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004405 } else {
4406 if (len != 0) {
4407 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004408 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004409 goto drop;
4410 }
4411
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004412 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004413 }
4414
4415 return 0;
4416
4417drop:
4418 kfree_skb(skb);
4419 return 0;
4420}
4421
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4423{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004424 struct l2cap_chan *chan;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004425 u32 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004426 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004427 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004428
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004429 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004430 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004431 BT_DBG("unknown cid 0x%4.4x", cid);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004432 /* Drop packet and return */
Dan Carpenter33790132012-02-28 09:52:46 +03004433 kfree_skb(skb);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004434 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435 }
4436
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004437 l2cap_chan_lock(chan);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004438
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004439 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004441 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442 goto drop;
4443
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004444 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004445 case L2CAP_MODE_BASIC:
4446 /* If socket recv buffers overflows we drop data here
4447 * which is *bad* because L2CAP has to be reliable.
4448 * But we don't have any other choice. L2CAP doesn't
4449 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004450
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004451 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004452 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004454 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004455 goto done;
4456 break;
4457
4458 case L2CAP_MODE_ERTM:
Andrei Emeltchenko5ef8cb92012-01-13 17:21:42 +02004459 l2cap_ertm_data_rcv(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004460
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004461 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004462
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004463 case L2CAP_MODE_STREAMING:
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004464 control = __get_control(chan, skb->data);
4465 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004466 len = skb->len;
4467
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004468 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004469 goto drop;
4470
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004471 if (__is_sar_start(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004472 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004473
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004474 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004475 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004476
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004477 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004478 goto drop;
4479
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004480 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004481
Mat Martineau84084a32011-07-22 14:54:00 -07004482 if (chan->expected_tx_seq != tx_seq) {
4483 /* Frame(s) missing - must discard partial SDU */
4484 kfree_skb(chan->sdu);
4485 chan->sdu = NULL;
4486 chan->sdu_last_frag = NULL;
4487 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004488
Mat Martineau84084a32011-07-22 14:54:00 -07004489 /* TODO: Notify userland of missing data */
4490 }
4491
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004492 chan->expected_tx_seq = __next_seq(chan, tx_seq);
Mat Martineau84084a32011-07-22 14:54:00 -07004493
4494 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
4495 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004496
4497 goto done;
4498
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004499 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004500 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004501 break;
4502 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004503
4504drop:
4505 kfree_skb(skb);
4506
4507done:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004508 l2cap_chan_unlock(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +02004509
Linus Torvalds1da177e2005-04-16 15:20:36 -07004510 return 0;
4511}
4512
Al Viro8e036fc2007-07-29 00:16:36 -07004513static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004515 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004516
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004517 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
4518 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004519 goto drop;
4520
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02004521 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004522
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004523 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004524 goto drop;
4525
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004526 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527 goto drop;
4528
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004529 if (!chan->ops->recv(chan->data, skb))
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02004530 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004531
4532drop:
4533 kfree_skb(skb);
4534
Linus Torvalds1da177e2005-04-16 15:20:36 -07004535 return 0;
4536}
4537
Andrei Emeltchenkod9b88702012-03-12 12:13:08 +02004538static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid,
4539 struct sk_buff *skb)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004540{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004541 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004542
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004543 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
4544 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004545 goto drop;
4546
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02004547 BT_DBG("chan %p, len %d", chan, skb->len);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004548
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004549 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004550 goto drop;
4551
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004552 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004553 goto drop;
4554
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004555 if (!chan->ops->recv(chan->data, skb))
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02004556 return 0;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004557
4558drop:
4559 kfree_skb(skb);
4560
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004561 return 0;
4562}
4563
Linus Torvalds1da177e2005-04-16 15:20:36 -07004564static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4565{
4566 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004567 u16 cid, len;
4568 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004569
4570 skb_pull(skb, L2CAP_HDR_SIZE);
4571 cid = __le16_to_cpu(lh->cid);
4572 len = __le16_to_cpu(lh->len);
4573
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004574 if (len != skb->len) {
4575 kfree_skb(skb);
4576 return;
4577 }
4578
Linus Torvalds1da177e2005-04-16 15:20:36 -07004579 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4580
4581 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004582 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004583 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004584 l2cap_sig_channel(conn, skb);
4585 break;
4586
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004587 case L2CAP_CID_CONN_LESS:
Andrei Emeltchenko097db762012-03-09 14:16:17 +02004588 psm = get_unaligned((__le16 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004589 skb_pull(skb, 2);
4590 l2cap_conless_channel(conn, psm, skb);
4591 break;
4592
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004593 case L2CAP_CID_LE_DATA:
4594 l2cap_att_channel(conn, cid, skb);
4595 break;
4596
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004597 case L2CAP_CID_SMP:
4598 if (smp_sig_channel(conn, skb))
4599 l2cap_conn_del(conn->hcon, EACCES);
4600 break;
4601
Linus Torvalds1da177e2005-04-16 15:20:36 -07004602 default:
4603 l2cap_data_channel(conn, cid, skb);
4604 break;
4605 }
4606}
4607
4608/* ---- L2CAP interface with lower layer (HCI) ---- */
4609
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004610int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004611{
4612 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004613 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004614
Linus Torvalds1da177e2005-04-16 15:20:36 -07004615 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4616
4617 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004618 read_lock(&chan_list_lock);
4619 list_for_each_entry(c, &chan_list, global_l) {
4620 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004621
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004622 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004623 continue;
4624
4625 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004626 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004627 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004628 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004629 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004630 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4631 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004632 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004633 lm2 |= HCI_LM_MASTER;
4634 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004635 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004636 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004637
4638 return exact ? lm1 : lm2;
4639}
4640
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004641int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004642{
Marcel Holtmann01394182006-07-03 10:02:46 +02004643 struct l2cap_conn *conn;
4644
Linus Torvalds1da177e2005-04-16 15:20:36 -07004645 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4646
Linus Torvalds1da177e2005-04-16 15:20:36 -07004647 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004648 conn = l2cap_conn_add(hcon, status);
4649 if (conn)
4650 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004651 } else
Joe Perchese1750722011-06-29 18:18:29 -07004652 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004653
4654 return 0;
4655}
4656
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004657int l2cap_disconn_ind(struct hci_conn *hcon)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004658{
4659 struct l2cap_conn *conn = hcon->l2cap_data;
4660
4661 BT_DBG("hcon %p", hcon);
4662
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004663 if (!conn)
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02004664 return HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01004665 return conn->disc_reason;
4666}
4667
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004668int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004669{
4670 BT_DBG("hcon %p reason %d", hcon, reason);
4671
Joe Perchese1750722011-06-29 18:18:29 -07004672 l2cap_conn_del(hcon, bt_to_errno(reason));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004673 return 0;
4674}
4675
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004676static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004677{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004678 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004679 return;
4680
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004681 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004682 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08004683 __set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004684 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004685 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004686 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004687 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004688 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004689 }
4690}
4691
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004692int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004693{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004694 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004695 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004696
Marcel Holtmann01394182006-07-03 10:02:46 +02004697 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004698 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004699
Linus Torvalds1da177e2005-04-16 15:20:36 -07004700 BT_DBG("conn %p", conn);
4701
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004702 if (hcon->type == LE_LINK) {
4703 smp_distribute_keys(conn, 0);
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02004704 cancel_delayed_work(&conn->security_timer);
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004705 }
4706
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004707 mutex_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004708
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004709 list_for_each_entry(chan, &conn->chan_l, list) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004710 l2cap_chan_lock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004711
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004712 BT_DBG("chan->scid %d", chan->scid);
4713
4714 if (chan->scid == L2CAP_CID_LE_DATA) {
4715 if (!status && encrypt) {
4716 chan->sec_level = hcon->sec_level;
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02004717 l2cap_chan_ready(chan);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004718 }
4719
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004720 l2cap_chan_unlock(chan);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004721 continue;
4722 }
4723
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004724 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004725 l2cap_chan_unlock(chan);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004726 continue;
4727 }
4728
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004729 if (!status && (chan->state == BT_CONNECTED ||
4730 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004731 l2cap_check_encryption(chan, encrypt);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004732 l2cap_chan_unlock(chan);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004733 continue;
4734 }
4735
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004736 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004737 if (!status) {
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +02004738 l2cap_send_conn_req(chan);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004739 } else {
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08004740 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004741 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004742 } else if (chan->state == BT_CONNECT2) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004743 struct sock *sk = chan->sk;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004744 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004745 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004746
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004747 lock_sock(sk);
4748
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004749 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004750 if (bt_sk(sk)->defer_setup) {
4751 struct sock *parent = bt_sk(sk)->parent;
4752 res = L2CAP_CR_PEND;
4753 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004754 if (parent)
4755 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004756 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02004757 __l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004758 res = L2CAP_CR_SUCCESS;
4759 stat = L2CAP_CS_NO_INFO;
4760 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004761 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02004762 __l2cap_state_change(chan, BT_DISCONN);
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08004763 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004764 res = L2CAP_CR_SEC_BLOCK;
4765 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004766 }
4767
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004768 release_sock(sk);
4769
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004770 rsp.scid = cpu_to_le16(chan->dcid);
4771 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004772 rsp.result = cpu_to_le16(res);
4773 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004774 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4775 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004776 }
4777
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004778 l2cap_chan_unlock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004779 }
4780
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004781 mutex_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004782
Linus Torvalds1da177e2005-04-16 15:20:36 -07004783 return 0;
4784}
4785
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004786int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004787{
4788 struct l2cap_conn *conn = hcon->l2cap_data;
4789
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004790 if (!conn)
4791 conn = l2cap_conn_add(hcon, 0);
4792
4793 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004794 goto drop;
4795
4796 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4797
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004798 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004799 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004800 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004801 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004802 int len;
4803
4804 if (conn->rx_len) {
4805 BT_ERR("Unexpected start frame (len %d)", skb->len);
4806 kfree_skb(conn->rx_skb);
4807 conn->rx_skb = NULL;
4808 conn->rx_len = 0;
4809 l2cap_conn_unreliable(conn, ECOMM);
4810 }
4811
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004812 /* Start fragment always begin with Basic L2CAP header */
4813 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004814 BT_ERR("Frame is too short (len %d)", skb->len);
4815 l2cap_conn_unreliable(conn, ECOMM);
4816 goto drop;
4817 }
4818
4819 hdr = (struct l2cap_hdr *) skb->data;
4820 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004821 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004822
4823 if (len == skb->len) {
4824 /* Complete frame received */
4825 l2cap_recv_frame(conn, skb);
4826 return 0;
4827 }
4828
4829 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4830
4831 if (skb->len > len) {
4832 BT_ERR("Frame is too long (len %d, expected len %d)",
4833 skb->len, len);
4834 l2cap_conn_unreliable(conn, ECOMM);
4835 goto drop;
4836 }
4837
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004838 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004839
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004840 if (chan && chan->sk) {
4841 struct sock *sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004842 lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004843
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004844 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004845 BT_ERR("Frame exceeding recv MTU (len %d, "
4846 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004847 chan->imtu);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004848 release_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004849 l2cap_conn_unreliable(conn, ECOMM);
4850 goto drop;
4851 }
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004852 release_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004853 }
4854
Linus Torvalds1da177e2005-04-16 15:20:36 -07004855 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004856 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4857 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004858 goto drop;
4859
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004860 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004861 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004862 conn->rx_len = len - skb->len;
4863 } else {
4864 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4865
4866 if (!conn->rx_len) {
4867 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4868 l2cap_conn_unreliable(conn, ECOMM);
4869 goto drop;
4870 }
4871
4872 if (skb->len > conn->rx_len) {
4873 BT_ERR("Fragment is too long (len %d, expected %d)",
4874 skb->len, conn->rx_len);
4875 kfree_skb(conn->rx_skb);
4876 conn->rx_skb = NULL;
4877 conn->rx_len = 0;
4878 l2cap_conn_unreliable(conn, ECOMM);
4879 goto drop;
4880 }
4881
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004882 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004883 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004884 conn->rx_len -= skb->len;
4885
4886 if (!conn->rx_len) {
4887 /* Complete frame received */
4888 l2cap_recv_frame(conn, conn->rx_skb);
4889 conn->rx_skb = NULL;
4890 }
4891 }
4892
4893drop:
4894 kfree_skb(skb);
4895 return 0;
4896}
4897
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004898static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004899{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004900 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004901
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02004902 read_lock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004903
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004904 list_for_each_entry(c, &chan_list, global_l) {
4905 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004906
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004907 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 +01004908 batostr(&bt_sk(sk)->src),
4909 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004910 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004911 c->scid, c->dcid, c->imtu, c->omtu,
4912 c->sec_level, c->mode);
Andrei Emeltchenko61e1b4b2012-01-19 11:19:50 +02004913 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004914
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02004915 read_unlock(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004916
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004917 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004918}
4919
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004920static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4921{
4922 return single_open(file, l2cap_debugfs_show, inode->i_private);
4923}
4924
4925static const struct file_operations l2cap_debugfs_fops = {
4926 .open = l2cap_debugfs_open,
4927 .read = seq_read,
4928 .llseek = seq_lseek,
4929 .release = single_release,
4930};
4931
4932static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004933
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004934int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004935{
4936 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004937
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004938 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004939 if (err < 0)
4940 return err;
4941
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004942 if (bt_debugfs) {
4943 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4944 bt_debugfs, NULL, &l2cap_debugfs_fops);
4945 if (!l2cap_debugfs)
4946 BT_ERR("Failed to create L2CAP debug file");
4947 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004948
Linus Torvalds1da177e2005-04-16 15:20:36 -07004949 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004950}
4951
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004952void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004953{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004954 debugfs_remove(l2cap_debugfs);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004955 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004956}
4957
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004958module_param(disable_ertm, bool, 0644);
4959MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");