blob: 24f144b72a96a87ee5f8fdc2016f613f00615344 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Gustavo F. Padovan590051d2011-12-18 13:39:33 -02006 Copyright (C) 2011 ProFUSION Embedded Systems
Mat Martineau422e9252012-04-27 16:50:55 -07007 Copyright (c) 2012 Code Aurora Forum. All rights reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07008
9 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License version 2 as
13 published by the Free Software Foundation;
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
18 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090019 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
20 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
21 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090024 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
25 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070026 SOFTWARE IS DISCLAIMED.
27*/
28
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020029/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070030
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/module.h>
32
33#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080034#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/errno.h>
36#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/sched.h>
38#include <linux/slab.h>
39#include <linux/poll.h>
40#include <linux/fcntl.h>
41#include <linux/init.h>
42#include <linux/interrupt.h>
43#include <linux/socket.h>
44#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080046#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010047#include <linux/debugfs.h>
48#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030049#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030050#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070051#include <net/sock.h>
52
Linus Torvalds1da177e2005-04-16 15:20:36 -070053#include <asm/unaligned.h>
54
55#include <net/bluetooth/bluetooth.h>
56#include <net/bluetooth/hci_core.h>
57#include <net/bluetooth/l2cap.h>
Anderson Brigliab501d6a2011-06-07 18:46:31 -030058#include <net/bluetooth/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
Rusty Russelleb939922011-12-19 14:08:01 +000060bool disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020061
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070062static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Mat Martineau50a147c2011-11-02 16:18:34 -070063static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Johannes Bergb5ad8b72011-06-01 08:54:45 +020065static LIST_HEAD(chan_list);
66static DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Linus Torvalds1da177e2005-04-16 15:20:36 -070068static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
69 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030070static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
71 void *data);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -030072static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030073static void l2cap_send_disconn_req(struct l2cap_conn *conn,
Gustavo Padovanc5daa682012-05-16 12:17:10 -030074 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
Marcel Holtmann01394182006-07-03 10:02:46 +020076/* ---- L2CAP channels ---- */
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -030077
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030078static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020079{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020080 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030081
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020082 list_for_each_entry(c, &conn->chan_l, list) {
83 if (c->dcid == cid)
84 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020085 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020086 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +020087}
88
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030089static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020090{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020091 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030092
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020093 list_for_each_entry(c, &conn->chan_l, list) {
94 if (c->scid == cid)
95 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020096 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020097 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +020098}
99
100/* Find channel with given SCID.
Mat Martineauef191ad2012-05-02 09:42:00 -0700101 * Returns locked channel. */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300102static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200103{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300104 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300105
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200106 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300107 c = __l2cap_get_chan_by_scid(conn, cid);
Mat Martineauef191ad2012-05-02 09:42:00 -0700108 if (c)
109 l2cap_chan_lock(c);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200110 mutex_unlock(&conn->chan_lock);
111
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300112 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200113}
114
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300115static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200116{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200117 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300118
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200119 list_for_each_entry(c, &conn->chan_l, list) {
120 if (c->ident == ident)
121 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200122 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200123 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200124}
125
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300126static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300127{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300128 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300129
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300130 list_for_each_entry(c, &chan_list, global_l) {
131 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Szymon Janc250938c2011-11-16 09:32:22 +0100132 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300133 }
Szymon Janc250938c2011-11-16 09:32:22 +0100134 return NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300135}
136
137int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
138{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300139 int err;
140
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200141 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300142
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300143 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300144 err = -EADDRINUSE;
145 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300146 }
147
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300148 if (psm) {
149 chan->psm = psm;
150 chan->sport = psm;
151 err = 0;
152 } else {
153 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300154
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300155 err = -EINVAL;
156 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300157 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300158 chan->psm = cpu_to_le16(p);
159 chan->sport = cpu_to_le16(p);
160 err = 0;
161 break;
162 }
163 }
164
165done:
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200166 write_unlock(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300167 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300168}
169
170int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
171{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200172 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300173
174 chan->scid = scid;
175
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200176 write_unlock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300177
178 return 0;
179}
180
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300181static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200182{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300183 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200184
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300185 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300186 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200187 return cid;
188 }
189
190 return 0;
191}
192
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200193static void __l2cap_state_change(struct l2cap_chan *chan, int state)
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300194{
Andrei Emeltchenko42d2d872012-02-17 11:40:57 +0200195 BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
Gustavo F. Padovanbadaaa02011-11-23 20:11:46 -0200196 state_to_string(state));
197
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300198 chan->state = state;
199 chan->ops->state_change(chan->data, state);
200}
201
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200202static void l2cap_state_change(struct l2cap_chan *chan, int state)
203{
204 struct sock *sk = chan->sk;
205
206 lock_sock(sk);
207 __l2cap_state_change(chan, state);
208 release_sock(sk);
209}
210
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +0200211static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err)
212{
213 struct sock *sk = chan->sk;
214
215 sk->sk_err = err;
216}
217
218static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
219{
220 struct sock *sk = chan->sk;
221
222 lock_sock(sk);
223 __l2cap_chan_set_err(chan, err);
224 release_sock(sk);
225}
226
Mat Martineau3c588192012-04-11 10:48:42 -0700227/* ---- L2CAP sequence number lists ---- */
228
229/* For ERTM, ordered lists of sequence numbers must be tracked for
230 * SREJ requests that are received and for frames that are to be
231 * retransmitted. These seq_list functions implement a singly-linked
232 * list in an array, where membership in the list can also be checked
233 * in constant time. Items can also be added to the tail of the list
234 * and removed from the head in constant time, without further memory
235 * allocs or frees.
236 */
237
238static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
239{
240 size_t alloc_size, i;
241
242 /* Allocated size is a power of 2 to map sequence numbers
243 * (which may be up to 14 bits) in to a smaller array that is
244 * sized for the negotiated ERTM transmit windows.
245 */
246 alloc_size = roundup_pow_of_two(size);
247
248 seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL);
249 if (!seq_list->list)
250 return -ENOMEM;
251
252 seq_list->mask = alloc_size - 1;
253 seq_list->head = L2CAP_SEQ_LIST_CLEAR;
254 seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
255 for (i = 0; i < alloc_size; i++)
256 seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
257
258 return 0;
259}
260
261static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
262{
263 kfree(seq_list->list);
264}
265
266static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
267 u16 seq)
268{
269 /* Constant-time check for list membership */
270 return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
271}
272
273static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq)
274{
275 u16 mask = seq_list->mask;
276
277 if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) {
278 /* In case someone tries to pop the head of an empty list */
279 return L2CAP_SEQ_LIST_CLEAR;
280 } else if (seq_list->head == seq) {
281 /* Head can be removed in constant time */
282 seq_list->head = seq_list->list[seq & mask];
283 seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
284
285 if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
286 seq_list->head = L2CAP_SEQ_LIST_CLEAR;
287 seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
288 }
289 } else {
290 /* Walk the list to find the sequence number */
291 u16 prev = seq_list->head;
292 while (seq_list->list[prev & mask] != seq) {
293 prev = seq_list->list[prev & mask];
294 if (prev == L2CAP_SEQ_LIST_TAIL)
295 return L2CAP_SEQ_LIST_CLEAR;
296 }
297
298 /* Unlink the number from the list and clear it */
299 seq_list->list[prev & mask] = seq_list->list[seq & mask];
300 seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
301 if (seq_list->tail == seq)
302 seq_list->tail = prev;
303 }
304 return seq;
305}
306
307static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
308{
309 /* Remove the head in constant time */
310 return l2cap_seq_list_remove(seq_list, seq_list->head);
311}
312
313static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
314{
Gustavo Padovanf522ae32012-05-09 18:28:00 -0300315 u16 i;
Mat Martineau3c588192012-04-11 10:48:42 -0700316
Gustavo Padovanf522ae32012-05-09 18:28:00 -0300317 if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
318 return;
319
320 for (i = 0; i <= seq_list->mask; i++)
321 seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
322
323 seq_list->head = L2CAP_SEQ_LIST_CLEAR;
324 seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
Mat Martineau3c588192012-04-11 10:48:42 -0700325}
326
327static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
328{
329 u16 mask = seq_list->mask;
330
331 /* All appends happen in constant time */
332
Gustavo Padovanf522ae32012-05-09 18:28:00 -0300333 if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
334 return;
Mat Martineau3c588192012-04-11 10:48:42 -0700335
Gustavo Padovanf522ae32012-05-09 18:28:00 -0300336 if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
337 seq_list->head = seq;
338 else
339 seq_list->list[seq_list->tail & mask] = seq;
340
341 seq_list->tail = seq;
342 seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
Mat Martineau3c588192012-04-11 10:48:42 -0700343}
344
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300345static void l2cap_chan_timeout(struct work_struct *work)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300346{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300347 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
348 chan_timer.work);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200349 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300350 int reason;
351
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200352 BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300353
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200354 mutex_lock(&conn->chan_lock);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200355 l2cap_chan_lock(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300356
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300357 if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300358 reason = ECONNREFUSED;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300359 else if (chan->state == BT_CONNECT &&
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300360 chan->sec_level != BT_SECURITY_SDP)
361 reason = ECONNREFUSED;
362 else
363 reason = ETIMEDOUT;
364
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300365 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300366
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200367 l2cap_chan_unlock(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300368
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300369 chan->ops->close(chan->data);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200370 mutex_unlock(&conn->chan_lock);
371
Ulisses Furquim371fd832011-12-21 20:02:36 -0200372 l2cap_chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300373}
374
Gustavo Padovaneef1d9b2012-03-25 13:59:16 -0300375struct l2cap_chan *l2cap_chan_create(void)
Marcel Holtmann01394182006-07-03 10:02:46 +0200376{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300377 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200378
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300379 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
380 if (!chan)
381 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200382
Andrei Emeltchenkoc03b3552012-02-21 12:54:56 +0200383 mutex_init(&chan->lock);
384
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200385 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300386 list_add(&chan->global_l, &chan_list);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200387 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300388
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300389 INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300390
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300391 chan->state = BT_OPEN;
392
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300393 atomic_set(&chan->refcnt, 1);
394
Gustavo Padovaneef1d9b2012-03-25 13:59:16 -0300395 BT_DBG("chan %p", chan);
Szymon Jancabc545b2011-11-03 16:05:44 +0100396
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300397 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200398}
399
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300400void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300401{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200402 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300403 list_del(&chan->global_l);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200404 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300405
Ulisses Furquim371fd832011-12-21 20:02:36 -0200406 l2cap_chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300407}
408
Andrei Emeltchenkobd4b1652012-03-28 16:31:25 +0300409void l2cap_chan_set_defaults(struct l2cap_chan *chan)
410{
411 chan->fcs = L2CAP_FCS_CRC16;
412 chan->max_tx = L2CAP_DEFAULT_MAX_TX;
413 chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
414 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
415 chan->sec_level = BT_SECURITY_LOW;
416
417 set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
418}
419
Andrei Emeltchenko14a28492012-03-23 16:31:49 +0200420static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200421{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300422 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Andrei Emeltchenko097db762012-03-09 14:16:17 +0200423 __le16_to_cpu(chan->psm), chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200424
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +0200425 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +0100426
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300427 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200428
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200429 switch (chan->chan_type) {
430 case L2CAP_CHAN_CONN_ORIENTED:
Ville Tervob62f3282011-02-10 22:38:50 -0300431 if (conn->hcon->type == LE_LINK) {
432 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300433 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300434 chan->scid = L2CAP_CID_LE_DATA;
435 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300436 } else {
437 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300438 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300439 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300440 }
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200441 break;
442
443 case L2CAP_CHAN_CONN_LESS:
Marcel Holtmann01394182006-07-03 10:02:46 +0200444 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300445 chan->scid = L2CAP_CID_CONN_LESS;
446 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300447 chan->omtu = L2CAP_DEFAULT_MTU;
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200448 break;
449
450 default:
Marcel Holtmann01394182006-07-03 10:02:46 +0200451 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300452 chan->scid = L2CAP_CID_SIGNALING;
453 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300454 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200455 }
456
Andrei Emeltchenko8f7975b2011-10-13 16:18:54 +0300457 chan->local_id = L2CAP_BESTEFFORT_ID;
458 chan->local_stype = L2CAP_SERV_BESTEFFORT;
459 chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
460 chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
461 chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
462 chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
463
Ulisses Furquim371fd832011-12-21 20:02:36 -0200464 l2cap_chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300465
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200466 list_add(&chan->list, &conn->chan_l);
Andrei Emeltchenko643162a2012-02-22 17:11:55 +0200467}
468
Andrei Emeltchenko14a28492012-03-23 16:31:49 +0200469static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Andrei Emeltchenko643162a2012-02-22 17:11:55 +0200470{
471 mutex_lock(&conn->chan_lock);
472 __l2cap_chan_add(conn, chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200473 mutex_unlock(&conn->chan_lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200474}
475
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300476static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200477{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300478 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300479 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200480 struct sock *parent = bt_sk(sk)->parent;
481
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300482 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200483
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300484 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200485
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900486 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300487 /* Delete from channel list */
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200488 list_del(&chan->list);
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200489
Ulisses Furquim371fd832011-12-21 20:02:36 -0200490 l2cap_chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300491
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300492 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200493 hci_conn_put(conn->hcon);
494 }
495
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200496 lock_sock(sk);
497
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200498 __l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200499 sock_set_flag(sk, SOCK_ZAPPED);
500
501 if (err)
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +0200502 __l2cap_chan_set_err(chan, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200503
504 if (parent) {
505 bt_accept_unlink(sk);
506 parent->sk_data_ready(parent, 0);
507 } else
508 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300509
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200510 release_sock(sk);
511
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300512 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
513 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300514 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300515
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300516 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300517
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300518 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300519 struct srej_list *l, *tmp;
520
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300521 __clear_retrans_timer(chan);
522 __clear_monitor_timer(chan);
523 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300524
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300525 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300526
Mat Martineau3c588192012-04-11 10:48:42 -0700527 l2cap_seq_list_free(&chan->srej_list);
528 l2cap_seq_list_free(&chan->retrans_list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300529 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300530 list_del(&l->list);
531 kfree(l);
532 }
533 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200534}
535
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300536static void l2cap_chan_cleanup_listen(struct sock *parent)
537{
538 struct sock *sk;
539
540 BT_DBG("parent %p", parent);
541
542 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300543 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300544 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200545
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200546 l2cap_chan_lock(chan);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300547 __clear_chan_timer(chan);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300548 l2cap_chan_close(chan, ECONNRESET);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200549 l2cap_chan_unlock(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200550
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300551 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300552 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300553}
554
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300555void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300556{
557 struct l2cap_conn *conn = chan->conn;
558 struct sock *sk = chan->sk;
559
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200560 BT_DBG("chan %p state %s sk %p", chan,
561 state_to_string(chan->state), sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300562
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300563 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300564 case BT_LISTEN:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200565 lock_sock(sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300566 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300567
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200568 __l2cap_state_change(chan, BT_CLOSED);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300569 sock_set_flag(sk, SOCK_ZAPPED);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200570 release_sock(sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300571 break;
572
573 case BT_CONNECTED:
574 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300575 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300576 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300577 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300578 l2cap_send_disconn_req(conn, chan, reason);
579 } else
580 l2cap_chan_del(chan, reason);
581 break;
582
583 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300584 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300585 conn->hcon->type == ACL_LINK) {
586 struct l2cap_conn_rsp rsp;
587 __u16 result;
588
Gustavo Padovanc5daa682012-05-16 12:17:10 -0300589 if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300590 result = L2CAP_CR_SEC_BLOCK;
591 else
592 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300593 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300594
595 rsp.scid = cpu_to_le16(chan->dcid);
596 rsp.dcid = cpu_to_le16(chan->scid);
597 rsp.result = cpu_to_le16(result);
598 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
599 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
600 sizeof(rsp), &rsp);
601 }
602
603 l2cap_chan_del(chan, reason);
604 break;
605
606 case BT_CONNECT:
607 case BT_DISCONN:
608 l2cap_chan_del(chan, reason);
609 break;
610
611 default:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200612 lock_sock(sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300613 sock_set_flag(sk, SOCK_ZAPPED);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200614 release_sock(sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300615 break;
616 }
617}
618
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300619static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530620{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300621 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300622 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530623 case BT_SECURITY_HIGH:
624 return HCI_AT_DEDICATED_BONDING_MITM;
625 case BT_SECURITY_MEDIUM:
626 return HCI_AT_DEDICATED_BONDING;
627 default:
628 return HCI_AT_NO_BONDING;
629 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300630 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300631 if (chan->sec_level == BT_SECURITY_LOW)
632 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530633
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300634 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530635 return HCI_AT_NO_BONDING_MITM;
636 else
637 return HCI_AT_NO_BONDING;
638 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300639 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530640 case BT_SECURITY_HIGH:
641 return HCI_AT_GENERAL_BONDING_MITM;
642 case BT_SECURITY_MEDIUM:
643 return HCI_AT_GENERAL_BONDING;
644 default:
645 return HCI_AT_NO_BONDING;
646 }
647 }
648}
649
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200650/* Service level security */
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200651int l2cap_chan_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200652{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300653 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100654 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200655
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300656 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100657
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300658 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200659}
660
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200661static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200662{
663 u8 id;
664
665 /* Get next available identificator.
666 * 1 - 128 are used by kernel.
667 * 129 - 199 are reserved.
668 * 200 - 254 are used by utilities like l2ping, etc.
669 */
670
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200671 spin_lock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200672
673 if (++conn->tx_ident > 128)
674 conn->tx_ident = 1;
675
676 id = conn->tx_ident;
677
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200678 spin_unlock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200679
680 return id;
681}
682
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300683static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200684{
685 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200686 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200687
688 BT_DBG("code 0x%2.2x", code);
689
690 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300691 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200692
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200693 if (lmp_no_flush_capable(conn->hcon->hdev))
694 flags = ACL_START_NO_FLUSH;
695 else
696 flags = ACL_START;
697
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700698 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +0200699 skb->priority = HCI_PRIO_MAX;
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700700
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200701 hci_send_acl(conn->hchan, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200702}
703
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200704static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
705{
706 struct hci_conn *hcon = chan->conn->hcon;
707 u16 flags;
708
709 BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
710 skb->priority);
711
712 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
713 lmp_no_flush_capable(hcon->hdev))
714 flags = ACL_START_NO_FLUSH;
715 else
716 flags = ACL_START;
717
718 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
719 hci_send_acl(chan->conn->hchan, skb, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720}
721
Mat Martineaub5c6aae2012-04-25 16:36:15 -0700722static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
723{
724 control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
725 control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
726
727 if (enh & L2CAP_CTRL_FRAME_TYPE) {
728 /* S-Frame */
729 control->sframe = 1;
730 control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
731 control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
732
733 control->sar = 0;
734 control->txseq = 0;
735 } else {
736 /* I-Frame */
737 control->sframe = 0;
738 control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
739 control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
740
741 control->poll = 0;
742 control->super = 0;
743 }
744}
745
746static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
747{
748 control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
749 control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
750
751 if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
752 /* S-Frame */
753 control->sframe = 1;
754 control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
755 control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
756
757 control->sar = 0;
758 control->txseq = 0;
759 } else {
760 /* I-Frame */
761 control->sframe = 0;
762 control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
763 control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
764
765 control->poll = 0;
766 control->super = 0;
767 }
768}
769
770static inline void __unpack_control(struct l2cap_chan *chan,
771 struct sk_buff *skb)
772{
773 if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
774 __unpack_extended_control(get_unaligned_le32(skb->data),
775 &bt_cb(skb)->control);
776 } else {
777 __unpack_enhanced_control(get_unaligned_le16(skb->data),
778 &bt_cb(skb)->control);
779 }
780}
781
782static u32 __pack_extended_control(struct l2cap_ctrl *control)
783{
784 u32 packed;
785
786 packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
787 packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
788
789 if (control->sframe) {
790 packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
791 packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
792 packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
793 } else {
794 packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
795 packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
796 }
797
798 return packed;
799}
800
801static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
802{
803 u16 packed;
804
805 packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
806 packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
807
808 if (control->sframe) {
809 packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
810 packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
811 packed |= L2CAP_CTRL_FRAME_TYPE;
812 } else {
813 packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
814 packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
815 }
816
817 return packed;
818}
819
820static inline void __pack_control(struct l2cap_chan *chan,
821 struct l2cap_ctrl *control,
822 struct sk_buff *skb)
823{
824 if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
825 put_unaligned_le32(__pack_extended_control(control),
826 skb->data + L2CAP_HDR_SIZE);
827 } else {
828 put_unaligned_le16(__pack_enhanced_control(control),
829 skb->data + L2CAP_HDR_SIZE);
830 }
831}
832
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300833static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300834{
835 struct sk_buff *skb;
836 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300837 struct l2cap_conn *conn = chan->conn;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300838 int count, hlen;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300839
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300840 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300841 return;
842
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300843 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
844 hlen = L2CAP_EXT_HDR_SIZE;
845 else
846 hlen = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300847
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300848 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300849 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300850
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300851 BT_DBG("chan %p, control 0x%8.8x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300852
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300853 count = min_t(unsigned int, conn->mtu, hlen);
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +0300854
855 control |= __set_sframe(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300856
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300857 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +0300858 control |= __set_ctrl_final(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300859
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300860 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +0300861 control |= __set_ctrl_poll(chan);
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300862
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300863 skb = bt_skb_alloc(count, GFP_ATOMIC);
864 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300865 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300866
867 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300868 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300869 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300870
871 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300872
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300873 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300874 u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
875 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300876 }
877
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200878 skb->priority = HCI_PRIO_MAX;
879 l2cap_do_send(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300880}
881
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300882static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300883{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300884 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300885 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300886 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300887 } else
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300888 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300889
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300890 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300891
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300892 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300893}
894
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300895static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300896{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300897 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300898}
899
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +0200900static void l2cap_send_conn_req(struct l2cap_chan *chan)
901{
902 struct l2cap_conn *conn = chan->conn;
903 struct l2cap_conn_req req;
904
905 req.scid = cpu_to_le16(chan->scid);
906 req.psm = chan->psm;
907
908 chan->ident = l2cap_get_ident(conn);
909
910 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
911
912 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
913}
914
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300915static void l2cap_chan_ready(struct l2cap_chan *chan)
916{
917 struct sock *sk = chan->sk;
918 struct sock *parent;
919
920 lock_sock(sk);
921
922 parent = bt_sk(sk)->parent;
923
924 BT_DBG("sk %p, parent %p", sk, parent);
925
926 chan->conf_state = 0;
927 __clear_chan_timer(chan);
928
929 __l2cap_state_change(chan, BT_CONNECTED);
930 sk->sk_state_change(sk);
931
932 if (parent)
933 parent->sk_data_ready(parent, 0);
934
935 release_sock(sk);
936}
937
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300938static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200939{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300940 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200941
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300942 if (conn->hcon->type == LE_LINK) {
943 l2cap_chan_ready(chan);
944 return;
945 }
946
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200947 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100948 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
949 return;
950
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200951 if (l2cap_chan_check_security(chan) &&
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +0200952 __l2cap_no_conn_pending(chan))
953 l2cap_send_conn_req(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200954 } else {
955 struct l2cap_info_req req;
956 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
957
958 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
959 conn->info_ident = l2cap_get_ident(conn);
960
Marcel Holtmannba13ccd2012-03-01 14:25:33 -0800961 schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200962
963 l2cap_send_cmd(conn, conn->info_ident,
964 L2CAP_INFO_REQ, sizeof(req), &req);
965 }
966}
967
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300968static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
969{
970 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300971 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300972 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
973
974 switch (mode) {
975 case L2CAP_MODE_ERTM:
976 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
977 case L2CAP_MODE_STREAMING:
978 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
979 default:
980 return 0x00;
981 }
982}
983
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300984static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300985{
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200986 struct sock *sk = chan->sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300987 struct l2cap_disconn_req req;
988
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300989 if (!conn)
990 return;
991
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300992 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300993 __clear_retrans_timer(chan);
994 __clear_monitor_timer(chan);
995 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300996 }
997
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300998 req.dcid = cpu_to_le16(chan->dcid);
999 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -03001000 l2cap_send_cmd(conn, l2cap_get_ident(conn),
1001 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001002
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001003 lock_sock(sk);
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001004 __l2cap_state_change(chan, BT_DISCONN);
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +02001005 __l2cap_chan_set_err(chan, err);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001006 release_sock(sk);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -03001007}
1008
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001010static void l2cap_conn_start(struct l2cap_conn *conn)
1011{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001012 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001013
1014 BT_DBG("conn %p", conn);
1015
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001016 mutex_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001017
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001018 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001019 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001020
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001021 l2cap_chan_lock(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001022
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001023 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001024 l2cap_chan_unlock(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001025 continue;
1026 }
1027
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001028 if (chan->state == BT_CONNECT) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001029 if (!l2cap_chan_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001030 !__l2cap_no_conn_pending(chan)) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001031 l2cap_chan_unlock(chan);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -03001032 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02001033 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -03001034
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001035 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1036 && test_bit(CONF_STATE2_DEVICE,
1037 &chan->conf_state)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001038 l2cap_chan_close(chan, ECONNRESET);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001039 l2cap_chan_unlock(chan);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -03001040 continue;
1041 }
1042
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +02001043 l2cap_send_conn_req(chan);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -03001044
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001045 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001046 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001047 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001048 rsp.scid = cpu_to_le16(chan->dcid);
1049 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001050
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001051 if (l2cap_chan_check_security(chan)) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001052 lock_sock(sk);
Gustavo Padovanc5daa682012-05-16 12:17:10 -03001053 if (test_bit(BT_SK_DEFER_SETUP,
1054 &bt_sk(sk)->flags)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001055 struct sock *parent = bt_sk(sk)->parent;
1056 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1057 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00001058 if (parent)
1059 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001060
1061 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001062 __l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001063 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1064 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1065 }
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001066 release_sock(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001067 } else {
1068 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1069 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
1070 }
1071
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001072 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1073 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001074
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001075 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001076 rsp.result != L2CAP_CR_SUCCESS) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001077 l2cap_chan_unlock(chan);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001078 continue;
1079 }
1080
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001081 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001082 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001083 l2cap_build_conf_req(chan, buf), buf);
1084 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001085 }
1086
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001087 l2cap_chan_unlock(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001088 }
1089
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001090 mutex_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001091}
1092
Ido Yarivc2287682012-04-20 15:46:07 -03001093/* Find socket with cid and source/destination bdaddr.
Ville Tervob62f3282011-02-10 22:38:50 -03001094 * Returns closest match, locked.
1095 */
Andrei Emeltchenkod9b88702012-03-12 12:13:08 +02001096static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
Ido Yarivc2287682012-04-20 15:46:07 -03001097 bdaddr_t *src,
1098 bdaddr_t *dst)
Ville Tervob62f3282011-02-10 22:38:50 -03001099{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001100 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -03001101
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001102 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -03001103
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001104 list_for_each_entry(c, &chan_list, global_l) {
1105 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001106
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001107 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -03001108 continue;
1109
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001110 if (c->scid == cid) {
Ido Yarivc2287682012-04-20 15:46:07 -03001111 int src_match, dst_match;
1112 int src_any, dst_any;
1113
Ville Tervob62f3282011-02-10 22:38:50 -03001114 /* Exact match. */
Ido Yarivc2287682012-04-20 15:46:07 -03001115 src_match = !bacmp(&bt_sk(sk)->src, src);
1116 dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1117 if (src_match && dst_match) {
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001118 read_unlock(&chan_list_lock);
1119 return c;
1120 }
Ville Tervob62f3282011-02-10 22:38:50 -03001121
1122 /* Closest match */
Ido Yarivc2287682012-04-20 15:46:07 -03001123 src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1124 dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1125 if ((src_match && dst_any) || (src_any && dst_match) ||
1126 (src_any && dst_any))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001127 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -03001128 }
1129 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -03001130
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001131 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -03001132
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001133 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -03001134}
1135
1136static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1137{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -03001138 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001139 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -03001140
1141 BT_DBG("");
1142
1143 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001144 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ido Yarivc2287682012-04-20 15:46:07 -03001145 conn->src, conn->dst);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001146 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -03001147 return;
1148
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001149 parent = pchan->sk;
1150
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001151 lock_sock(parent);
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -03001152
Ville Tervob62f3282011-02-10 22:38:50 -03001153 /* Check for backlog size */
1154 if (sk_acceptq_is_full(parent)) {
1155 BT_DBG("backlog full %d", parent->sk_ack_backlog);
1156 goto clean;
1157 }
1158
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03001159 chan = pchan->ops->new_connection(pchan->data);
1160 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -03001161 goto clean;
1162
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03001163 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001164
Ville Tervob62f3282011-02-10 22:38:50 -03001165 hci_conn_hold(conn->hcon);
1166
Ville Tervob62f3282011-02-10 22:38:50 -03001167 bacpy(&bt_sk(sk)->src, conn->src);
1168 bacpy(&bt_sk(sk)->dst, conn->dst);
1169
Gustavo F. Padovand1010242011-03-25 00:39:48 -03001170 bt_accept_enqueue(parent, sk);
1171
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001172 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001173
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001174 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -03001175
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001176 __l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -03001177 parent->sk_data_ready(parent, 0);
1178
Ville Tervob62f3282011-02-10 22:38:50 -03001179clean:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001180 release_sock(parent);
Ville Tervob62f3282011-02-10 22:38:50 -03001181}
1182
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001183static void l2cap_conn_ready(struct l2cap_conn *conn)
1184{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001185 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001186
1187 BT_DBG("conn %p", conn);
1188
Ville Tervob62f3282011-02-10 22:38:50 -03001189 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
1190 l2cap_le_conn_ready(conn);
1191
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03001192 if (conn->hcon->out && conn->hcon->type == LE_LINK)
1193 smp_conn_security(conn, conn->hcon->pending_sec_level);
1194
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001195 mutex_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001196
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001197 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001198
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001199 l2cap_chan_lock(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001200
Vinicius Costa Gomes63128452011-06-17 22:46:26 -03001201 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -03001202 if (smp_conn_security(conn, chan->sec_level))
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02001203 l2cap_chan_ready(chan);
Ville Tervoacd7d372011-02-10 22:38:49 -03001204
Vinicius Costa Gomes63128452011-06-17 22:46:26 -03001205 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001206 struct sock *sk = chan->sk;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001207 __clear_chan_timer(chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001208 lock_sock(sk);
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001209 __l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001210 sk->sk_state_change(sk);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001211 release_sock(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -03001212
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001213 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001214 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001215
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001216 l2cap_chan_unlock(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001217 }
1218
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001219 mutex_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001220}
1221
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001222/* Notify sockets that we cannot guaranty reliability anymore */
1223static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
1224{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001225 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001226
1227 BT_DBG("conn %p", conn);
1228
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001229 mutex_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001230
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001231 list_for_each_entry(chan, &conn->chan_l, list) {
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +03001232 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +02001233 __l2cap_chan_set_err(chan, err);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001234 }
1235
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001236 mutex_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001237}
1238
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -02001239static void l2cap_info_timeout(struct work_struct *work)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001240{
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -02001241 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02001242 info_timer.work);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001243
Marcel Holtmann984947d2009-02-06 23:35:19 +01001244 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01001245 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01001246
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001247 l2cap_conn_start(conn);
1248}
1249
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001250static void l2cap_conn_del(struct hci_conn *hcon, int err)
1251{
1252 struct l2cap_conn *conn = hcon->l2cap_data;
1253 struct l2cap_chan *chan, *l;
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001254
1255 if (!conn)
1256 return;
1257
1258 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
1259
1260 kfree_skb(conn->rx_skb);
1261
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001262 mutex_lock(&conn->chan_lock);
1263
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001264 /* Kill channels */
1265 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Mat Martineau61d6ef32012-04-27 16:50:50 -07001266 l2cap_chan_hold(chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001267 l2cap_chan_lock(chan);
1268
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001269 l2cap_chan_del(chan, err);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001270
1271 l2cap_chan_unlock(chan);
1272
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001273 chan->ops->close(chan->data);
Mat Martineau61d6ef32012-04-27 16:50:50 -07001274 l2cap_chan_put(chan);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001275 }
1276
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001277 mutex_unlock(&conn->chan_lock);
1278
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001279 hci_chan_del(conn->hchan);
1280
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001281 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
Ulisses Furquim127074b2012-01-30 18:26:29 -02001282 cancel_delayed_work_sync(&conn->info_timer);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001283
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001284 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
Ulisses Furquim127074b2012-01-30 18:26:29 -02001285 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001286 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001287 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001288
1289 hcon->l2cap_data = NULL;
1290 kfree(conn);
1291}
1292
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001293static void security_timeout(struct work_struct *work)
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001294{
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001295 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1296 security_timer.work);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001297
1298 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1299}
1300
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1302{
Marcel Holtmann01394182006-07-03 10:02:46 +02001303 struct l2cap_conn *conn = hcon->l2cap_data;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001304 struct hci_chan *hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305
Marcel Holtmann01394182006-07-03 10:02:46 +02001306 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 return conn;
1308
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001309 hchan = hci_chan_create(hcon);
1310 if (!hchan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001313 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1314 if (!conn) {
1315 hci_chan_del(hchan);
1316 return NULL;
1317 }
1318
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 hcon->l2cap_data = conn;
1320 conn->hcon = hcon;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001321 conn->hchan = hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001323 BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
Marcel Holtmann01394182006-07-03 10:02:46 +02001324
Ville Tervoacd7d372011-02-10 22:38:49 -03001325 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1326 conn->mtu = hcon->hdev->le_mtu;
1327 else
1328 conn->mtu = hcon->hdev->acl_mtu;
1329
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 conn->src = &hcon->hdev->bdaddr;
1331 conn->dst = &hcon->dst;
1332
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001333 conn->feat_mask = 0;
1334
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 spin_lock_init(&conn->lock);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001336 mutex_init(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001337
1338 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001340 if (hcon->type == LE_LINK)
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001341 INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001342 else
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02001343 INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
Dave Young45054dc2009-10-18 20:28:30 +00001344
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001345 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01001346
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 return conn;
1348}
1349
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
Ido Yarivc2287682012-04-20 15:46:07 -03001352/* Find socket with psm and source / destination bdaddr.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 * Returns closest match.
1354 */
Ido Yarivc2287682012-04-20 15:46:07 -03001355static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1356 bdaddr_t *src,
1357 bdaddr_t *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001359 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001361 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001362
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001363 list_for_each_entry(c, &chan_list, global_l) {
1364 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001365
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001366 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 continue;
1368
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001369 if (c->psm == psm) {
Ido Yarivc2287682012-04-20 15:46:07 -03001370 int src_match, dst_match;
1371 int src_any, dst_any;
1372
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 /* Exact match. */
Ido Yarivc2287682012-04-20 15:46:07 -03001374 src_match = !bacmp(&bt_sk(sk)->src, src);
1375 dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1376 if (src_match && dst_match) {
Johannes Berga7567b22011-06-01 08:29:54 +02001377 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001378 return c;
1379 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380
1381 /* Closest match */
Ido Yarivc2287682012-04-20 15:46:07 -03001382 src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1383 dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1384 if ((src_match && dst_any) || (src_any && dst_match) ||
1385 (src_any && dst_any))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001386 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 }
1388 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001390 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001391
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001392 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393}
1394
Andre Guedes8e9f9892012-04-24 21:02:55 -03001395int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
1396 bdaddr_t *dst, u8 dst_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001398 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 bdaddr_t *src = &bt_sk(sk)->src;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400 struct l2cap_conn *conn;
1401 struct hci_conn *hcon;
1402 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001403 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001404 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405
Andre Guedes8e9f9892012-04-24 21:02:55 -03001406 BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst),
1407 dst_type, __le16_to_cpu(chan->psm));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001409 hdev = hci_get_route(dst, src);
1410 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 return -EHOSTUNREACH;
1412
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001413 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001415 l2cap_chan_lock(chan);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001416
1417 /* PSM must be odd and lsb of upper byte must be 0 */
1418 if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
1419 chan->chan_type != L2CAP_CHAN_RAW) {
1420 err = -EINVAL;
1421 goto done;
1422 }
1423
1424 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
1425 err = -EINVAL;
1426 goto done;
1427 }
1428
1429 switch (chan->mode) {
1430 case L2CAP_MODE_BASIC:
1431 break;
1432 case L2CAP_MODE_ERTM:
1433 case L2CAP_MODE_STREAMING:
1434 if (!disable_ertm)
1435 break;
1436 /* fall through */
1437 default:
1438 err = -ENOTSUPP;
1439 goto done;
1440 }
1441
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001442 lock_sock(sk);
1443
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001444 switch (sk->sk_state) {
1445 case BT_CONNECT:
1446 case BT_CONNECT2:
1447 case BT_CONFIG:
1448 /* Already connecting */
1449 err = 0;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001450 release_sock(sk);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001451 goto done;
1452
1453 case BT_CONNECTED:
1454 /* Already connected */
1455 err = -EISCONN;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001456 release_sock(sk);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001457 goto done;
1458
1459 case BT_OPEN:
1460 case BT_BOUND:
1461 /* Can connect */
1462 break;
1463
1464 default:
1465 err = -EBADFD;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001466 release_sock(sk);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001467 goto done;
1468 }
1469
1470 /* Set destination address and psm */
Gustavo F. Padovan9219b2a2012-01-02 20:08:04 -02001471 bacpy(&bt_sk(sk)->dst, dst);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001472
1473 release_sock(sk);
1474
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001475 chan->psm = psm;
1476 chan->dcid = cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001478 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001479
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001480 if (chan->dcid == L2CAP_CID_LE_DATA)
Andre Guedes8e9f9892012-04-24 21:02:55 -03001481 hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
Andre Guedesb12f62c2012-04-24 21:02:54 -03001482 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001483 else
Andre Guedes8e9f9892012-04-24 21:02:55 -03001484 hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
Andre Guedesb12f62c2012-04-24 21:02:54 -03001485 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001486
Ville Tervo30e76272011-02-22 16:10:53 -03001487 if (IS_ERR(hcon)) {
1488 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001490 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491
1492 conn = l2cap_conn_add(hcon, 0);
1493 if (!conn) {
1494 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001495 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 goto done;
1497 }
1498
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -03001499 if (hcon->type == LE_LINK) {
1500 err = 0;
1501
1502 if (!list_empty(&conn->chan_l)) {
1503 err = -EBUSY;
1504 hci_conn_put(hcon);
1505 }
1506
1507 if (err)
1508 goto done;
1509 }
1510
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 /* Update source addr of the socket */
1512 bacpy(src, conn->src);
1513
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001514 l2cap_chan_unlock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001515 l2cap_chan_add(conn, chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001516 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001517
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001518 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001519 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520
1521 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001522 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001523 __clear_chan_timer(chan);
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001524 if (l2cap_chan_check_security(chan))
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001525 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001526 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001527 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 }
1529
Ville Tervo30e76272011-02-22 16:10:53 -03001530 err = 0;
1531
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532done:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001533 l2cap_chan_unlock(chan);
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001534 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535 hci_dev_put(hdev);
1536 return err;
1537}
1538
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001539int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001540{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001541 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001542 DECLARE_WAITQUEUE(wait, current);
1543 int err = 0;
1544 int timeo = HZ/5;
1545
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001546 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001547 set_current_state(TASK_INTERRUPTIBLE);
1548 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001549 if (!timeo)
1550 timeo = HZ/5;
1551
1552 if (signal_pending(current)) {
1553 err = sock_intr_errno(timeo);
1554 break;
1555 }
1556
1557 release_sock(sk);
1558 timeo = schedule_timeout(timeo);
1559 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001560 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001561
1562 err = sock_error(sk);
1563 if (err)
1564 break;
1565 }
1566 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001567 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001568 return err;
1569}
1570
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001571static void l2cap_monitor_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001572{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001573 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1574 monitor_timer.work);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001575
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001576 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001577
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001578 l2cap_chan_lock(chan);
1579
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001580 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001581 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001582 l2cap_chan_unlock(chan);
Andrei Emeltchenko8d7e1c72012-03-23 09:42:15 +02001583 l2cap_chan_put(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001584 return;
1585 }
1586
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001587 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001588 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001589
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001590 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001591 l2cap_chan_unlock(chan);
Andrei Emeltchenko8d7e1c72012-03-23 09:42:15 +02001592 l2cap_chan_put(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001593}
1594
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001595static void l2cap_retrans_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001596{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001597 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1598 retrans_timer.work);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001599
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001600 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001601
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001602 l2cap_chan_lock(chan);
1603
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001604 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001605 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001606
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001607 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001608
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001609 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001610
1611 l2cap_chan_unlock(chan);
Andrei Emeltchenko8d7e1c72012-03-23 09:42:15 +02001612 l2cap_chan_put(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001613}
1614
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001615static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001616{
1617 struct sk_buff *skb;
1618
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001619 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001620 chan->unacked_frames) {
Mat Martineau3ce35142012-04-25 16:36:14 -07001621 if (bt_cb(skb)->control.txseq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001622 break;
1623
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001624 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001625 kfree_skb(skb);
1626
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001627 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001628 }
1629
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001630 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001631 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001632}
1633
Szymon Janc67c9e842011-07-28 16:24:33 +02001634static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001635{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001636 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001637 u32 control;
1638 u16 fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001639
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001640 while ((skb = skb_dequeue(&chan->tx_q))) {
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001641 control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001642 control |= __set_txseq(chan, chan->next_tx_seq);
Mat Martineau94122bb2012-05-02 09:42:02 -07001643 control |= __set_ctrl_sar(chan, bt_cb(skb)->control.sar);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001644 __put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001645
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001646 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001647 fcs = crc16(0, (u8 *)skb->data,
1648 skb->len - L2CAP_FCS_SIZE);
1649 put_unaligned_le16(fcs,
1650 skb->data + skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001651 }
1652
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001653 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001654
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001655 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001656 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001657}
1658
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001659static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001660{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001661 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001662 u16 fcs;
1663 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001664
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001665 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001666 if (!skb)
1667 return;
1668
Mat Martineau3ce35142012-04-25 16:36:14 -07001669 while (bt_cb(skb)->control.txseq != tx_seq) {
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001670 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001671 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001672
Szymon Jancd1726b62011-11-16 09:32:20 +01001673 skb = skb_queue_next(&chan->tx_q, skb);
1674 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001675
Mat Martineau3ce35142012-04-25 16:36:14 -07001676 if (bt_cb(skb)->control.retries == chan->remote_max_tx &&
1677 chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001678 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001679 return;
1680 }
1681
1682 tx_skb = skb_clone(skb, GFP_ATOMIC);
Mat Martineau3ce35142012-04-25 16:36:14 -07001683 bt_cb(skb)->control.retries++;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001684
1685 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001686 control &= __get_sar_mask(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001687
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001688 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001689 control |= __set_ctrl_final(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001690
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001691 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001692 control |= __set_txseq(chan, tx_seq);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001693
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001694 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001695
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001696 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001697 fcs = crc16(0, (u8 *)tx_skb->data,
1698 tx_skb->len - L2CAP_FCS_SIZE);
1699 put_unaligned_le16(fcs,
1700 tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001701 }
1702
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001703 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001704}
1705
Szymon Janc67c9e842011-07-28 16:24:33 +02001706static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001707{
1708 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001709 u16 fcs;
1710 u32 control;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001711 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001712
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001713 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001714 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001715
Mat Martineau94122bb2012-05-02 09:42:02 -07001716 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
1717 return 0;
1718
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001719 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001720
Mat Martineau3ce35142012-04-25 16:36:14 -07001721 if (bt_cb(skb)->control.retries == chan->remote_max_tx &&
1722 chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001723 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001724 break;
1725 }
1726
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001727 tx_skb = skb_clone(skb, GFP_ATOMIC);
1728
Mat Martineau3ce35142012-04-25 16:36:14 -07001729 bt_cb(skb)->control.retries++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001730
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001731 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001732 control &= __get_sar_mask(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001733
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001734 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001735 control |= __set_ctrl_final(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001736
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001737 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001738 control |= __set_txseq(chan, chan->next_tx_seq);
Mat Martineau94122bb2012-05-02 09:42:02 -07001739 control |= __set_ctrl_sar(chan, bt_cb(skb)->control.sar);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001740
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001741 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001742
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001743 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001744 fcs = crc16(0, (u8 *)skb->data,
1745 tx_skb->len - L2CAP_FCS_SIZE);
1746 put_unaligned_le16(fcs, skb->data +
1747 tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001748 }
1749
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001750 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001751
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001752 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001753
Mat Martineau3ce35142012-04-25 16:36:14 -07001754 bt_cb(skb)->control.txseq = chan->next_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001755
1756 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001757
Mat Martineau3ce35142012-04-25 16:36:14 -07001758 if (bt_cb(skb)->control.retries == 1) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001759 chan->unacked_frames++;
Szymon Janc930fa4a2012-02-07 15:43:02 +01001760
1761 if (!nsent++)
1762 __clear_ack_timer(chan);
Szymon Janc8ed7a0a2012-02-07 15:43:01 +01001763 }
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301764
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001765 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001766
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001767 if (skb_queue_is_last(&chan->tx_q, skb))
1768 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001769 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001770 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001771 }
1772
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001773 return nsent;
1774}
1775
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001776static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001777{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001778 int ret;
1779
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001780 if (!skb_queue_empty(&chan->tx_q))
1781 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001782
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001783 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001784 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001785 return ret;
1786}
1787
Szymon Jancb17e73b2012-01-11 10:59:47 +01001788static void __l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001789{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001790 u32 control = 0;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001791
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001792 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001793
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001794 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001795 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001796 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001797 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001798 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001799 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001800
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001801 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001802 return;
1803
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001804 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001805 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001806}
1807
Szymon Jancb17e73b2012-01-11 10:59:47 +01001808static void l2cap_send_ack(struct l2cap_chan *chan)
1809{
1810 __clear_ack_timer(chan);
1811 __l2cap_send_ack(chan);
1812}
1813
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001814static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001815{
1816 struct srej_list *tail;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001817 u32 control;
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001818
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001819 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001820 control |= __set_ctrl_final(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001821
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001822 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001823 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001824
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001825 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001826}
1827
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001828static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
1829 struct msghdr *msg, int len,
1830 int count, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831{
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001832 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001833 struct sk_buff **frag;
Gustavo Padovan90338942012-04-06 20:15:47 -03001834 int sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001836 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001837 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838
1839 sent += count;
1840 len -= count;
1841
1842 /* Continuation fragments (no L2CAP header) */
1843 frag = &skb_shinfo(skb)->frag_list;
1844 while (len) {
Gustavo Padovanfbe00702012-05-15 13:22:55 -03001845 struct sk_buff *tmp;
1846
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 count = min_t(unsigned int, conn->mtu, len);
1848
Gustavo Padovanfbe00702012-05-15 13:22:55 -03001849 tmp = chan->ops->alloc_skb(chan, count,
1850 msg->msg_flags & MSG_DONTWAIT);
1851 if (IS_ERR(tmp))
1852 return PTR_ERR(tmp);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001853
Gustavo Padovanfbe00702012-05-15 13:22:55 -03001854 *frag = tmp;
1855
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001856 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1857 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001859 (*frag)->priority = skb->priority;
1860
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 sent += count;
1862 len -= count;
1863
Gustavo Padovan2d0ed3d2012-05-11 13:16:12 -03001864 skb->len += (*frag)->len;
1865 skb->data_len += (*frag)->len;
1866
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 frag = &(*frag)->next;
1868 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869
1870 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001871}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001873static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
1874 struct msghdr *msg, size_t len,
1875 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001876{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001877 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001878 struct sk_buff *skb;
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001879 int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001880 struct l2cap_hdr *lh;
1881
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001882 BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001883
1884 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001885
1886 skb = chan->ops->alloc_skb(chan, count + hlen,
Gustavo Padovan90338942012-04-06 20:15:47 -03001887 msg->msg_flags & MSG_DONTWAIT);
1888 if (IS_ERR(skb))
1889 return skb;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001890
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001891 skb->priority = priority;
1892
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001893 /* Create L2CAP header */
1894 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001895 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenkodaf6a78c2012-05-03 10:55:52 +03001896 lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
1897 put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001898
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001899 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001900 if (unlikely(err < 0)) {
1901 kfree_skb(skb);
1902 return ERR_PTR(err);
1903 }
1904 return skb;
1905}
1906
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001907static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
1908 struct msghdr *msg, size_t len,
1909 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001910{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001911 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001912 struct sk_buff *skb;
Gustavo Padovanf2ba7fa2012-05-03 04:54:21 -03001913 int err, count;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001914 struct l2cap_hdr *lh;
1915
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001916 BT_DBG("chan %p len %d", chan, (int)len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001917
Gustavo Padovanf2ba7fa2012-05-03 04:54:21 -03001918 count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001919
Gustavo Padovanf2ba7fa2012-05-03 04:54:21 -03001920 skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE,
Gustavo Padovan90338942012-04-06 20:15:47 -03001921 msg->msg_flags & MSG_DONTWAIT);
1922 if (IS_ERR(skb))
1923 return skb;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001924
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001925 skb->priority = priority;
1926
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001927 /* Create L2CAP header */
1928 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001929 lh->cid = cpu_to_le16(chan->dcid);
Gustavo Padovan6ff9b5e2012-05-02 11:56:17 -03001930 lh->len = cpu_to_le16(len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001931
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001932 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001933 if (unlikely(err < 0)) {
1934 kfree_skb(skb);
1935 return ERR_PTR(err);
1936 }
1937 return skb;
1938}
1939
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001940static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1941 struct msghdr *msg, size_t len,
Mat Martineau94122bb2012-05-02 09:42:02 -07001942 u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001943{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001944 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001945 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001946 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001947 struct l2cap_hdr *lh;
1948
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001949 BT_DBG("chan %p len %d", chan, (int)len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001950
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001951 if (!conn)
1952 return ERR_PTR(-ENOTCONN);
1953
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001954 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1955 hlen = L2CAP_EXT_HDR_SIZE;
1956 else
1957 hlen = L2CAP_ENH_HDR_SIZE;
1958
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001959 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001960 hlen += L2CAP_SDULEN_SIZE;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001961
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001962 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001963 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001964
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001965 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001966
1967 skb = chan->ops->alloc_skb(chan, count + hlen,
Gustavo Padovan90338942012-04-06 20:15:47 -03001968 msg->msg_flags & MSG_DONTWAIT);
1969 if (IS_ERR(skb))
1970 return skb;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001971
1972 /* Create L2CAP header */
1973 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001974 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001975 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001976
Mat Martineau94122bb2012-05-02 09:42:02 -07001977 __put_control(chan, 0, skb_put(skb, __ctrl_size(chan)));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001978
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001979 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001980 put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001981
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001982 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001983 if (unlikely(err < 0)) {
1984 kfree_skb(skb);
1985 return ERR_PTR(err);
1986 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001987
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001988 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001989 put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001990
Mat Martineau3ce35142012-04-25 16:36:14 -07001991 bt_cb(skb)->control.retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001992 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993}
1994
Mat Martineau94122bb2012-05-02 09:42:02 -07001995static int l2cap_segment_sdu(struct l2cap_chan *chan,
1996 struct sk_buff_head *seg_queue,
1997 struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001998{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001999 struct sk_buff *skb;
Mat Martineau94122bb2012-05-02 09:42:02 -07002000 u16 sdu_len;
2001 size_t pdu_len;
2002 int err = 0;
2003 u8 sar;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002004
Mat Martineau94122bb2012-05-02 09:42:02 -07002005 BT_DBG("chan %p, msg %p, len %d", chan, msg, (int)len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002006
Mat Martineau94122bb2012-05-02 09:42:02 -07002007 /* It is critical that ERTM PDUs fit in a single HCI fragment,
2008 * so fragmented skbs are not used. The HCI layer's handling
2009 * of fragmented skbs is not compatible with ERTM's queueing.
2010 */
2011
2012 /* PDU size is derived from the HCI MTU */
2013 pdu_len = chan->conn->mtu;
2014
2015 pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
2016
2017 /* Adjust for largest possible L2CAP overhead. */
2018 pdu_len -= L2CAP_EXT_HDR_SIZE + L2CAP_FCS_SIZE;
2019
2020 /* Remote device may have requested smaller PDUs */
2021 pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
2022
2023 if (len <= pdu_len) {
2024 sar = L2CAP_SAR_UNSEGMENTED;
2025 sdu_len = 0;
2026 pdu_len = len;
2027 } else {
2028 sar = L2CAP_SAR_START;
2029 sdu_len = len;
2030 pdu_len -= L2CAP_SDULEN_SIZE;
2031 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002032
2033 while (len > 0) {
Mat Martineau94122bb2012-05-02 09:42:02 -07002034 skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002035
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002036 if (IS_ERR(skb)) {
Mat Martineau94122bb2012-05-02 09:42:02 -07002037 __skb_queue_purge(seg_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002038 return PTR_ERR(skb);
2039 }
2040
Mat Martineau94122bb2012-05-02 09:42:02 -07002041 bt_cb(skb)->control.sar = sar;
2042 __skb_queue_tail(seg_queue, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002043
Mat Martineau94122bb2012-05-02 09:42:02 -07002044 len -= pdu_len;
2045 if (sdu_len) {
2046 sdu_len = 0;
2047 pdu_len += L2CAP_SDULEN_SIZE;
2048 }
2049
2050 if (len <= pdu_len) {
2051 sar = L2CAP_SAR_END;
2052 pdu_len = len;
2053 } else {
2054 sar = L2CAP_SAR_CONTINUE;
2055 }
2056 }
2057
2058 return err;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002059}
2060
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02002061int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
2062 u32 priority)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002063{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002064 struct sk_buff *skb;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002065 int err;
Mat Martineau94122bb2012-05-02 09:42:02 -07002066 struct sk_buff_head seg_queue;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002067
2068 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03002069 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02002070 skb = l2cap_create_connless_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002071 if (IS_ERR(skb))
2072 return PTR_ERR(skb);
2073
2074 l2cap_do_send(chan, skb);
2075 return len;
2076 }
2077
2078 switch (chan->mode) {
2079 case L2CAP_MODE_BASIC:
2080 /* Check outgoing MTU */
2081 if (len > chan->omtu)
2082 return -EMSGSIZE;
2083
2084 /* Create a basic PDU */
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02002085 skb = l2cap_create_basic_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002086 if (IS_ERR(skb))
2087 return PTR_ERR(skb);
2088
2089 l2cap_do_send(chan, skb);
2090 err = len;
2091 break;
2092
2093 case L2CAP_MODE_ERTM:
2094 case L2CAP_MODE_STREAMING:
Mat Martineau94122bb2012-05-02 09:42:02 -07002095 /* Check outgoing MTU */
2096 if (len > chan->omtu) {
2097 err = -EMSGSIZE;
2098 break;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002099 }
2100
Mat Martineau94122bb2012-05-02 09:42:02 -07002101 __skb_queue_head_init(&seg_queue);
2102
2103 /* Do segmentation before calling in to the state machine,
2104 * since it's possible to block while waiting for memory
2105 * allocation.
2106 */
2107 err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
2108
2109 /* The channel could have been closed while segmenting,
2110 * check that it is still connected.
2111 */
2112 if (chan->state != BT_CONNECTED) {
2113 __skb_queue_purge(&seg_queue);
2114 err = -ENOTCONN;
2115 }
2116
2117 if (err)
2118 break;
2119
Mat Martineau577cfae2012-05-14 11:24:33 -07002120 if (chan->mode == L2CAP_MODE_ERTM && chan->tx_send_head == NULL)
2121 chan->tx_send_head = seg_queue.next;
Mat Martineau94122bb2012-05-02 09:42:02 -07002122 skb_queue_splice_tail_init(&seg_queue, &chan->tx_q);
Mat Martineau577cfae2012-05-14 11:24:33 -07002123
Mat Martineau94122bb2012-05-02 09:42:02 -07002124 if (chan->mode == L2CAP_MODE_ERTM)
2125 err = l2cap_ertm_send(chan);
2126 else
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002127 l2cap_streaming_send(chan);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002128
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002129 if (err >= 0)
2130 err = len;
2131
Mat Martineau94122bb2012-05-02 09:42:02 -07002132 /* If the skbs were not queued for sending, they'll still be in
2133 * seg_queue and need to be purged.
2134 */
2135 __skb_queue_purge(&seg_queue);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002136 break;
2137
2138 default:
2139 BT_DBG("bad state %1.1x", chan->mode);
2140 err = -EBADFD;
2141 }
2142
2143 return err;
2144}
2145
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146/* Copy frame to all raw sockets on that connection */
2147static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
2148{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002150 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151
2152 BT_DBG("conn %p", conn);
2153
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002154 mutex_lock(&conn->chan_lock);
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02002155
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002156 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002157 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03002158 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 continue;
2160
2161 /* Don't send frame to the socket it came from */
2162 if (skb->sk == sk)
2163 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002164 nskb = skb_clone(skb, GFP_ATOMIC);
2165 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 continue;
2167
Gustavo F. Padovan23070492011-05-16 17:57:22 -03002168 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 kfree_skb(nskb);
2170 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02002171
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002172 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173}
2174
2175/* ---- L2CAP signalling commands ---- */
2176static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
2177 u8 code, u8 ident, u16 dlen, void *data)
2178{
2179 struct sk_buff *skb, **frag;
2180 struct l2cap_cmd_hdr *cmd;
2181 struct l2cap_hdr *lh;
2182 int len, count;
2183
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002184 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
2185 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186
2187 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
2188 count = min_t(unsigned int, conn->mtu, len);
2189
2190 skb = bt_skb_alloc(count, GFP_ATOMIC);
2191 if (!skb)
2192 return NULL;
2193
2194 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002195 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002196
2197 if (conn->hcon->type == LE_LINK)
2198 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
2199 else
2200 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201
2202 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
2203 cmd->code = code;
2204 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002205 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206
2207 if (dlen) {
2208 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
2209 memcpy(skb_put(skb, count), data, count);
2210 data += count;
2211 }
2212
2213 len -= skb->len;
2214
2215 /* Continuation fragments (no L2CAP header) */
2216 frag = &skb_shinfo(skb)->frag_list;
2217 while (len) {
2218 count = min_t(unsigned int, conn->mtu, len);
2219
2220 *frag = bt_skb_alloc(count, GFP_ATOMIC);
2221 if (!*frag)
2222 goto fail;
2223
2224 memcpy(skb_put(*frag, count), data, count);
2225
2226 len -= count;
2227 data += count;
2228
2229 frag = &(*frag)->next;
2230 }
2231
2232 return skb;
2233
2234fail:
2235 kfree_skb(skb);
2236 return NULL;
2237}
2238
2239static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
2240{
2241 struct l2cap_conf_opt *opt = *ptr;
2242 int len;
2243
2244 len = L2CAP_CONF_OPT_SIZE + opt->len;
2245 *ptr += len;
2246
2247 *type = opt->type;
2248 *olen = opt->len;
2249
2250 switch (opt->len) {
2251 case 1:
2252 *val = *((u8 *) opt->val);
2253 break;
2254
2255 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04002256 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 break;
2258
2259 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04002260 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 break;
2262
2263 default:
2264 *val = (unsigned long) opt->val;
2265 break;
2266 }
2267
2268 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
2269 return len;
2270}
2271
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
2273{
2274 struct l2cap_conf_opt *opt = *ptr;
2275
2276 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
2277
2278 opt->type = type;
2279 opt->len = len;
2280
2281 switch (len) {
2282 case 1:
2283 *((u8 *) opt->val) = val;
2284 break;
2285
2286 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02002287 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 break;
2289
2290 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02002291 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 break;
2293
2294 default:
2295 memcpy(opt->val, (void *) val, len);
2296 break;
2297 }
2298
2299 *ptr += L2CAP_CONF_OPT_SIZE + len;
2300}
2301
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002302static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
2303{
2304 struct l2cap_conf_efs efs;
2305
Szymon Janc1ec918c2011-11-16 09:32:21 +01002306 switch (chan->mode) {
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002307 case L2CAP_MODE_ERTM:
2308 efs.id = chan->local_id;
2309 efs.stype = chan->local_stype;
2310 efs.msdu = cpu_to_le16(chan->local_msdu);
2311 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
2312 efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
2313 efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
2314 break;
2315
2316 case L2CAP_MODE_STREAMING:
2317 efs.id = 1;
2318 efs.stype = L2CAP_SERV_BESTEFFORT;
2319 efs.msdu = cpu_to_le16(chan->local_msdu);
2320 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
2321 efs.acc_lat = 0;
2322 efs.flush_to = 0;
2323 break;
2324
2325 default:
2326 return;
2327 }
2328
2329 l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
2330 (unsigned long) &efs);
2331}
2332
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002333static void l2cap_ack_timeout(struct work_struct *work)
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002334{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002335 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2336 ack_timer.work);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002337
Gustavo F. Padovan2fb9b3d2011-12-22 16:56:05 -02002338 BT_DBG("chan %p", chan);
2339
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02002340 l2cap_chan_lock(chan);
2341
Szymon Jancb17e73b2012-01-11 10:59:47 +01002342 __l2cap_send_ack(chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02002343
2344 l2cap_chan_unlock(chan);
Szymon Janc09bfb2e2012-01-11 10:59:49 +01002345
2346 l2cap_chan_put(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002347}
2348
Mat Martineau3c588192012-04-11 10:48:42 -07002349static inline int l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002350{
Mat Martineau3c588192012-04-11 10:48:42 -07002351 int err;
2352
Mat Martineau105bdf92012-04-27 16:50:48 -07002353 chan->next_tx_seq = 0;
2354 chan->expected_tx_seq = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002355 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002356 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002357 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002358 chan->num_acked = 0;
2359 chan->frames_sent = 0;
Mat Martineau105bdf92012-04-27 16:50:48 -07002360 chan->last_acked_seq = 0;
2361 chan->sdu = NULL;
2362 chan->sdu_last_frag = NULL;
2363 chan->sdu_len = 0;
2364
Mat Martineaud34c34f2012-05-14 14:49:27 -07002365 skb_queue_head_init(&chan->tx_q);
2366
Mat Martineau105bdf92012-04-27 16:50:48 -07002367 if (chan->mode != L2CAP_MODE_ERTM)
2368 return 0;
2369
2370 chan->rx_state = L2CAP_RX_STATE_RECV;
2371 chan->tx_state = L2CAP_TX_STATE_XMIT;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002372
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002373 INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2374 INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2375 INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002376
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002377 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002378
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03002379 INIT_LIST_HEAD(&chan->srej_l);
Mat Martineau3c588192012-04-11 10:48:42 -07002380 err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
2381 if (err < 0)
2382 return err;
2383
2384 return l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002385}
2386
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002387static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2388{
2389 switch (mode) {
2390 case L2CAP_MODE_STREAMING:
2391 case L2CAP_MODE_ERTM:
2392 if (l2cap_mode_supported(mode, remote_feat_mask))
2393 return mode;
2394 /* fall through */
2395 default:
2396 return L2CAP_MODE_BASIC;
2397 }
2398}
2399
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002400static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
2401{
2402 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
2403}
2404
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002405static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2406{
2407 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2408}
2409
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002410static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
2411{
2412 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002413 __l2cap_ews_supported(chan)) {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002414 /* use extended control field */
2415 set_bit(FLAG_EXT_CTRL, &chan->flags);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002416 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2417 } else {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002418 chan->tx_win = min_t(u16, chan->tx_win,
2419 L2CAP_DEFAULT_TX_WINDOW);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002420 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2421 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002422}
2423
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002424static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002427 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 void *ptr = req->data;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002429 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002431 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002433 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002434 goto done;
2435
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002436 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002437 case L2CAP_MODE_STREAMING:
2438 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002439 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002440 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002441
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002442 if (__l2cap_efs_supported(chan))
2443 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2444
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002445 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002446 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002447 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002448 break;
2449 }
2450
2451done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002452 if (chan->imtu != L2CAP_DEFAULT_MTU)
2453 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002454
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002455 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002456 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002457 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2458 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002459 break;
2460
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002461 rfc.mode = L2CAP_MODE_BASIC;
2462 rfc.txwin_size = 0;
2463 rfc.max_transmit = 0;
2464 rfc.retrans_timeout = 0;
2465 rfc.monitor_timeout = 0;
2466 rfc.max_pdu_size = 0;
2467
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002468 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2469 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002470 break;
2471
2472 case L2CAP_MODE_ERTM:
2473 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002474 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002475 rfc.retrans_timeout = 0;
2476 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002477
2478 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2479 L2CAP_EXT_HDR_SIZE -
2480 L2CAP_SDULEN_SIZE -
2481 L2CAP_FCS_SIZE);
2482 rfc.max_pdu_size = cpu_to_le16(size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002483
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002484 l2cap_txwin_setup(chan);
2485
2486 rfc.txwin_size = min_t(u16, chan->tx_win,
2487 L2CAP_DEFAULT_TX_WINDOW);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002488
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002489 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2490 (unsigned long) &rfc);
2491
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002492 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2493 l2cap_add_opt_efs(&ptr, chan);
2494
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002495 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002496 break;
2497
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002498 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002499 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002500 chan->fcs = L2CAP_FCS_NONE;
2501 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002502 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002503
2504 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2505 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2506 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002507 break;
2508
2509 case L2CAP_MODE_STREAMING:
2510 rfc.mode = L2CAP_MODE_STREAMING;
2511 rfc.txwin_size = 0;
2512 rfc.max_transmit = 0;
2513 rfc.retrans_timeout = 0;
2514 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002515
2516 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2517 L2CAP_EXT_HDR_SIZE -
2518 L2CAP_SDULEN_SIZE -
2519 L2CAP_FCS_SIZE);
2520 rfc.max_pdu_size = cpu_to_le16(size);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002521
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002522 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2523 (unsigned long) &rfc);
2524
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002525 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2526 l2cap_add_opt_efs(&ptr, chan);
2527
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002528 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002529 break;
2530
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002531 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002532 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002533 chan->fcs = L2CAP_FCS_NONE;
2534 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002535 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002536 break;
2537 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002539 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002540 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541
2542 return ptr - data;
2543}
2544
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002545static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002547 struct l2cap_conf_rsp *rsp = data;
2548 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002549 void *req = chan->conf_req;
2550 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002551 int type, hint, olen;
2552 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002553 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002554 struct l2cap_conf_efs efs;
2555 u8 remote_efs = 0;
Marcel Holtmann861d6882007-10-20 13:37:06 +02002556 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002557 u16 result = L2CAP_CONF_SUCCESS;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002558 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002560 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002561
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002562 while (len >= L2CAP_CONF_OPT_SIZE) {
2563 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002565 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002566 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002567
2568 switch (type) {
2569 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002570 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002571 break;
2572
2573 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002574 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002575 break;
2576
2577 case L2CAP_CONF_QOS:
2578 break;
2579
Marcel Holtmann6464f352007-10-20 13:39:51 +02002580 case L2CAP_CONF_RFC:
2581 if (olen == sizeof(rfc))
2582 memcpy(&rfc, (void *) val, olen);
2583 break;
2584
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002585 case L2CAP_CONF_FCS:
2586 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002587 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002588 break;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002589
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002590 case L2CAP_CONF_EFS:
2591 remote_efs = 1;
2592 if (olen == sizeof(efs))
2593 memcpy(&efs, (void *) val, olen);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002594 break;
2595
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002596 case L2CAP_CONF_EWS:
2597 if (!enable_hs)
2598 return -ECONNREFUSED;
2599
2600 set_bit(FLAG_EXT_CTRL, &chan->flags);
2601 set_bit(CONF_EWS_RECV, &chan->conf_state);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002602 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002603 chan->remote_tx_win = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002604 break;
2605
2606 default:
2607 if (hint)
2608 break;
2609
2610 result = L2CAP_CONF_UNKNOWN;
2611 *((u8 *) ptr++) = type;
2612 break;
2613 }
2614 }
2615
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002616 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002617 goto done;
2618
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002619 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002620 case L2CAP_MODE_STREAMING:
2621 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002622 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002623 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002624 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002625 break;
2626 }
2627
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002628 if (remote_efs) {
2629 if (__l2cap_efs_supported(chan))
2630 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2631 else
2632 return -ECONNREFUSED;
2633 }
2634
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002635 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002636 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002637
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002638 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002639 }
2640
2641done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002642 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002643 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002644 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002645
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002646 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002647 return -ECONNREFUSED;
2648
2649 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2650 sizeof(rfc), (unsigned long) &rfc);
2651 }
2652
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002653 if (result == L2CAP_CONF_SUCCESS) {
2654 /* Configure output options and let the other side know
2655 * which ones we don't like. */
2656
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002657 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2658 result = L2CAP_CONF_UNACCEPT;
2659 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002660 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002661 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002662 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002663 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002664
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002665 if (remote_efs) {
2666 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2667 efs.stype != L2CAP_SERV_NOTRAFIC &&
2668 efs.stype != chan->local_stype) {
2669
2670 result = L2CAP_CONF_UNACCEPT;
2671
2672 if (chan->num_conf_req >= 1)
2673 return -ECONNREFUSED;
2674
2675 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002676 sizeof(efs),
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002677 (unsigned long) &efs);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002678 } else {
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002679 /* Send PENDING Conf Rsp */
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002680 result = L2CAP_CONF_PENDING;
2681 set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002682 }
2683 }
2684
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002685 switch (rfc.mode) {
2686 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002687 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002688 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002689 break;
2690
2691 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002692 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2693 chan->remote_tx_win = rfc.txwin_size;
2694 else
2695 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2696
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002697 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002698
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002699 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2700 chan->conn->mtu -
2701 L2CAP_EXT_HDR_SIZE -
2702 L2CAP_SDULEN_SIZE -
2703 L2CAP_FCS_SIZE);
2704 rfc.max_pdu_size = cpu_to_le16(size);
2705 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002706
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002707 rfc.retrans_timeout =
Andrei Emeltchenko4fd21a82012-03-12 12:13:10 +02002708 __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002709 rfc.monitor_timeout =
Andrei Emeltchenko4fd21a82012-03-12 12:13:10 +02002710 __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002711
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002712 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002713
2714 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2715 sizeof(rfc), (unsigned long) &rfc);
2716
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002717 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2718 chan->remote_id = efs.id;
2719 chan->remote_stype = efs.stype;
2720 chan->remote_msdu = le16_to_cpu(efs.msdu);
2721 chan->remote_flush_to =
2722 le32_to_cpu(efs.flush_to);
2723 chan->remote_acc_lat =
2724 le32_to_cpu(efs.acc_lat);
2725 chan->remote_sdu_itime =
2726 le32_to_cpu(efs.sdu_itime);
2727 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2728 sizeof(efs), (unsigned long) &efs);
2729 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002730 break;
2731
2732 case L2CAP_MODE_STREAMING:
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002733 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2734 chan->conn->mtu -
2735 L2CAP_EXT_HDR_SIZE -
2736 L2CAP_SDULEN_SIZE -
2737 L2CAP_FCS_SIZE);
2738 rfc.max_pdu_size = cpu_to_le16(size);
2739 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002740
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002741 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002742
2743 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2744 sizeof(rfc), (unsigned long) &rfc);
2745
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002746 break;
2747
2748 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002749 result = L2CAP_CONF_UNACCEPT;
2750
2751 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002752 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002753 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002754
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002755 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002756 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002757 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002758 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002759 rsp->result = cpu_to_le16(result);
2760 rsp->flags = cpu_to_le16(0x0000);
2761
2762 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763}
2764
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002765static 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 -03002766{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002767 struct l2cap_conf_req *req = data;
2768 void *ptr = req->data;
2769 int type, olen;
2770 unsigned long val;
Mat Martineau36e999a2011-12-08 17:23:21 -08002771 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002772 struct l2cap_conf_efs efs;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002773
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002774 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002775
2776 while (len >= L2CAP_CONF_OPT_SIZE) {
2777 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2778
2779 switch (type) {
2780 case L2CAP_CONF_MTU:
2781 if (val < L2CAP_DEFAULT_MIN_MTU) {
2782 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002783 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002784 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002785 chan->imtu = val;
2786 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002787 break;
2788
2789 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002790 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002791 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002792 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002793 break;
2794
2795 case L2CAP_CONF_RFC:
2796 if (olen == sizeof(rfc))
2797 memcpy(&rfc, (void *)val, olen);
2798
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002799 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002800 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002801 return -ECONNREFUSED;
2802
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002803 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002804
2805 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2806 sizeof(rfc), (unsigned long) &rfc);
2807 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002808
2809 case L2CAP_CONF_EWS:
2810 chan->tx_win = min_t(u16, val,
2811 L2CAP_DEFAULT_EXT_WINDOW);
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002812 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2813 chan->tx_win);
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002814 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002815
2816 case L2CAP_CONF_EFS:
2817 if (olen == sizeof(efs))
2818 memcpy(&efs, (void *)val, olen);
2819
2820 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2821 efs.stype != L2CAP_SERV_NOTRAFIC &&
2822 efs.stype != chan->local_stype)
2823 return -ECONNREFUSED;
2824
2825 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2826 sizeof(efs), (unsigned long) &efs);
2827 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002828 }
2829 }
2830
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002831 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002832 return -ECONNREFUSED;
2833
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002834 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002835
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002836 if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002837 switch (rfc.mode) {
2838 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002839 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2840 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2841 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002842
2843 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2844 chan->local_msdu = le16_to_cpu(efs.msdu);
2845 chan->local_sdu_itime =
2846 le32_to_cpu(efs.sdu_itime);
2847 chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
2848 chan->local_flush_to =
2849 le32_to_cpu(efs.flush_to);
2850 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002851 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002852
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002853 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002854 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002855 }
2856 }
2857
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002858 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002859 req->flags = cpu_to_le16(0x0000);
2860
2861 return ptr - data;
2862}
2863
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002864static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865{
2866 struct l2cap_conf_rsp *rsp = data;
2867 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002869 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002871 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002872 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002873 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874
2875 return ptr - data;
2876}
2877
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002878void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002879{
2880 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002881 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002882 u8 buf[128];
2883
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002884 rsp.scid = cpu_to_le16(chan->dcid);
2885 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002886 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2887 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2888 l2cap_send_cmd(conn, chan->ident,
2889 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2890
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002891 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002892 return;
2893
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002894 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2895 l2cap_build_conf_req(chan, buf), buf);
2896 chan->num_conf_req++;
2897}
2898
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002899static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002900{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002901 int type, olen;
2902 unsigned long val;
2903 struct l2cap_conf_rfc rfc;
2904
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002905 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002906
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002907 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002908 return;
2909
2910 while (len >= L2CAP_CONF_OPT_SIZE) {
2911 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2912
2913 switch (type) {
2914 case L2CAP_CONF_RFC:
2915 if (olen == sizeof(rfc))
2916 memcpy(&rfc, (void *)val, olen);
2917 goto done;
2918 }
2919 }
2920
Mat Martineau36e999a2011-12-08 17:23:21 -08002921 /* Use sane default values in case a misbehaving remote device
2922 * did not send an RFC option.
2923 */
2924 rfc.mode = chan->mode;
2925 rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
2926 rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
2927 rfc.max_pdu_size = cpu_to_le16(chan->imtu);
2928
2929 BT_ERR("Expected RFC option was not found, using defaults");
2930
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002931done:
2932 switch (rfc.mode) {
2933 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002934 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2935 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2936 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002937 break;
2938 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002939 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002940 }
2941}
2942
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002943static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2944{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002945 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002946
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002947 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002948 return 0;
2949
2950 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2951 cmd->ident == conn->info_ident) {
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02002952 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002953
2954 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002955 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002956
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002957 l2cap_conn_start(conn);
2958 }
2959
2960 return 0;
2961}
2962
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2964{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2966 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002967 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002968 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002969 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970
2971 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002972 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973
Andrei Emeltchenko097db762012-03-09 14:16:17 +02002974 BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975
2976 /* Check if we have socket listening on psm */
Ido Yarivc2287682012-04-20 15:46:07 -03002977 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002978 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979 result = L2CAP_CR_BAD_PSM;
2980 goto sendresp;
2981 }
2982
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002983 parent = pchan->sk;
2984
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002985 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002986 lock_sock(parent);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002987
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002988 /* Check if the ACL is secure enough (if not SDP) */
2989 if (psm != cpu_to_le16(0x0001) &&
2990 !hci_conn_check_link_mode(conn->hcon)) {
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002991 conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002992 result = L2CAP_CR_SEC_BLOCK;
2993 goto response;
2994 }
2995
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996 result = L2CAP_CR_NO_MEM;
2997
2998 /* Check for backlog size */
2999 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09003000 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001 goto response;
3002 }
3003
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03003004 chan = pchan->ops->new_connection(pchan->data);
3005 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006 goto response;
3007
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03003008 sk = chan->sk;
3009
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003011 if (__l2cap_get_chan_by_dcid(conn, scid)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003013 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014 goto response;
3015 }
3016
3017 hci_conn_hold(conn->hcon);
3018
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019 bacpy(&bt_sk(sk)->src, conn->src);
3020 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003021 chan->psm = psm;
3022 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023
Gustavo F. Padovand1010242011-03-25 00:39:48 -03003024 bt_accept_enqueue(parent, sk);
3025
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003026 __l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003027
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003028 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03003030 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003032 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033
Marcel Holtmann984947d2009-02-06 23:35:19 +01003034 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02003035 if (l2cap_chan_check_security(chan)) {
Gustavo Padovanc5daa682012-05-16 12:17:10 -03003036 if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02003037 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01003038 result = L2CAP_CR_PEND;
3039 status = L2CAP_CS_AUTHOR_PEND;
3040 parent->sk_data_ready(parent, 0);
3041 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02003042 __l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01003043 result = L2CAP_CR_SUCCESS;
3044 status = L2CAP_CS_NO_INFO;
3045 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003046 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02003047 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003048 result = L2CAP_CR_PEND;
3049 status = L2CAP_CS_AUTHEN_PEND;
3050 }
3051 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02003052 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003053 result = L2CAP_CR_PEND;
3054 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055 }
3056
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057response:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003058 release_sock(parent);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003059 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003060
3061sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003062 rsp.scid = cpu_to_le16(scid);
3063 rsp.dcid = cpu_to_le16(dcid);
3064 rsp.result = cpu_to_le16(result);
3065 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003067
3068 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
3069 struct l2cap_info_req info;
3070 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3071
3072 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
3073 conn->info_ident = l2cap_get_ident(conn);
3074
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08003075 schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003076
3077 l2cap_send_cmd(conn, conn->info_ident,
3078 L2CAP_INFO_REQ, sizeof(info), &info);
3079 }
3080
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003081 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003082 result == L2CAP_CR_SUCCESS) {
3083 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003084 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003085 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003086 l2cap_build_conf_req(chan, buf), buf);
3087 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003088 }
3089
Linus Torvalds1da177e2005-04-16 15:20:36 -07003090 return 0;
3091}
3092
3093static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3094{
3095 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
3096 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003097 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098 u8 req[128];
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003099 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003100
3101 scid = __le16_to_cpu(rsp->scid);
3102 dcid = __le16_to_cpu(rsp->dcid);
3103 result = __le16_to_cpu(rsp->result);
3104 status = __le16_to_cpu(rsp->status);
3105
Andrei Emeltchenko1b009c92012-02-21 12:54:54 +02003106 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
3107 dcid, scid, result, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003108
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003109 mutex_lock(&conn->chan_lock);
3110
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111 if (scid) {
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003112 chan = __l2cap_get_chan_by_scid(conn, scid);
3113 if (!chan) {
3114 err = -EFAULT;
3115 goto unlock;
3116 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117 } else {
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003118 chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
3119 if (!chan) {
3120 err = -EFAULT;
3121 goto unlock;
3122 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003123 }
3124
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003125 err = 0;
3126
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003127 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003128
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129 switch (result) {
3130 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003131 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003132 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003133 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003134 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003135
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003136 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003137 break;
3138
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003140 l2cap_build_conf_req(chan, req), req);
3141 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142 break;
3143
3144 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003145 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003146 break;
3147
3148 default:
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003149 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150 break;
3151 }
3152
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003153 l2cap_chan_unlock(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003154
3155unlock:
3156 mutex_unlock(&conn->chan_lock);
3157
3158 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159}
3160
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003161static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07003162{
3163 /* FCS is enabled only in ERTM or streaming mode, if one or both
3164 * sides request it.
3165 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003166 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003167 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003168 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003169 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07003170}
3171
Al Viro88219a02007-07-29 00:17:25 -07003172static 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 -07003173{
3174 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
3175 u16 dcid, flags;
3176 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003177 struct l2cap_chan *chan;
Mat Martineau3c588192012-04-11 10:48:42 -07003178 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179
3180 dcid = __le16_to_cpu(req->dcid);
3181 flags = __le16_to_cpu(req->flags);
3182
3183 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
3184
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003185 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003186 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187 return -ENOENT;
3188
David S. Miller033b1142011-07-21 13:38:42 -07003189 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003190 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003191
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003192 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
3193 rej.scid = cpu_to_le16(chan->scid);
3194 rej.dcid = cpu_to_le16(chan->dcid);
3195
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003196 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
3197 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003198 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003199 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003200
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003201 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07003202 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04003203 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003204 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003205 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003206 L2CAP_CONF_REJECT, flags), rsp);
3207 goto unlock;
3208 }
3209
3210 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003211 memcpy(chan->conf_req + chan->conf_len, req->data, len);
3212 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003213
3214 if (flags & 0x0001) {
3215 /* Incomplete config. Send empty response. */
3216 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003217 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003218 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003219 goto unlock;
3220 }
3221
3222 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003223 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003224 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003225 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003227 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003229 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003230 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003231
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003232 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003233 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003234
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003235 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02003236 goto unlock;
3237
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003238 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003239 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003240
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003241 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003242
Mat Martineau105bdf92012-04-27 16:50:48 -07003243 if (chan->mode == L2CAP_MODE_ERTM ||
3244 chan->mode == L2CAP_MODE_STREAMING)
Mat Martineau3c588192012-04-11 10:48:42 -07003245 err = l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003246
Mat Martineau3c588192012-04-11 10:48:42 -07003247 if (err < 0)
3248 l2cap_send_disconn_req(chan->conn, chan, -err);
3249 else
3250 l2cap_chan_ready(chan);
3251
Marcel Holtmann876d9482007-10-20 13:35:42 +02003252 goto unlock;
3253 }
3254
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003255 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003256 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003257 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003258 l2cap_build_conf_req(chan, buf), buf);
3259 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260 }
3261
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003262 /* Got Conf Rsp PENDING from remote side and asume we sent
3263 Conf Rsp PENDING in the code above */
3264 if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
3265 test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
3266
3267 /* check compatibility */
3268
3269 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
3270 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
3271
3272 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02003273 l2cap_build_conf_rsp(chan, rsp,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003274 L2CAP_CONF_SUCCESS, 0x0000), rsp);
3275 }
3276
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277unlock:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003278 l2cap_chan_unlock(chan);
Mat Martineau3c588192012-04-11 10:48:42 -07003279 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003280}
3281
3282static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3283{
3284 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
3285 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003286 struct l2cap_chan *chan;
Andrei Emeltchenko61386cb2012-03-12 12:13:07 +02003287 int len = le16_to_cpu(cmd->len) - sizeof(*rsp);
Mat Martineau3c588192012-04-11 10:48:42 -07003288 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003289
3290 scid = __le16_to_cpu(rsp->scid);
3291 flags = __le16_to_cpu(rsp->flags);
3292 result = __le16_to_cpu(rsp->result);
3293
Andrei Emeltchenko61386cb2012-03-12 12:13:07 +02003294 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
3295 result, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003297 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003298 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299 return 0;
3300
3301 switch (result) {
3302 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003303 l2cap_conf_rfc_get(chan, rsp->data, len);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003304 clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003305 break;
3306
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003307 case L2CAP_CONF_PENDING:
3308 set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
3309
3310 if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
3311 char buf[64];
3312
3313 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
3314 buf, &result);
3315 if (len < 0) {
3316 l2cap_send_disconn_req(conn, chan, ECONNRESET);
3317 goto done;
3318 }
3319
3320 /* check compatibility */
3321
3322 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
3323 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
3324
3325 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02003326 l2cap_build_conf_rsp(chan, buf,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003327 L2CAP_CONF_SUCCESS, 0x0000), buf);
3328 }
3329 goto done;
3330
Linus Torvalds1da177e2005-04-16 15:20:36 -07003331 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003332 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003333 char req[64];
3334
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003335 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003336 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003337 goto done;
3338 }
3339
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003340 /* throw out any old stored conf requests */
3341 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003342 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
3343 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003344 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003345 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003346 goto done;
3347 }
3348
3349 l2cap_send_cmd(conn, l2cap_get_ident(conn),
3350 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003351 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003352 if (result != L2CAP_CONF_SUCCESS)
3353 goto done;
3354 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355 }
3356
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09003357 default:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003358 l2cap_chan_set_err(chan, ECONNRESET);
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +02003359
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08003360 __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003361 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003362 goto done;
3363 }
3364
3365 if (flags & 0x01)
3366 goto done;
3367
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003368 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003369
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003370 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003371 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003372
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003373 l2cap_state_change(chan, BT_CONNECTED);
Mat Martineau105bdf92012-04-27 16:50:48 -07003374 if (chan->mode == L2CAP_MODE_ERTM ||
3375 chan->mode == L2CAP_MODE_STREAMING)
Mat Martineau3c588192012-04-11 10:48:42 -07003376 err = l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003377
Mat Martineau3c588192012-04-11 10:48:42 -07003378 if (err < 0)
3379 l2cap_send_disconn_req(chan->conn, chan, -err);
3380 else
3381 l2cap_chan_ready(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003382 }
3383
3384done:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003385 l2cap_chan_unlock(chan);
Mat Martineau3c588192012-04-11 10:48:42 -07003386 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003387}
3388
3389static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3390{
3391 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3392 struct l2cap_disconn_rsp rsp;
3393 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003394 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003395 struct sock *sk;
3396
3397 scid = __le16_to_cpu(req->scid);
3398 dcid = __le16_to_cpu(req->dcid);
3399
3400 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3401
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003402 mutex_lock(&conn->chan_lock);
3403
3404 chan = __l2cap_get_chan_by_scid(conn, dcid);
3405 if (!chan) {
3406 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407 return 0;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003408 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003410 l2cap_chan_lock(chan);
3411
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003412 sk = chan->sk;
3413
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003414 rsp.dcid = cpu_to_le16(chan->scid);
3415 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3417
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003418 lock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003419 sk->sk_shutdown = SHUTDOWN_MASK;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003420 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421
Mat Martineau61d6ef32012-04-27 16:50:50 -07003422 l2cap_chan_hold(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003423 l2cap_chan_del(chan, ECONNRESET);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003424
3425 l2cap_chan_unlock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003426
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003427 chan->ops->close(chan->data);
Mat Martineau61d6ef32012-04-27 16:50:50 -07003428 l2cap_chan_put(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003429
3430 mutex_unlock(&conn->chan_lock);
3431
Linus Torvalds1da177e2005-04-16 15:20:36 -07003432 return 0;
3433}
3434
3435static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3436{
3437 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3438 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003439 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003440
3441 scid = __le16_to_cpu(rsp->scid);
3442 dcid = __le16_to_cpu(rsp->dcid);
3443
3444 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3445
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003446 mutex_lock(&conn->chan_lock);
3447
3448 chan = __l2cap_get_chan_by_scid(conn, scid);
3449 if (!chan) {
3450 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451 return 0;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003452 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003454 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003455
Mat Martineau61d6ef32012-04-27 16:50:50 -07003456 l2cap_chan_hold(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003457 l2cap_chan_del(chan, 0);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003458
3459 l2cap_chan_unlock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003461 chan->ops->close(chan->data);
Mat Martineau61d6ef32012-04-27 16:50:50 -07003462 l2cap_chan_put(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003463
3464 mutex_unlock(&conn->chan_lock);
3465
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466 return 0;
3467}
3468
3469static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3470{
3471 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003472 u16 type;
3473
3474 type = __le16_to_cpu(req->type);
3475
3476 BT_DBG("type 0x%4.4x", type);
3477
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003478 if (type == L2CAP_IT_FEAT_MASK) {
3479 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003480 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003481 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3482 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3483 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003484 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003485 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3486 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003487 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003488 feat_mask |= L2CAP_FEAT_EXT_FLOW
3489 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003490
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003491 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003492 l2cap_send_cmd(conn, cmd->ident,
3493 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003494 } else if (type == L2CAP_IT_FIXED_CHAN) {
3495 u8 buf[12];
3496 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
Mat Martineau50a147c2011-11-02 16:18:34 -07003497
3498 if (enable_hs)
3499 l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
3500 else
3501 l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
3502
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003503 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3504 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003505 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003506 l2cap_send_cmd(conn, cmd->ident,
3507 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003508 } else {
3509 struct l2cap_info_rsp rsp;
3510 rsp.type = cpu_to_le16(type);
3511 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3512 l2cap_send_cmd(conn, cmd->ident,
3513 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3514 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003515
3516 return 0;
3517}
3518
3519static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3520{
3521 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3522 u16 type, result;
3523
3524 type = __le16_to_cpu(rsp->type);
3525 result = __le16_to_cpu(rsp->result);
3526
3527 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3528
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003529 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3530 if (cmd->ident != conn->info_ident ||
3531 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3532 return 0;
3533
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02003534 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003535
Ville Tervoadb08ed2010-08-04 09:43:33 +03003536 if (result != L2CAP_IR_SUCCESS) {
3537 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3538 conn->info_ident = 0;
3539
3540 l2cap_conn_start(conn);
3541
3542 return 0;
3543 }
3544
Andrei Emeltchenko978c93b2012-02-29 10:41:41 +02003545 switch (type) {
3546 case L2CAP_IT_FEAT_MASK:
Harvey Harrison83985312008-05-02 16:25:46 -07003547 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003548
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003549 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003550 struct l2cap_info_req req;
3551 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3552
3553 conn->info_ident = l2cap_get_ident(conn);
3554
3555 l2cap_send_cmd(conn, conn->info_ident,
3556 L2CAP_INFO_REQ, sizeof(req), &req);
3557 } else {
3558 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3559 conn->info_ident = 0;
3560
3561 l2cap_conn_start(conn);
3562 }
Andrei Emeltchenko978c93b2012-02-29 10:41:41 +02003563 break;
3564
3565 case L2CAP_IT_FIXED_CHAN:
3566 conn->fixed_chan_mask = rsp->data[0];
Marcel Holtmann984947d2009-02-06 23:35:19 +01003567 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003568 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003569
3570 l2cap_conn_start(conn);
Andrei Emeltchenko978c93b2012-02-29 10:41:41 +02003571 break;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003572 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003573
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574 return 0;
3575}
3576
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003577static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3578 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3579 void *data)
3580{
3581 struct l2cap_create_chan_req *req = data;
3582 struct l2cap_create_chan_rsp rsp;
3583 u16 psm, scid;
3584
3585 if (cmd_len != sizeof(*req))
3586 return -EPROTO;
3587
3588 if (!enable_hs)
3589 return -EINVAL;
3590
3591 psm = le16_to_cpu(req->psm);
3592 scid = le16_to_cpu(req->scid);
3593
3594 BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3595
3596 /* Placeholder: Always reject */
3597 rsp.dcid = 0;
3598 rsp.scid = cpu_to_le16(scid);
Andrei Emeltchenko8ce0c492012-03-12 12:13:09 +02003599 rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
3600 rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003601
3602 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3603 sizeof(rsp), &rsp);
3604
3605 return 0;
3606}
3607
3608static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3609 struct l2cap_cmd_hdr *cmd, void *data)
3610{
3611 BT_DBG("conn %p", conn);
3612
3613 return l2cap_connect_rsp(conn, cmd, data);
3614}
3615
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003616static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
3617 u16 icid, u16 result)
3618{
3619 struct l2cap_move_chan_rsp rsp;
3620
3621 BT_DBG("icid %d, result %d", icid, result);
3622
3623 rsp.icid = cpu_to_le16(icid);
3624 rsp.result = cpu_to_le16(result);
3625
3626 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
3627}
3628
3629static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
3630 struct l2cap_chan *chan, u16 icid, u16 result)
3631{
3632 struct l2cap_move_chan_cfm cfm;
3633 u8 ident;
3634
3635 BT_DBG("icid %d, result %d", icid, result);
3636
3637 ident = l2cap_get_ident(conn);
3638 if (chan)
3639 chan->ident = ident;
3640
3641 cfm.icid = cpu_to_le16(icid);
3642 cfm.result = cpu_to_le16(result);
3643
3644 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
3645}
3646
3647static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
3648 u16 icid)
3649{
3650 struct l2cap_move_chan_cfm_rsp rsp;
3651
3652 BT_DBG("icid %d", icid);
3653
3654 rsp.icid = cpu_to_le16(icid);
3655 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
3656}
3657
3658static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
3659 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3660{
3661 struct l2cap_move_chan_req *req = data;
3662 u16 icid = 0;
3663 u16 result = L2CAP_MR_NOT_ALLOWED;
3664
3665 if (cmd_len != sizeof(*req))
3666 return -EPROTO;
3667
3668 icid = le16_to_cpu(req->icid);
3669
3670 BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
3671
3672 if (!enable_hs)
3673 return -EINVAL;
3674
3675 /* Placeholder: Always refuse */
3676 l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
3677
3678 return 0;
3679}
3680
3681static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
3682 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3683{
3684 struct l2cap_move_chan_rsp *rsp = data;
3685 u16 icid, result;
3686
3687 if (cmd_len != sizeof(*rsp))
3688 return -EPROTO;
3689
3690 icid = le16_to_cpu(rsp->icid);
3691 result = le16_to_cpu(rsp->result);
3692
3693 BT_DBG("icid %d, result %d", icid, result);
3694
3695 /* Placeholder: Always unconfirmed */
3696 l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
3697
3698 return 0;
3699}
3700
3701static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
3702 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3703{
3704 struct l2cap_move_chan_cfm *cfm = data;
3705 u16 icid, result;
3706
3707 if (cmd_len != sizeof(*cfm))
3708 return -EPROTO;
3709
3710 icid = le16_to_cpu(cfm->icid);
3711 result = le16_to_cpu(cfm->result);
3712
3713 BT_DBG("icid %d, result %d", icid, result);
3714
3715 l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
3716
3717 return 0;
3718}
3719
3720static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
3721 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3722{
3723 struct l2cap_move_chan_cfm_rsp *rsp = data;
3724 u16 icid;
3725
3726 if (cmd_len != sizeof(*rsp))
3727 return -EPROTO;
3728
3729 icid = le16_to_cpu(rsp->icid);
3730
3731 BT_DBG("icid %d", icid);
3732
3733 return 0;
3734}
3735
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003736static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02003737 u16 to_multiplier)
3738{
3739 u16 max_latency;
3740
3741 if (min > max || min < 6 || max > 3200)
3742 return -EINVAL;
3743
3744 if (to_multiplier < 10 || to_multiplier > 3200)
3745 return -EINVAL;
3746
3747 if (max >= to_multiplier * 8)
3748 return -EINVAL;
3749
3750 max_latency = (to_multiplier * 8 / max) - 1;
3751 if (latency > 499 || latency > max_latency)
3752 return -EINVAL;
3753
3754 return 0;
3755}
3756
3757static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3758 struct l2cap_cmd_hdr *cmd, u8 *data)
3759{
3760 struct hci_conn *hcon = conn->hcon;
3761 struct l2cap_conn_param_update_req *req;
3762 struct l2cap_conn_param_update_rsp rsp;
3763 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003764 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02003765
3766 if (!(hcon->link_mode & HCI_LM_MASTER))
3767 return -EINVAL;
3768
3769 cmd_len = __le16_to_cpu(cmd->len);
3770 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3771 return -EPROTO;
3772
3773 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003774 min = __le16_to_cpu(req->min);
3775 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02003776 latency = __le16_to_cpu(req->latency);
3777 to_multiplier = __le16_to_cpu(req->to_multiplier);
3778
3779 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3780 min, max, latency, to_multiplier);
3781
3782 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003783
3784 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
3785 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02003786 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3787 else
3788 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3789
3790 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3791 sizeof(rsp), &rsp);
3792
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003793 if (!err)
3794 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
3795
Claudio Takahaside731152011-02-11 19:28:55 -02003796 return 0;
3797}
3798
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003799static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
3800 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
3801{
3802 int err = 0;
3803
3804 switch (cmd->code) {
3805 case L2CAP_COMMAND_REJ:
3806 l2cap_command_rej(conn, cmd, data);
3807 break;
3808
3809 case L2CAP_CONN_REQ:
3810 err = l2cap_connect_req(conn, cmd, data);
3811 break;
3812
3813 case L2CAP_CONN_RSP:
3814 err = l2cap_connect_rsp(conn, cmd, data);
3815 break;
3816
3817 case L2CAP_CONF_REQ:
3818 err = l2cap_config_req(conn, cmd, cmd_len, data);
3819 break;
3820
3821 case L2CAP_CONF_RSP:
3822 err = l2cap_config_rsp(conn, cmd, data);
3823 break;
3824
3825 case L2CAP_DISCONN_REQ:
3826 err = l2cap_disconnect_req(conn, cmd, data);
3827 break;
3828
3829 case L2CAP_DISCONN_RSP:
3830 err = l2cap_disconnect_rsp(conn, cmd, data);
3831 break;
3832
3833 case L2CAP_ECHO_REQ:
3834 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3835 break;
3836
3837 case L2CAP_ECHO_RSP:
3838 break;
3839
3840 case L2CAP_INFO_REQ:
3841 err = l2cap_information_req(conn, cmd, data);
3842 break;
3843
3844 case L2CAP_INFO_RSP:
3845 err = l2cap_information_rsp(conn, cmd, data);
3846 break;
3847
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003848 case L2CAP_CREATE_CHAN_REQ:
3849 err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3850 break;
3851
3852 case L2CAP_CREATE_CHAN_RSP:
3853 err = l2cap_create_channel_rsp(conn, cmd, data);
3854 break;
3855
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003856 case L2CAP_MOVE_CHAN_REQ:
3857 err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
3858 break;
3859
3860 case L2CAP_MOVE_CHAN_RSP:
3861 err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
3862 break;
3863
3864 case L2CAP_MOVE_CHAN_CFM:
3865 err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
3866 break;
3867
3868 case L2CAP_MOVE_CHAN_CFM_RSP:
3869 err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
3870 break;
3871
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003872 default:
3873 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3874 err = -EINVAL;
3875 break;
3876 }
3877
3878 return err;
3879}
3880
3881static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3882 struct l2cap_cmd_hdr *cmd, u8 *data)
3883{
3884 switch (cmd->code) {
3885 case L2CAP_COMMAND_REJ:
3886 return 0;
3887
3888 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003889 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003890
3891 case L2CAP_CONN_PARAM_UPDATE_RSP:
3892 return 0;
3893
3894 default:
3895 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3896 return -EINVAL;
3897 }
3898}
3899
3900static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3901 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902{
3903 u8 *data = skb->data;
3904 int len = skb->len;
3905 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003906 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907
3908 l2cap_raw_recv(conn, skb);
3909
3910 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003911 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3913 data += L2CAP_CMD_HDR_SIZE;
3914 len -= L2CAP_CMD_HDR_SIZE;
3915
Al Viro88219a02007-07-29 00:17:25 -07003916 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917
Al Viro88219a02007-07-29 00:17:25 -07003918 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 -07003919
Al Viro88219a02007-07-29 00:17:25 -07003920 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921 BT_DBG("corrupted command");
3922 break;
3923 }
3924
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003925 if (conn->hcon->type == LE_LINK)
3926 err = l2cap_le_sig_cmd(conn, &cmd, data);
3927 else
3928 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929
3930 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003931 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003932
3933 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934
3935 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003936 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3938 }
3939
Al Viro88219a02007-07-29 00:17:25 -07003940 data += cmd_len;
3941 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942 }
3943
3944 kfree_skb(skb);
3945}
3946
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003947static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003948{
3949 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003950 int hdr_size;
3951
3952 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3953 hdr_size = L2CAP_EXT_HDR_SIZE;
3954 else
3955 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003956
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003957 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003958 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003959 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3960 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3961
3962 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003963 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003964 }
3965 return 0;
3966}
3967
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003968static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003969{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003970 u32 control = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003971
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003972 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003973
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003974 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003975
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003976 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003977 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003978 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003979 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003980 }
3981
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003982 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003983 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003984
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003985 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003986
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003987 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003988 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003989 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003990 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003991 }
3992}
3993
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003994static 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 -03003995{
3996 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003997 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003998
Mat Martineau3ce35142012-04-25 16:36:14 -07003999 bt_cb(skb)->control.txseq = tx_seq;
4000 bt_cb(skb)->control.sar = sar;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004001
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004002 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004003
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004004 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03004005
Szymon Janc039d9572011-11-16 09:32:19 +01004006 while (next_skb) {
Mat Martineau3ce35142012-04-25 16:36:14 -07004007 if (bt_cb(next_skb)->control.txseq == tx_seq)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004008 return -EINVAL;
4009
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004010 next_tx_seq_offset = __seq_offset(chan,
Mat Martineau3ce35142012-04-25 16:36:14 -07004011 bt_cb(next_skb)->control.txseq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03004012
4013 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004014 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004015 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004016 }
4017
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004018 if (skb_queue_is_last(&chan->srej_q, next_skb))
Szymon Janc039d9572011-11-16 09:32:19 +01004019 next_skb = NULL;
4020 else
4021 next_skb = skb_queue_next(&chan->srej_q, next_skb);
4022 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004023
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004024 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004025
4026 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004027}
4028
Mat Martineau84084a32011-07-22 14:54:00 -07004029static void append_skb_frag(struct sk_buff *skb,
4030 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004031{
Mat Martineau84084a32011-07-22 14:54:00 -07004032 /* skb->len reflects data in skb as well as all fragments
4033 * skb->data_len reflects only data in fragments
4034 */
4035 if (!skb_has_frag_list(skb))
4036 skb_shinfo(skb)->frag_list = new_frag;
4037
4038 new_frag->next = NULL;
4039
4040 (*last_frag)->next = new_frag;
4041 *last_frag = new_frag;
4042
4043 skb->len += new_frag->len;
4044 skb->data_len += new_frag->len;
4045 skb->truesize += new_frag->truesize;
4046}
4047
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004048static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
Mat Martineau84084a32011-07-22 14:54:00 -07004049{
4050 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004051
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004052 switch (__get_ctrl_sar(chan, control)) {
4053 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07004054 if (chan->sdu)
4055 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004056
Mat Martineau84084a32011-07-22 14:54:00 -07004057 err = chan->ops->recv(chan->data, skb);
4058 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004059
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004060 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07004061 if (chan->sdu)
4062 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004063
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03004064 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004065 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004066
Mat Martineau84084a32011-07-22 14:54:00 -07004067 if (chan->sdu_len > chan->imtu) {
4068 err = -EMSGSIZE;
4069 break;
4070 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004071
Mat Martineau84084a32011-07-22 14:54:00 -07004072 if (skb->len >= chan->sdu_len)
4073 break;
4074
4075 chan->sdu = skb;
4076 chan->sdu_last_frag = skb;
4077
4078 skb = NULL;
4079 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004080 break;
4081
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004082 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03004083 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07004084 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004085
Mat Martineau84084a32011-07-22 14:54:00 -07004086 append_skb_frag(chan->sdu, skb,
4087 &chan->sdu_last_frag);
4088 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004089
Mat Martineau84084a32011-07-22 14:54:00 -07004090 if (chan->sdu->len >= chan->sdu_len)
4091 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03004092
Mat Martineau84084a32011-07-22 14:54:00 -07004093 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004094 break;
4095
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004096 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03004097 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07004098 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004099
Mat Martineau84084a32011-07-22 14:54:00 -07004100 append_skb_frag(chan->sdu, skb,
4101 &chan->sdu_last_frag);
4102 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004103
Mat Martineau84084a32011-07-22 14:54:00 -07004104 if (chan->sdu->len != chan->sdu_len)
4105 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004106
Mat Martineau84084a32011-07-22 14:54:00 -07004107 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03004108
Mat Martineau84084a32011-07-22 14:54:00 -07004109 if (!err) {
4110 /* Reassembly complete */
4111 chan->sdu = NULL;
4112 chan->sdu_last_frag = NULL;
4113 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004114 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004115 break;
4116 }
4117
Mat Martineau84084a32011-07-22 14:54:00 -07004118 if (err) {
4119 kfree_skb(skb);
4120 kfree_skb(chan->sdu);
4121 chan->sdu = NULL;
4122 chan->sdu_last_frag = NULL;
4123 chan->sdu_len = 0;
4124 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004125
Mat Martineau84084a32011-07-22 14:54:00 -07004126 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004127}
4128
Mat Martineau26f880d2011-07-07 09:39:01 -07004129static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004130{
Mat Martineau26f880d2011-07-07 09:39:01 -07004131 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004132
Mat Martineau26f880d2011-07-07 09:39:01 -07004133 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
Mat Martineau3c588192012-04-11 10:48:42 -07004134 l2cap_seq_list_clear(&chan->srej_list);
Mat Martineau26f880d2011-07-07 09:39:01 -07004135
Szymon Janc77f918b2012-01-11 10:59:48 +01004136 __set_ack_timer(chan);
Mat Martineau26f880d2011-07-07 09:39:01 -07004137}
4138
4139static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
4140{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004141 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004142
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004143 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004144 goto done;
4145
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004146 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004147 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004148 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004149 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004150 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004151
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004152 __clear_retrans_timer(chan);
4153 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004154
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004155 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004156
4157done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004158 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
4159 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004160
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004161 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03004162}
4163
Mat Martineaue3281402011-07-07 09:39:02 -07004164void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03004165{
Mat Martineaue3281402011-07-07 09:39:02 -07004166 if (chan->mode == L2CAP_MODE_ERTM) {
4167 if (busy)
4168 l2cap_ertm_enter_local_busy(chan);
4169 else
4170 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03004171 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004172}
4173
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004174static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004175{
4176 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004177 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004178
Mat Martineaue3281402011-07-07 09:39:02 -07004179 while ((skb = skb_peek(&chan->srej_q)) &&
4180 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4181 int err;
4182
Mat Martineau3ce35142012-04-25 16:36:14 -07004183 if (bt_cb(skb)->control.txseq != tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004184 break;
4185
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004186 skb = skb_dequeue(&chan->srej_q);
Mat Martineau3ce35142012-04-25 16:36:14 -07004187 control = __set_ctrl_sar(chan, bt_cb(skb)->control.sar);
Mat Martineau84084a32011-07-22 14:54:00 -07004188 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07004189
4190 if (err < 0) {
4191 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4192 break;
4193 }
4194
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004195 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
4196 tx_seq = __next_seq(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004197 }
4198}
4199
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004200static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004201{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004202 struct srej_list *l, *tmp;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004203 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004204
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004205 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004206 if (l->tx_seq == tx_seq) {
4207 list_del(&l->list);
4208 kfree(l);
4209 return;
4210 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004211 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004212 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004213 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004214 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004215 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004216 }
4217}
4218
Szymon Jancaef89f22011-11-16 09:32:18 +01004219static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004220{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004221 struct srej_list *new;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004222 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004223
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004224 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004225 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004226 control |= __set_reqseq(chan, chan->expected_tx_seq);
Mat Martineau3c588192012-04-11 10:48:42 -07004227 l2cap_seq_list_append(&chan->srej_list, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004228 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004229
4230 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Szymon Jancaef89f22011-11-16 09:32:18 +01004231 if (!new)
4232 return -ENOMEM;
4233
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004234 new->tx_seq = chan->expected_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004235
4236 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
4237
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004238 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004239 }
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004240
4241 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Szymon Jancaef89f22011-11-16 09:32:18 +01004242
4243 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004244}
4245
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004246static 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 -03004247{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004248 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004249 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004250 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03004251 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004252 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004253 int err = 0;
4254
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004255 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 -03004256 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004257
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004258 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004259 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004260 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004261 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004262 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004263 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004264 }
4265
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004266 chan->expected_ack_seq = req_seq;
4267 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03004268
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004269 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004270
4271 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004272 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004273 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004274 goto drop;
4275 }
4276
Szymon Janc77f918b2012-01-11 10:59:48 +01004277 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4278 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
4279 l2cap_send_ack(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004280 goto drop;
Szymon Janc77f918b2012-01-11 10:59:48 +01004281 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004282
Mat Martineau02f1b642011-06-29 14:35:19 -07004283 if (tx_seq == chan->expected_tx_seq)
4284 goto expected;
4285
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004286 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004287 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004288
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004289 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004290 struct srej_list, list);
4291 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004292 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004293 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004294
4295 list_del(&first->list);
4296 kfree(first);
4297
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004298 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004299 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004300 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004301 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004302 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004303 }
4304 } else {
4305 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004306
4307 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004308 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004309 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004310
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004311 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004312 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004313 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004314 return 0;
4315 }
4316 }
Szymon Jancaef89f22011-11-16 09:32:18 +01004317
4318 err = l2cap_send_srejframe(chan, tx_seq);
4319 if (err < 0) {
4320 l2cap_send_disconn_req(chan->conn, chan, -err);
4321 return err;
4322 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004323 }
4324 } else {
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004325 expected_tx_seq_offset = __seq_offset(chan,
4326 chan->expected_tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004327
4328 /* duplicated tx_seq */
4329 if (tx_seq_offset < expected_tx_seq_offset)
4330 goto drop;
4331
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004332 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004333
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004334 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004335
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004336 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004337 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004338
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004339 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004340 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004341
Szymon Janc0ef3ef02012-01-11 10:59:46 +01004342 /* Set P-bit only if there are some I-frames to ack. */
4343 if (__clear_ack_timer(chan))
4344 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03004345
Szymon Jancaef89f22011-11-16 09:32:18 +01004346 err = l2cap_send_srejframe(chan, tx_seq);
4347 if (err < 0) {
4348 l2cap_send_disconn_req(chan->conn, chan, -err);
4349 return err;
4350 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004351 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004352 return 0;
4353
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004354expected:
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004355 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004356
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004357 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Mat Martineau3ce35142012-04-25 16:36:14 -07004358 bt_cb(skb)->control.txseq = tx_seq;
4359 bt_cb(skb)->control.sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004360 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004361 return 0;
4362 }
4363
Mat Martineau84084a32011-07-22 14:54:00 -07004364 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004365 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
4366
Mat Martineaue3281402011-07-07 09:39:02 -07004367 if (err < 0) {
4368 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4369 return err;
4370 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03004371
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004372 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004373 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004374 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03004375 }
4376
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03004377
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004378 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
4379 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004380 l2cap_send_ack(chan);
Gustavo F. Padovan4d611e42011-06-23 19:30:48 -03004381 else
4382 __set_ack_timer(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03004383
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004384 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004385
4386drop:
4387 kfree_skb(skb);
4388 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004389}
4390
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004391static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004392{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004393 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004394 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004395
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004396 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004397 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004398
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004399 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004400 set_bit(CONN_SEND_FBIT, &chan->conn_state);
4401 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
4402 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004403 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004404 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004405
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004406 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004407 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004408 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004409 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004410 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004411
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004412 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004413 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004414
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004415 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004416 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004417
4418 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004419 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004420 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004421 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004422
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004423 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4424 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004425 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02004426 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004427 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004428 }
4429}
4430
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004431static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004432{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004433 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004434
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004435 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004436
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004437 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004438
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004439 chan->expected_ack_seq = tx_seq;
4440 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004441
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004442 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004443 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004444 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004445 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004446 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004447
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004448 if (test_bit(CONN_WAIT_F, &chan->conn_state))
4449 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004450 }
4451}
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004452static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004453{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004454 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004455
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004456 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004457
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004458 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004459
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004460 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004461 chan->expected_ack_seq = tx_seq;
4462 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004463
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004464 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004465 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004466
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004467 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004468
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004469 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004470 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004471 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004472 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004473 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004474 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004475 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004476 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004477 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004478 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004479 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004480 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004481 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004482 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004483 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004484 }
4485 }
4486}
4487
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004488static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004489{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004490 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004491
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004492 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004493
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004494 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004495 chan->expected_ack_seq = tx_seq;
4496 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004497
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004498 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004499 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004500
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004501 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004502 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004503 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004504 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004505 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004506 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004507
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004508 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004509 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004510 } else {
4511 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4512 l2cap_send_sframe(chan, rx_control);
4513 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004514}
4515
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004516static 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 -03004517{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004518 BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004519
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004520 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004521 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004522 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004523 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004524 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004525 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004526 }
4527
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004528 switch (__get_ctrl_super(chan, rx_control)) {
4529 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004530 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004531 break;
4532
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004533 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004534 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004535 break;
4536
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004537 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004538 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004539 break;
4540
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004541 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004542 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004543 break;
4544 }
4545
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004546 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004547 return 0;
4548}
4549
Szymon Janccad8f1d2012-01-23 10:06:05 +01004550static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004551{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004552 u32 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004553 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004554 int len, next_tx_seq_offset, req_seq_offset;
4555
Mat Martineaub76bbd62012-04-11 10:48:43 -07004556 __unpack_control(chan, skb);
4557
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004558 control = __get_control(chan, skb->data);
4559 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004560 len = skb->len;
4561
4562 /*
4563 * We can just drop the corrupted I-frame here.
4564 * Receiver will miss it and start proper recovery
4565 * procedures and ask retransmission.
4566 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004567 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004568 goto drop;
4569
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004570 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004571 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004572
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004573 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004574 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004575
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004576 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004577 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004578 goto drop;
4579 }
4580
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004581 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004582
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004583 req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4584
4585 next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4586 chan->expected_ack_seq);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004587
4588 /* check for invalid req-seq */
4589 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004590 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004591 goto drop;
4592 }
4593
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004594 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004595 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004596 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004597 goto drop;
4598 }
4599
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004600 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004601 } else {
4602 if (len != 0) {
4603 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004604 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004605 goto drop;
4606 }
4607
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004608 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004609 }
4610
4611 return 0;
4612
4613drop:
4614 kfree_skb(skb);
4615 return 0;
4616}
4617
Linus Torvalds1da177e2005-04-16 15:20:36 -07004618static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4619{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004620 struct l2cap_chan *chan;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004621 u32 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004622 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004623 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004624
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004625 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004626 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004627 BT_DBG("unknown cid 0x%4.4x", cid);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004628 /* Drop packet and return */
Dan Carpenter33790132012-02-28 09:52:46 +03004629 kfree_skb(skb);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004630 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004631 }
4632
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004633 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004634
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004635 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004636 goto drop;
4637
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004638 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004639 case L2CAP_MODE_BASIC:
4640 /* If socket recv buffers overflows we drop data here
4641 * which is *bad* because L2CAP has to be reliable.
4642 * But we don't have any other choice. L2CAP doesn't
4643 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004644
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004645 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004646 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004647
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004648 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004649 goto done;
4650 break;
4651
4652 case L2CAP_MODE_ERTM:
Andrei Emeltchenko5ef8cb92012-01-13 17:21:42 +02004653 l2cap_ertm_data_rcv(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004654
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004655 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004656
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004657 case L2CAP_MODE_STREAMING:
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004658 control = __get_control(chan, skb->data);
4659 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004660 len = skb->len;
4661
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004662 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004663 goto drop;
4664
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004665 if (__is_sar_start(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004666 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004667
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004668 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004669 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004670
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004671 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004672 goto drop;
4673
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004674 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004675
Mat Martineau84084a32011-07-22 14:54:00 -07004676 if (chan->expected_tx_seq != tx_seq) {
4677 /* Frame(s) missing - must discard partial SDU */
4678 kfree_skb(chan->sdu);
4679 chan->sdu = NULL;
4680 chan->sdu_last_frag = NULL;
4681 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004682
Mat Martineau84084a32011-07-22 14:54:00 -07004683 /* TODO: Notify userland of missing data */
4684 }
4685
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004686 chan->expected_tx_seq = __next_seq(chan, tx_seq);
Mat Martineau84084a32011-07-22 14:54:00 -07004687
4688 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
4689 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004690
4691 goto done;
4692
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004693 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004694 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004695 break;
4696 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004697
4698drop:
4699 kfree_skb(skb);
4700
4701done:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004702 l2cap_chan_unlock(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +02004703
Linus Torvalds1da177e2005-04-16 15:20:36 -07004704 return 0;
4705}
4706
Al Viro8e036fc2007-07-29 00:16:36 -07004707static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004708{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004709 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004710
Ido Yarivc2287682012-04-20 15:46:07 -03004711 chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004712 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004713 goto drop;
4714
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02004715 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004716
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004717 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004718 goto drop;
4719
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004720 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004721 goto drop;
4722
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004723 if (!chan->ops->recv(chan->data, skb))
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02004724 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004725
4726drop:
4727 kfree_skb(skb);
4728
Linus Torvalds1da177e2005-04-16 15:20:36 -07004729 return 0;
4730}
4731
Andrei Emeltchenkod9b88702012-03-12 12:13:08 +02004732static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid,
4733 struct sk_buff *skb)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004734{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004735 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004736
Ido Yarivc2287682012-04-20 15:46:07 -03004737 chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004738 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004739 goto drop;
4740
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02004741 BT_DBG("chan %p, len %d", chan, skb->len);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004742
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004743 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004744 goto drop;
4745
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004746 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004747 goto drop;
4748
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004749 if (!chan->ops->recv(chan->data, skb))
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02004750 return 0;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004751
4752drop:
4753 kfree_skb(skb);
4754
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004755 return 0;
4756}
4757
Linus Torvalds1da177e2005-04-16 15:20:36 -07004758static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4759{
4760 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004761 u16 cid, len;
4762 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004763
4764 skb_pull(skb, L2CAP_HDR_SIZE);
4765 cid = __le16_to_cpu(lh->cid);
4766 len = __le16_to_cpu(lh->len);
4767
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004768 if (len != skb->len) {
4769 kfree_skb(skb);
4770 return;
4771 }
4772
Linus Torvalds1da177e2005-04-16 15:20:36 -07004773 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4774
4775 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004776 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004777 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004778 l2cap_sig_channel(conn, skb);
4779 break;
4780
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004781 case L2CAP_CID_CONN_LESS:
Andrei Emeltchenko097db762012-03-09 14:16:17 +02004782 psm = get_unaligned((__le16 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004783 skb_pull(skb, 2);
4784 l2cap_conless_channel(conn, psm, skb);
4785 break;
4786
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004787 case L2CAP_CID_LE_DATA:
4788 l2cap_att_channel(conn, cid, skb);
4789 break;
4790
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004791 case L2CAP_CID_SMP:
4792 if (smp_sig_channel(conn, skb))
4793 l2cap_conn_del(conn->hcon, EACCES);
4794 break;
4795
Linus Torvalds1da177e2005-04-16 15:20:36 -07004796 default:
4797 l2cap_data_channel(conn, cid, skb);
4798 break;
4799 }
4800}
4801
4802/* ---- L2CAP interface with lower layer (HCI) ---- */
4803
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004804int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004805{
4806 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004807 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004808
Linus Torvalds1da177e2005-04-16 15:20:36 -07004809 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4810
4811 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004812 read_lock(&chan_list_lock);
4813 list_for_each_entry(c, &chan_list, global_l) {
4814 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004815
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004816 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004817 continue;
4818
4819 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004820 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004821 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004822 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004823 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004824 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4825 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004826 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004827 lm2 |= HCI_LM_MASTER;
4828 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004829 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004830 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004831
4832 return exact ? lm1 : lm2;
4833}
4834
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004835int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004836{
Marcel Holtmann01394182006-07-03 10:02:46 +02004837 struct l2cap_conn *conn;
4838
Linus Torvalds1da177e2005-04-16 15:20:36 -07004839 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4840
Linus Torvalds1da177e2005-04-16 15:20:36 -07004841 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004842 conn = l2cap_conn_add(hcon, status);
4843 if (conn)
4844 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004845 } else
Joe Perchese1750722011-06-29 18:18:29 -07004846 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004847
4848 return 0;
4849}
4850
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004851int l2cap_disconn_ind(struct hci_conn *hcon)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004852{
4853 struct l2cap_conn *conn = hcon->l2cap_data;
4854
4855 BT_DBG("hcon %p", hcon);
4856
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004857 if (!conn)
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02004858 return HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01004859 return conn->disc_reason;
4860}
4861
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004862int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004863{
4864 BT_DBG("hcon %p reason %d", hcon, reason);
4865
Joe Perchese1750722011-06-29 18:18:29 -07004866 l2cap_conn_del(hcon, bt_to_errno(reason));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004867 return 0;
4868}
4869
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004870static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004871{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004872 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004873 return;
4874
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004875 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004876 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08004877 __set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004878 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004879 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004880 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004881 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004882 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004883 }
4884}
4885
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004886int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004887{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004888 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004889 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004890
Marcel Holtmann01394182006-07-03 10:02:46 +02004891 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004892 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004893
Linus Torvalds1da177e2005-04-16 15:20:36 -07004894 BT_DBG("conn %p", conn);
4895
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004896 if (hcon->type == LE_LINK) {
Hemant Gupta35d4adcc2012-04-18 14:46:26 +05304897 if (!status && encrypt)
4898 smp_distribute_keys(conn, 0);
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02004899 cancel_delayed_work(&conn->security_timer);
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004900 }
4901
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004902 mutex_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004903
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004904 list_for_each_entry(chan, &conn->chan_l, list) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004905 l2cap_chan_lock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004906
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004907 BT_DBG("chan->scid %d", chan->scid);
4908
4909 if (chan->scid == L2CAP_CID_LE_DATA) {
4910 if (!status && encrypt) {
4911 chan->sec_level = hcon->sec_level;
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02004912 l2cap_chan_ready(chan);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004913 }
4914
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004915 l2cap_chan_unlock(chan);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004916 continue;
4917 }
4918
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004919 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004920 l2cap_chan_unlock(chan);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004921 continue;
4922 }
4923
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004924 if (!status && (chan->state == BT_CONNECTED ||
4925 chan->state == BT_CONFIG)) {
Gustavo Padovana7d77232012-05-13 03:20:07 -03004926 struct sock *sk = chan->sk;
4927
Gustavo Padovanc5daa682012-05-16 12:17:10 -03004928 clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
Gustavo Padovana7d77232012-05-13 03:20:07 -03004929 sk->sk_state_change(sk);
4930
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004931 l2cap_check_encryption(chan, encrypt);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004932 l2cap_chan_unlock(chan);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004933 continue;
4934 }
4935
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004936 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004937 if (!status) {
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +02004938 l2cap_send_conn_req(chan);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004939 } else {
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08004940 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004941 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004942 } else if (chan->state == BT_CONNECT2) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004943 struct sock *sk = chan->sk;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004944 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004945 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004946
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004947 lock_sock(sk);
4948
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004949 if (!status) {
Gustavo Padovanc5daa682012-05-16 12:17:10 -03004950 if (test_bit(BT_SK_DEFER_SETUP,
4951 &bt_sk(sk)->flags)) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004952 struct sock *parent = bt_sk(sk)->parent;
4953 res = L2CAP_CR_PEND;
4954 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004955 if (parent)
4956 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004957 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02004958 __l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004959 res = L2CAP_CR_SUCCESS;
4960 stat = L2CAP_CS_NO_INFO;
4961 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004962 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02004963 __l2cap_state_change(chan, BT_DISCONN);
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08004964 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004965 res = L2CAP_CR_SEC_BLOCK;
4966 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004967 }
4968
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004969 release_sock(sk);
4970
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004971 rsp.scid = cpu_to_le16(chan->dcid);
4972 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004973 rsp.result = cpu_to_le16(res);
4974 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004975 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4976 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004977 }
4978
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004979 l2cap_chan_unlock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004980 }
4981
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004982 mutex_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004983
Linus Torvalds1da177e2005-04-16 15:20:36 -07004984 return 0;
4985}
4986
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004987int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004988{
4989 struct l2cap_conn *conn = hcon->l2cap_data;
4990
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004991 if (!conn)
4992 conn = l2cap_conn_add(hcon, 0);
4993
4994 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004995 goto drop;
4996
4997 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4998
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004999 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005000 struct l2cap_hdr *hdr;
5001 int len;
5002
5003 if (conn->rx_len) {
5004 BT_ERR("Unexpected start frame (len %d)", skb->len);
5005 kfree_skb(conn->rx_skb);
5006 conn->rx_skb = NULL;
5007 conn->rx_len = 0;
5008 l2cap_conn_unreliable(conn, ECOMM);
5009 }
5010
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03005011 /* Start fragment always begin with Basic L2CAP header */
5012 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005013 BT_ERR("Frame is too short (len %d)", skb->len);
5014 l2cap_conn_unreliable(conn, ECOMM);
5015 goto drop;
5016 }
5017
5018 hdr = (struct l2cap_hdr *) skb->data;
5019 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
5020
5021 if (len == skb->len) {
5022 /* Complete frame received */
5023 l2cap_recv_frame(conn, skb);
5024 return 0;
5025 }
5026
5027 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
5028
5029 if (skb->len > len) {
5030 BT_ERR("Frame is too long (len %d, expected len %d)",
5031 skb->len, len);
5032 l2cap_conn_unreliable(conn, ECOMM);
5033 goto drop;
5034 }
5035
5036 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03005037 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
5038 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005039 goto drop;
5040
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03005041 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01005042 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005043 conn->rx_len = len - skb->len;
5044 } else {
5045 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
5046
5047 if (!conn->rx_len) {
5048 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
5049 l2cap_conn_unreliable(conn, ECOMM);
5050 goto drop;
5051 }
5052
5053 if (skb->len > conn->rx_len) {
5054 BT_ERR("Fragment is too long (len %d, expected %d)",
5055 skb->len, conn->rx_len);
5056 kfree_skb(conn->rx_skb);
5057 conn->rx_skb = NULL;
5058 conn->rx_len = 0;
5059 l2cap_conn_unreliable(conn, ECOMM);
5060 goto drop;
5061 }
5062
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03005063 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01005064 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005065 conn->rx_len -= skb->len;
5066
5067 if (!conn->rx_len) {
5068 /* Complete frame received */
5069 l2cap_recv_frame(conn, conn->rx_skb);
5070 conn->rx_skb = NULL;
5071 }
5072 }
5073
5074drop:
5075 kfree_skb(skb);
5076 return 0;
5077}
5078
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005079static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005080{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005081 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005082
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02005083 read_lock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005084
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005085 list_for_each_entry(c, &chan_list, global_l) {
5086 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005087
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02005088 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 +01005089 batostr(&bt_sk(sk)->src),
5090 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03005091 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005092 c->scid, c->dcid, c->imtu, c->omtu,
5093 c->sec_level, c->mode);
Andrei Emeltchenko61e1b4b2012-01-19 11:19:50 +02005094 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005095
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02005096 read_unlock(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08005097
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005098 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005099}
5100
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005101static int l2cap_debugfs_open(struct inode *inode, struct file *file)
5102{
5103 return single_open(file, l2cap_debugfs_show, inode->i_private);
5104}
5105
5106static const struct file_operations l2cap_debugfs_fops = {
5107 .open = l2cap_debugfs_open,
5108 .read = seq_read,
5109 .llseek = seq_lseek,
5110 .release = single_release,
5111};
5112
5113static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005114
Gustavo F. Padovan64274512011-02-07 20:08:52 -02005115int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005116{
5117 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08005118
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02005119 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005120 if (err < 0)
5121 return err;
5122
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005123 if (bt_debugfs) {
5124 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
5125 bt_debugfs, NULL, &l2cap_debugfs_fops);
5126 if (!l2cap_debugfs)
5127 BT_ERR("Failed to create L2CAP debug file");
5128 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005129
Linus Torvalds1da177e2005-04-16 15:20:36 -07005130 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005131}
5132
Gustavo F. Padovan64274512011-02-07 20:08:52 -02005133void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005134{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005135 debugfs_remove(l2cap_debugfs);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02005136 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005137}
5138
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03005139module_param(disable_ertm, bool, 0644);
5140MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");