blob: 0a195ab4a385a2f78630dd6b027402268e9e837d [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
Mat Martineaub191e032012-05-17 20:53:31 -070060bool disable_ertm = 1;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020061
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070062static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Mat Martineau50a147c2011-11-02 16:18:34 -070063static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Johannes Bergb5ad8b72011-06-01 08:54:45 +020065static LIST_HEAD(chan_list);
66static DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Linus Torvalds1da177e2005-04-16 15:20:36 -070068static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
69 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030070static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
71 void *data);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -030072static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030073static void l2cap_send_disconn_req(struct l2cap_conn *conn,
Gustavo Padovanc5daa682012-05-16 12:17:10 -030074 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
Mat Martineau608bcc62012-05-17 20:53:32 -070076static int l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
77 struct sk_buff_head *skbs, u8 event);
78
Marcel Holtmann01394182006-07-03 10:02:46 +020079/* ---- L2CAP channels ---- */
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -030080
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030081static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020082{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020083 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030084
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020085 list_for_each_entry(c, &conn->chan_l, list) {
86 if (c->dcid == cid)
87 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020088 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020089 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +020090}
91
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030092static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020093{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020094 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030095
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020096 list_for_each_entry(c, &conn->chan_l, list) {
97 if (c->scid == cid)
98 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020099 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200100 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200101}
102
103/* Find channel with given SCID.
Mat Martineauef191ad2012-05-02 09:42:00 -0700104 * Returns locked channel. */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300105static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200106{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300107 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300108
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200109 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300110 c = __l2cap_get_chan_by_scid(conn, cid);
Mat Martineauef191ad2012-05-02 09:42:00 -0700111 if (c)
112 l2cap_chan_lock(c);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200113 mutex_unlock(&conn->chan_lock);
114
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300115 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200116}
117
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300118static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200119{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200120 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300121
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200122 list_for_each_entry(c, &conn->chan_l, list) {
123 if (c->ident == ident)
124 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200125 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200126 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200127}
128
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300129static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300130{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300131 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300132
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300133 list_for_each_entry(c, &chan_list, global_l) {
134 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Szymon Janc250938c2011-11-16 09:32:22 +0100135 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300136 }
Szymon Janc250938c2011-11-16 09:32:22 +0100137 return NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300138}
139
140int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
141{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300142 int err;
143
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200144 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300145
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300146 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300147 err = -EADDRINUSE;
148 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300149 }
150
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300151 if (psm) {
152 chan->psm = psm;
153 chan->sport = psm;
154 err = 0;
155 } else {
156 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300157
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300158 err = -EINVAL;
159 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300160 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300161 chan->psm = cpu_to_le16(p);
162 chan->sport = cpu_to_le16(p);
163 err = 0;
164 break;
165 }
166 }
167
168done:
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200169 write_unlock(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300170 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300171}
172
173int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
174{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200175 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300176
177 chan->scid = scid;
178
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200179 write_unlock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300180
181 return 0;
182}
183
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300184static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200185{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300186 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200187
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300188 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300189 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200190 return cid;
191 }
192
193 return 0;
194}
195
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200196static void __l2cap_state_change(struct l2cap_chan *chan, int state)
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300197{
Andrei Emeltchenko42d2d872012-02-17 11:40:57 +0200198 BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
Gustavo F. Padovanbadaaa02011-11-23 20:11:46 -0200199 state_to_string(state));
200
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300201 chan->state = state;
202 chan->ops->state_change(chan->data, state);
203}
204
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200205static void l2cap_state_change(struct l2cap_chan *chan, int state)
206{
207 struct sock *sk = chan->sk;
208
209 lock_sock(sk);
210 __l2cap_state_change(chan, state);
211 release_sock(sk);
212}
213
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +0200214static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err)
215{
216 struct sock *sk = chan->sk;
217
218 sk->sk_err = err;
219}
220
221static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
222{
223 struct sock *sk = chan->sk;
224
225 lock_sock(sk);
226 __l2cap_chan_set_err(chan, err);
227 release_sock(sk);
228}
229
Mat Martineau608bcc62012-05-17 20:53:32 -0700230static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head,
231 u16 seq)
232{
233 struct sk_buff *skb;
234
235 skb_queue_walk(head, skb) {
236 if (bt_cb(skb)->control.txseq == seq)
237 return skb;
238 }
239
240 return NULL;
241}
242
Mat Martineau3c588192012-04-11 10:48:42 -0700243/* ---- L2CAP sequence number lists ---- */
244
245/* For ERTM, ordered lists of sequence numbers must be tracked for
246 * SREJ requests that are received and for frames that are to be
247 * retransmitted. These seq_list functions implement a singly-linked
248 * list in an array, where membership in the list can also be checked
249 * in constant time. Items can also be added to the tail of the list
250 * and removed from the head in constant time, without further memory
251 * allocs or frees.
252 */
253
254static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
255{
256 size_t alloc_size, i;
257
258 /* Allocated size is a power of 2 to map sequence numbers
259 * (which may be up to 14 bits) in to a smaller array that is
260 * sized for the negotiated ERTM transmit windows.
261 */
262 alloc_size = roundup_pow_of_two(size);
263
264 seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL);
265 if (!seq_list->list)
266 return -ENOMEM;
267
268 seq_list->mask = alloc_size - 1;
269 seq_list->head = L2CAP_SEQ_LIST_CLEAR;
270 seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
271 for (i = 0; i < alloc_size; i++)
272 seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
273
274 return 0;
275}
276
277static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
278{
279 kfree(seq_list->list);
280}
281
282static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
283 u16 seq)
284{
285 /* Constant-time check for list membership */
286 return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
287}
288
289static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq)
290{
291 u16 mask = seq_list->mask;
292
293 if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) {
294 /* In case someone tries to pop the head of an empty list */
295 return L2CAP_SEQ_LIST_CLEAR;
296 } else if (seq_list->head == seq) {
297 /* Head can be removed in constant time */
298 seq_list->head = seq_list->list[seq & mask];
299 seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
300
301 if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
302 seq_list->head = L2CAP_SEQ_LIST_CLEAR;
303 seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
304 }
305 } else {
306 /* Walk the list to find the sequence number */
307 u16 prev = seq_list->head;
308 while (seq_list->list[prev & mask] != seq) {
309 prev = seq_list->list[prev & mask];
310 if (prev == L2CAP_SEQ_LIST_TAIL)
311 return L2CAP_SEQ_LIST_CLEAR;
312 }
313
314 /* Unlink the number from the list and clear it */
315 seq_list->list[prev & mask] = seq_list->list[seq & mask];
316 seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
317 if (seq_list->tail == seq)
318 seq_list->tail = prev;
319 }
320 return seq;
321}
322
323static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
324{
325 /* Remove the head in constant time */
326 return l2cap_seq_list_remove(seq_list, seq_list->head);
327}
328
329static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
330{
Gustavo Padovanf522ae32012-05-09 18:28:00 -0300331 u16 i;
Mat Martineau3c588192012-04-11 10:48:42 -0700332
Gustavo Padovanf522ae32012-05-09 18:28:00 -0300333 if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
334 return;
335
336 for (i = 0; i <= seq_list->mask; i++)
337 seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
338
339 seq_list->head = L2CAP_SEQ_LIST_CLEAR;
340 seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
Mat Martineau3c588192012-04-11 10:48:42 -0700341}
342
343static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
344{
345 u16 mask = seq_list->mask;
346
347 /* All appends happen in constant time */
348
Gustavo Padovanf522ae32012-05-09 18:28:00 -0300349 if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
350 return;
Mat Martineau3c588192012-04-11 10:48:42 -0700351
Gustavo Padovanf522ae32012-05-09 18:28:00 -0300352 if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
353 seq_list->head = seq;
354 else
355 seq_list->list[seq_list->tail & mask] = seq;
356
357 seq_list->tail = seq;
358 seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
Mat Martineau3c588192012-04-11 10:48:42 -0700359}
360
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300361static void l2cap_chan_timeout(struct work_struct *work)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300362{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300363 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
364 chan_timer.work);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200365 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300366 int reason;
367
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200368 BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300369
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200370 mutex_lock(&conn->chan_lock);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200371 l2cap_chan_lock(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300372
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300373 if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300374 reason = ECONNREFUSED;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300375 else if (chan->state == BT_CONNECT &&
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300376 chan->sec_level != BT_SECURITY_SDP)
377 reason = ECONNREFUSED;
378 else
379 reason = ETIMEDOUT;
380
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300381 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300382
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200383 l2cap_chan_unlock(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300384
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300385 chan->ops->close(chan->data);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200386 mutex_unlock(&conn->chan_lock);
387
Ulisses Furquim371fd832011-12-21 20:02:36 -0200388 l2cap_chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300389}
390
Gustavo Padovaneef1d9b2012-03-25 13:59:16 -0300391struct l2cap_chan *l2cap_chan_create(void)
Marcel Holtmann01394182006-07-03 10:02:46 +0200392{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300393 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200394
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300395 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
396 if (!chan)
397 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200398
Andrei Emeltchenkoc03b3552012-02-21 12:54:56 +0200399 mutex_init(&chan->lock);
400
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200401 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300402 list_add(&chan->global_l, &chan_list);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200403 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300404
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300405 INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300406
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300407 chan->state = BT_OPEN;
408
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300409 atomic_set(&chan->refcnt, 1);
410
Mat Martineau28270112012-05-17 21:14:09 -0700411 /* This flag is cleared in l2cap_chan_ready() */
412 set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
413
Gustavo Padovaneef1d9b2012-03-25 13:59:16 -0300414 BT_DBG("chan %p", chan);
Szymon Jancabc545b2011-11-03 16:05:44 +0100415
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300416 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200417}
418
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300419void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300420{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200421 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300422 list_del(&chan->global_l);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200423 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300424
Ulisses Furquim371fd832011-12-21 20:02:36 -0200425 l2cap_chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300426}
427
Andrei Emeltchenkobd4b1652012-03-28 16:31:25 +0300428void l2cap_chan_set_defaults(struct l2cap_chan *chan)
429{
430 chan->fcs = L2CAP_FCS_CRC16;
431 chan->max_tx = L2CAP_DEFAULT_MAX_TX;
432 chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
433 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
434 chan->sec_level = BT_SECURITY_LOW;
435
436 set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
437}
438
Andrei Emeltchenko14a28492012-03-23 16:31:49 +0200439static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200440{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300441 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Andrei Emeltchenko097db762012-03-09 14:16:17 +0200442 __le16_to_cpu(chan->psm), chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200443
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +0200444 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +0100445
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300446 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200447
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200448 switch (chan->chan_type) {
449 case L2CAP_CHAN_CONN_ORIENTED:
Ville Tervob62f3282011-02-10 22:38:50 -0300450 if (conn->hcon->type == LE_LINK) {
451 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300452 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300453 chan->scid = L2CAP_CID_LE_DATA;
454 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300455 } else {
456 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300457 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300458 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300459 }
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200460 break;
461
462 case L2CAP_CHAN_CONN_LESS:
Marcel Holtmann01394182006-07-03 10:02:46 +0200463 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300464 chan->scid = L2CAP_CID_CONN_LESS;
465 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300466 chan->omtu = L2CAP_DEFAULT_MTU;
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200467 break;
468
469 default:
Marcel Holtmann01394182006-07-03 10:02:46 +0200470 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300471 chan->scid = L2CAP_CID_SIGNALING;
472 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300473 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200474 }
475
Andrei Emeltchenko8f7975b2011-10-13 16:18:54 +0300476 chan->local_id = L2CAP_BESTEFFORT_ID;
477 chan->local_stype = L2CAP_SERV_BESTEFFORT;
478 chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
479 chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
480 chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
481 chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
482
Ulisses Furquim371fd832011-12-21 20:02:36 -0200483 l2cap_chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300484
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200485 list_add(&chan->list, &conn->chan_l);
Andrei Emeltchenko643162a2012-02-22 17:11:55 +0200486}
487
Andrei Emeltchenko14a28492012-03-23 16:31:49 +0200488static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Andrei Emeltchenko643162a2012-02-22 17:11:55 +0200489{
490 mutex_lock(&conn->chan_lock);
491 __l2cap_chan_add(conn, chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200492 mutex_unlock(&conn->chan_lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200493}
494
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300495static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200496{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300497 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300498 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200499 struct sock *parent = bt_sk(sk)->parent;
500
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300501 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200502
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300503 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200504
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900505 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300506 /* Delete from channel list */
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200507 list_del(&chan->list);
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200508
Ulisses Furquim371fd832011-12-21 20:02:36 -0200509 l2cap_chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300510
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300511 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200512 hci_conn_put(conn->hcon);
513 }
514
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200515 lock_sock(sk);
516
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200517 __l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200518 sock_set_flag(sk, SOCK_ZAPPED);
519
520 if (err)
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +0200521 __l2cap_chan_set_err(chan, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200522
523 if (parent) {
524 bt_accept_unlink(sk);
525 parent->sk_data_ready(parent, 0);
526 } else
527 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300528
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200529 release_sock(sk);
530
Mat Martineau28270112012-05-17 21:14:09 -0700531 if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300532 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300533
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300534 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300535
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300536 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300537 struct srej_list *l, *tmp;
538
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300539 __clear_retrans_timer(chan);
540 __clear_monitor_timer(chan);
541 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300542
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300543 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300544
Mat Martineau3c588192012-04-11 10:48:42 -0700545 l2cap_seq_list_free(&chan->srej_list);
546 l2cap_seq_list_free(&chan->retrans_list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300547 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300548 list_del(&l->list);
549 kfree(l);
550 }
551 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200552}
553
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300554static void l2cap_chan_cleanup_listen(struct sock *parent)
555{
556 struct sock *sk;
557
558 BT_DBG("parent %p", parent);
559
560 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300561 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300562 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200563
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200564 l2cap_chan_lock(chan);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300565 __clear_chan_timer(chan);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300566 l2cap_chan_close(chan, ECONNRESET);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200567 l2cap_chan_unlock(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200568
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300569 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300570 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300571}
572
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300573void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300574{
575 struct l2cap_conn *conn = chan->conn;
576 struct sock *sk = chan->sk;
577
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200578 BT_DBG("chan %p state %s sk %p", chan,
579 state_to_string(chan->state), sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300580
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300581 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300582 case BT_LISTEN:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200583 lock_sock(sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300584 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300585
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200586 __l2cap_state_change(chan, BT_CLOSED);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300587 sock_set_flag(sk, SOCK_ZAPPED);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200588 release_sock(sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300589 break;
590
591 case BT_CONNECTED:
592 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300593 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300594 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300595 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300596 l2cap_send_disconn_req(conn, chan, reason);
597 } else
598 l2cap_chan_del(chan, reason);
599 break;
600
601 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300602 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300603 conn->hcon->type == ACL_LINK) {
604 struct l2cap_conn_rsp rsp;
605 __u16 result;
606
Gustavo Padovanc5daa682012-05-16 12:17:10 -0300607 if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300608 result = L2CAP_CR_SEC_BLOCK;
609 else
610 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300611 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300612
613 rsp.scid = cpu_to_le16(chan->dcid);
614 rsp.dcid = cpu_to_le16(chan->scid);
615 rsp.result = cpu_to_le16(result);
616 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
617 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
618 sizeof(rsp), &rsp);
619 }
620
621 l2cap_chan_del(chan, reason);
622 break;
623
624 case BT_CONNECT:
625 case BT_DISCONN:
626 l2cap_chan_del(chan, reason);
627 break;
628
629 default:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200630 lock_sock(sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300631 sock_set_flag(sk, SOCK_ZAPPED);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200632 release_sock(sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300633 break;
634 }
635}
636
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300637static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530638{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300639 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300640 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530641 case BT_SECURITY_HIGH:
642 return HCI_AT_DEDICATED_BONDING_MITM;
643 case BT_SECURITY_MEDIUM:
644 return HCI_AT_DEDICATED_BONDING;
645 default:
646 return HCI_AT_NO_BONDING;
647 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300648 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300649 if (chan->sec_level == BT_SECURITY_LOW)
650 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530651
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300652 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530653 return HCI_AT_NO_BONDING_MITM;
654 else
655 return HCI_AT_NO_BONDING;
656 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300657 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530658 case BT_SECURITY_HIGH:
659 return HCI_AT_GENERAL_BONDING_MITM;
660 case BT_SECURITY_MEDIUM:
661 return HCI_AT_GENERAL_BONDING;
662 default:
663 return HCI_AT_NO_BONDING;
664 }
665 }
666}
667
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200668/* Service level security */
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200669int l2cap_chan_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200670{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300671 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100672 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200673
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300674 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100675
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300676 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200677}
678
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200679static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200680{
681 u8 id;
682
683 /* Get next available identificator.
684 * 1 - 128 are used by kernel.
685 * 129 - 199 are reserved.
686 * 200 - 254 are used by utilities like l2ping, etc.
687 */
688
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200689 spin_lock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200690
691 if (++conn->tx_ident > 128)
692 conn->tx_ident = 1;
693
694 id = conn->tx_ident;
695
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200696 spin_unlock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200697
698 return id;
699}
700
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300701static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200702{
703 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200704 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200705
706 BT_DBG("code 0x%2.2x", code);
707
708 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300709 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200710
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200711 if (lmp_no_flush_capable(conn->hcon->hdev))
712 flags = ACL_START_NO_FLUSH;
713 else
714 flags = ACL_START;
715
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700716 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +0200717 skb->priority = HCI_PRIO_MAX;
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700718
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200719 hci_send_acl(conn->hchan, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200720}
721
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200722static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
723{
724 struct hci_conn *hcon = chan->conn->hcon;
725 u16 flags;
726
727 BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
728 skb->priority);
729
730 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
731 lmp_no_flush_capable(hcon->hdev))
732 flags = ACL_START_NO_FLUSH;
733 else
734 flags = ACL_START;
735
736 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
737 hci_send_acl(chan->conn->hchan, skb, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738}
739
Mat Martineaub5c6aae2012-04-25 16:36:15 -0700740static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
741{
742 control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
743 control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
744
745 if (enh & L2CAP_CTRL_FRAME_TYPE) {
746 /* S-Frame */
747 control->sframe = 1;
748 control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
749 control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
750
751 control->sar = 0;
752 control->txseq = 0;
753 } else {
754 /* I-Frame */
755 control->sframe = 0;
756 control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
757 control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
758
759 control->poll = 0;
760 control->super = 0;
761 }
762}
763
764static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
765{
766 control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
767 control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
768
769 if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
770 /* S-Frame */
771 control->sframe = 1;
772 control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
773 control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
774
775 control->sar = 0;
776 control->txseq = 0;
777 } else {
778 /* I-Frame */
779 control->sframe = 0;
780 control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
781 control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
782
783 control->poll = 0;
784 control->super = 0;
785 }
786}
787
788static inline void __unpack_control(struct l2cap_chan *chan,
789 struct sk_buff *skb)
790{
791 if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
792 __unpack_extended_control(get_unaligned_le32(skb->data),
793 &bt_cb(skb)->control);
Mat Martineaucec8ab6e2012-05-17 20:53:36 -0700794 skb_pull(skb, L2CAP_EXT_CTRL_SIZE);
Mat Martineaub5c6aae2012-04-25 16:36:15 -0700795 } else {
796 __unpack_enhanced_control(get_unaligned_le16(skb->data),
797 &bt_cb(skb)->control);
Mat Martineaucec8ab6e2012-05-17 20:53:36 -0700798 skb_pull(skb, L2CAP_ENH_CTRL_SIZE);
Mat Martineaub5c6aae2012-04-25 16:36:15 -0700799 }
800}
801
802static u32 __pack_extended_control(struct l2cap_ctrl *control)
803{
804 u32 packed;
805
806 packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
807 packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
808
809 if (control->sframe) {
810 packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
811 packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
812 packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
813 } else {
814 packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
815 packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
816 }
817
818 return packed;
819}
820
821static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
822{
823 u16 packed;
824
825 packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
826 packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
827
828 if (control->sframe) {
829 packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
830 packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
831 packed |= L2CAP_CTRL_FRAME_TYPE;
832 } else {
833 packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
834 packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
835 }
836
837 return packed;
838}
839
840static inline void __pack_control(struct l2cap_chan *chan,
841 struct l2cap_ctrl *control,
842 struct sk_buff *skb)
843{
844 if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
845 put_unaligned_le32(__pack_extended_control(control),
846 skb->data + L2CAP_HDR_SIZE);
847 } else {
848 put_unaligned_le16(__pack_enhanced_control(control),
849 skb->data + L2CAP_HDR_SIZE);
850 }
851}
852
Mat Martineaua67d7f62012-05-17 20:53:35 -0700853static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
854 u32 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300855{
856 struct sk_buff *skb;
857 struct l2cap_hdr *lh;
Mat Martineaua67d7f62012-05-17 20:53:35 -0700858 int hlen;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300859
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300860 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
861 hlen = L2CAP_EXT_HDR_SIZE;
862 else
863 hlen = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300864
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300865 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300866 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300867
Mat Martineaua67d7f62012-05-17 20:53:35 -0700868 skb = bt_skb_alloc(hlen, GFP_KERNEL);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300869
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300870 if (!skb)
Mat Martineaua67d7f62012-05-17 20:53:35 -0700871 return ERR_PTR(-ENOMEM);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300872
873 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300874 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300875 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300876
Mat Martineaua67d7f62012-05-17 20:53:35 -0700877 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
878 put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
879 else
880 put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300881
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300882 if (chan->fcs == L2CAP_FCS_CRC16) {
Mat Martineaua67d7f62012-05-17 20:53:35 -0700883 u16 fcs = crc16(0, (u8 *)skb->data, skb->len);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300884 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300885 }
886
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200887 skb->priority = HCI_PRIO_MAX;
Mat Martineaua67d7f62012-05-17 20:53:35 -0700888 return skb;
889}
890
891static void l2cap_send_sframe(struct l2cap_chan *chan,
892 struct l2cap_ctrl *control)
893{
894 struct sk_buff *skb;
895 u32 control_field;
896
897 BT_DBG("chan %p, control %p", chan, control);
898
899 if (!control->sframe)
900 return;
901
902 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
903 !control->poll)
904 control->final = 1;
905
906 if (control->super == L2CAP_SUPER_RR)
907 clear_bit(CONN_RNR_SENT, &chan->conn_state);
908 else if (control->super == L2CAP_SUPER_RNR)
909 set_bit(CONN_RNR_SENT, &chan->conn_state);
910
911 if (control->super != L2CAP_SUPER_SREJ) {
912 chan->last_acked_seq = control->reqseq;
913 __clear_ack_timer(chan);
914 }
915
916 BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq,
917 control->final, control->poll, control->super);
918
919 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
920 control_field = __pack_extended_control(control);
921 else
922 control_field = __pack_enhanced_control(control);
923
924 skb = l2cap_create_sframe_pdu(chan, control_field);
925 if (!IS_ERR(skb))
926 l2cap_do_send(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300927}
928
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300929static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300930{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300931 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300932 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300933 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300934 } else
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300935 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300936
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300937 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300938}
939
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300940static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300941{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300942 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300943}
944
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +0200945static void l2cap_send_conn_req(struct l2cap_chan *chan)
946{
947 struct l2cap_conn *conn = chan->conn;
948 struct l2cap_conn_req req;
949
950 req.scid = cpu_to_le16(chan->scid);
951 req.psm = chan->psm;
952
953 chan->ident = l2cap_get_ident(conn);
954
955 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
956
957 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
958}
959
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300960static void l2cap_chan_ready(struct l2cap_chan *chan)
961{
962 struct sock *sk = chan->sk;
963 struct sock *parent;
964
965 lock_sock(sk);
966
967 parent = bt_sk(sk)->parent;
968
969 BT_DBG("sk %p, parent %p", sk, parent);
970
Mat Martineau28270112012-05-17 21:14:09 -0700971 /* This clears all conf flags, including CONF_NOT_COMPLETE */
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300972 chan->conf_state = 0;
973 __clear_chan_timer(chan);
974
975 __l2cap_state_change(chan, BT_CONNECTED);
976 sk->sk_state_change(sk);
977
978 if (parent)
979 parent->sk_data_ready(parent, 0);
980
981 release_sock(sk);
982}
983
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300984static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200985{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300986 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200987
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300988 if (conn->hcon->type == LE_LINK) {
989 l2cap_chan_ready(chan);
990 return;
991 }
992
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200993 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100994 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
995 return;
996
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200997 if (l2cap_chan_check_security(chan) &&
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +0200998 __l2cap_no_conn_pending(chan))
999 l2cap_send_conn_req(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001000 } else {
1001 struct l2cap_info_req req;
1002 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
1003
1004 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
1005 conn->info_ident = l2cap_get_ident(conn);
1006
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08001007 schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001008
1009 l2cap_send_cmd(conn, conn->info_ident,
1010 L2CAP_INFO_REQ, sizeof(req), &req);
1011 }
1012}
1013
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -03001014static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
1015{
1016 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03001017 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -03001018 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
1019
1020 switch (mode) {
1021 case L2CAP_MODE_ERTM:
1022 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
1023 case L2CAP_MODE_STREAMING:
1024 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
1025 default:
1026 return 0x00;
1027 }
1028}
1029
Gustavo F. Padovan4519de92011-04-28 17:55:53 -03001030static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -03001031{
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001032 struct sock *sk = chan->sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -03001033 struct l2cap_disconn_req req;
1034
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001035 if (!conn)
1036 return;
1037
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001038 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001039 __clear_retrans_timer(chan);
1040 __clear_monitor_timer(chan);
1041 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001042 }
1043
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001044 req.dcid = cpu_to_le16(chan->dcid);
1045 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -03001046 l2cap_send_cmd(conn, l2cap_get_ident(conn),
1047 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001048
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001049 lock_sock(sk);
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001050 __l2cap_state_change(chan, BT_DISCONN);
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +02001051 __l2cap_chan_set_err(chan, err);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001052 release_sock(sk);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -03001053}
1054
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001056static void l2cap_conn_start(struct l2cap_conn *conn)
1057{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001058 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001059
1060 BT_DBG("conn %p", conn);
1061
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001062 mutex_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001063
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001064 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001065 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001066
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001067 l2cap_chan_lock(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001068
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001069 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001070 l2cap_chan_unlock(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001071 continue;
1072 }
1073
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001074 if (chan->state == BT_CONNECT) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001075 if (!l2cap_chan_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001076 !__l2cap_no_conn_pending(chan)) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001077 l2cap_chan_unlock(chan);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -03001078 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02001079 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -03001080
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001081 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1082 && test_bit(CONF_STATE2_DEVICE,
1083 &chan->conf_state)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001084 l2cap_chan_close(chan, ECONNRESET);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001085 l2cap_chan_unlock(chan);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -03001086 continue;
1087 }
1088
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +02001089 l2cap_send_conn_req(chan);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -03001090
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001091 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001092 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001093 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001094 rsp.scid = cpu_to_le16(chan->dcid);
1095 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001096
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001097 if (l2cap_chan_check_security(chan)) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001098 lock_sock(sk);
Gustavo Padovanc5daa682012-05-16 12:17:10 -03001099 if (test_bit(BT_SK_DEFER_SETUP,
1100 &bt_sk(sk)->flags)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001101 struct sock *parent = bt_sk(sk)->parent;
1102 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1103 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00001104 if (parent)
1105 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001106
1107 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001108 __l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001109 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1110 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1111 }
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001112 release_sock(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001113 } else {
1114 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1115 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
1116 }
1117
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001118 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1119 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001120
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001121 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001122 rsp.result != L2CAP_CR_SUCCESS) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001123 l2cap_chan_unlock(chan);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001124 continue;
1125 }
1126
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001127 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001128 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001129 l2cap_build_conf_req(chan, buf), buf);
1130 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001131 }
1132
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001133 l2cap_chan_unlock(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001134 }
1135
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001136 mutex_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001137}
1138
Ido Yarivc2287682012-04-20 15:46:07 -03001139/* Find socket with cid and source/destination bdaddr.
Ville Tervob62f3282011-02-10 22:38:50 -03001140 * Returns closest match, locked.
1141 */
Andrei Emeltchenkod9b88702012-03-12 12:13:08 +02001142static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
Ido Yarivc2287682012-04-20 15:46:07 -03001143 bdaddr_t *src,
1144 bdaddr_t *dst)
Ville Tervob62f3282011-02-10 22:38:50 -03001145{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001146 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -03001147
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001148 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -03001149
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001150 list_for_each_entry(c, &chan_list, global_l) {
1151 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001152
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001153 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -03001154 continue;
1155
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001156 if (c->scid == cid) {
Ido Yarivc2287682012-04-20 15:46:07 -03001157 int src_match, dst_match;
1158 int src_any, dst_any;
1159
Ville Tervob62f3282011-02-10 22:38:50 -03001160 /* Exact match. */
Ido Yarivc2287682012-04-20 15:46:07 -03001161 src_match = !bacmp(&bt_sk(sk)->src, src);
1162 dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1163 if (src_match && dst_match) {
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001164 read_unlock(&chan_list_lock);
1165 return c;
1166 }
Ville Tervob62f3282011-02-10 22:38:50 -03001167
1168 /* Closest match */
Ido Yarivc2287682012-04-20 15:46:07 -03001169 src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1170 dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1171 if ((src_match && dst_any) || (src_any && dst_match) ||
1172 (src_any && dst_any))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001173 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -03001174 }
1175 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -03001176
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001177 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -03001178
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001179 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -03001180}
1181
1182static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1183{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -03001184 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001185 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -03001186
1187 BT_DBG("");
1188
1189 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001190 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ido Yarivc2287682012-04-20 15:46:07 -03001191 conn->src, conn->dst);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001192 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -03001193 return;
1194
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001195 parent = pchan->sk;
1196
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001197 lock_sock(parent);
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -03001198
Ville Tervob62f3282011-02-10 22:38:50 -03001199 /* Check for backlog size */
1200 if (sk_acceptq_is_full(parent)) {
1201 BT_DBG("backlog full %d", parent->sk_ack_backlog);
1202 goto clean;
1203 }
1204
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03001205 chan = pchan->ops->new_connection(pchan->data);
1206 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -03001207 goto clean;
1208
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03001209 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001210
Ville Tervob62f3282011-02-10 22:38:50 -03001211 hci_conn_hold(conn->hcon);
1212
Ville Tervob62f3282011-02-10 22:38:50 -03001213 bacpy(&bt_sk(sk)->src, conn->src);
1214 bacpy(&bt_sk(sk)->dst, conn->dst);
1215
Gustavo F. Padovand1010242011-03-25 00:39:48 -03001216 bt_accept_enqueue(parent, sk);
1217
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001218 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001219
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001220 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -03001221
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001222 __l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -03001223 parent->sk_data_ready(parent, 0);
1224
Ville Tervob62f3282011-02-10 22:38:50 -03001225clean:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001226 release_sock(parent);
Ville Tervob62f3282011-02-10 22:38:50 -03001227}
1228
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001229static void l2cap_conn_ready(struct l2cap_conn *conn)
1230{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001231 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001232
1233 BT_DBG("conn %p", conn);
1234
Ville Tervob62f3282011-02-10 22:38:50 -03001235 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
1236 l2cap_le_conn_ready(conn);
1237
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03001238 if (conn->hcon->out && conn->hcon->type == LE_LINK)
1239 smp_conn_security(conn, conn->hcon->pending_sec_level);
1240
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001241 mutex_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001242
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001243 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001244
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001245 l2cap_chan_lock(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001246
Vinicius Costa Gomes63128452011-06-17 22:46:26 -03001247 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -03001248 if (smp_conn_security(conn, chan->sec_level))
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02001249 l2cap_chan_ready(chan);
Ville Tervoacd7d372011-02-10 22:38:49 -03001250
Vinicius Costa Gomes63128452011-06-17 22:46:26 -03001251 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001252 struct sock *sk = chan->sk;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001253 __clear_chan_timer(chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001254 lock_sock(sk);
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001255 __l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001256 sk->sk_state_change(sk);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001257 release_sock(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -03001258
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001259 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001260 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001261
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001262 l2cap_chan_unlock(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001263 }
1264
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001265 mutex_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001266}
1267
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001268/* Notify sockets that we cannot guaranty reliability anymore */
1269static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
1270{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001271 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001272
1273 BT_DBG("conn %p", conn);
1274
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001275 mutex_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001276
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001277 list_for_each_entry(chan, &conn->chan_l, list) {
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +03001278 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +02001279 __l2cap_chan_set_err(chan, err);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001280 }
1281
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001282 mutex_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001283}
1284
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -02001285static void l2cap_info_timeout(struct work_struct *work)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001286{
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -02001287 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02001288 info_timer.work);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001289
Marcel Holtmann984947d2009-02-06 23:35:19 +01001290 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01001291 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01001292
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001293 l2cap_conn_start(conn);
1294}
1295
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001296static void l2cap_conn_del(struct hci_conn *hcon, int err)
1297{
1298 struct l2cap_conn *conn = hcon->l2cap_data;
1299 struct l2cap_chan *chan, *l;
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001300
1301 if (!conn)
1302 return;
1303
1304 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
1305
1306 kfree_skb(conn->rx_skb);
1307
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001308 mutex_lock(&conn->chan_lock);
1309
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001310 /* Kill channels */
1311 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Mat Martineau61d6ef32012-04-27 16:50:50 -07001312 l2cap_chan_hold(chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001313 l2cap_chan_lock(chan);
1314
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001315 l2cap_chan_del(chan, err);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001316
1317 l2cap_chan_unlock(chan);
1318
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001319 chan->ops->close(chan->data);
Mat Martineau61d6ef32012-04-27 16:50:50 -07001320 l2cap_chan_put(chan);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001321 }
1322
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001323 mutex_unlock(&conn->chan_lock);
1324
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001325 hci_chan_del(conn->hchan);
1326
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001327 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
Ulisses Furquim127074b2012-01-30 18:26:29 -02001328 cancel_delayed_work_sync(&conn->info_timer);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001329
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001330 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
Ulisses Furquim127074b2012-01-30 18:26:29 -02001331 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001332 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001333 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001334
1335 hcon->l2cap_data = NULL;
1336 kfree(conn);
1337}
1338
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001339static void security_timeout(struct work_struct *work)
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001340{
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001341 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1342 security_timer.work);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001343
1344 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1345}
1346
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1348{
Marcel Holtmann01394182006-07-03 10:02:46 +02001349 struct l2cap_conn *conn = hcon->l2cap_data;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001350 struct hci_chan *hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
Marcel Holtmann01394182006-07-03 10:02:46 +02001352 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 return conn;
1354
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001355 hchan = hci_chan_create(hcon);
1356 if (!hchan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001359 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1360 if (!conn) {
1361 hci_chan_del(hchan);
1362 return NULL;
1363 }
1364
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 hcon->l2cap_data = conn;
1366 conn->hcon = hcon;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001367 conn->hchan = hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001369 BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
Marcel Holtmann01394182006-07-03 10:02:46 +02001370
Ville Tervoacd7d372011-02-10 22:38:49 -03001371 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1372 conn->mtu = hcon->hdev->le_mtu;
1373 else
1374 conn->mtu = hcon->hdev->acl_mtu;
1375
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 conn->src = &hcon->hdev->bdaddr;
1377 conn->dst = &hcon->dst;
1378
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001379 conn->feat_mask = 0;
1380
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 spin_lock_init(&conn->lock);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001382 mutex_init(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001383
1384 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001386 if (hcon->type == LE_LINK)
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001387 INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001388 else
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02001389 INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
Dave Young45054dc2009-10-18 20:28:30 +00001390
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001391 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01001392
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 return conn;
1394}
1395
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397
Ido Yarivc2287682012-04-20 15:46:07 -03001398/* Find socket with psm and source / destination bdaddr.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 * Returns closest match.
1400 */
Ido Yarivc2287682012-04-20 15:46:07 -03001401static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1402 bdaddr_t *src,
1403 bdaddr_t *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001405 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001407 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001408
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001409 list_for_each_entry(c, &chan_list, global_l) {
1410 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001411
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001412 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 continue;
1414
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001415 if (c->psm == psm) {
Ido Yarivc2287682012-04-20 15:46:07 -03001416 int src_match, dst_match;
1417 int src_any, dst_any;
1418
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 /* Exact match. */
Ido Yarivc2287682012-04-20 15:46:07 -03001420 src_match = !bacmp(&bt_sk(sk)->src, src);
1421 dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1422 if (src_match && dst_match) {
Johannes Berga7567b22011-06-01 08:29:54 +02001423 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001424 return c;
1425 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426
1427 /* Closest match */
Ido Yarivc2287682012-04-20 15:46:07 -03001428 src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1429 dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1430 if ((src_match && dst_any) || (src_any && dst_match) ||
1431 (src_any && dst_any))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001432 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 }
1434 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001436 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001437
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001438 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439}
1440
Andre Guedes8e9f9892012-04-24 21:02:55 -03001441int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
1442 bdaddr_t *dst, u8 dst_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001444 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 bdaddr_t *src = &bt_sk(sk)->src;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 struct l2cap_conn *conn;
1447 struct hci_conn *hcon;
1448 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001449 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001450 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451
Andre Guedes8e9f9892012-04-24 21:02:55 -03001452 BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst),
1453 dst_type, __le16_to_cpu(chan->psm));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001455 hdev = hci_get_route(dst, src);
1456 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 return -EHOSTUNREACH;
1458
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001459 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001461 l2cap_chan_lock(chan);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001462
1463 /* PSM must be odd and lsb of upper byte must be 0 */
1464 if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
1465 chan->chan_type != L2CAP_CHAN_RAW) {
1466 err = -EINVAL;
1467 goto done;
1468 }
1469
1470 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
1471 err = -EINVAL;
1472 goto done;
1473 }
1474
1475 switch (chan->mode) {
1476 case L2CAP_MODE_BASIC:
1477 break;
1478 case L2CAP_MODE_ERTM:
1479 case L2CAP_MODE_STREAMING:
1480 if (!disable_ertm)
1481 break;
1482 /* fall through */
1483 default:
1484 err = -ENOTSUPP;
1485 goto done;
1486 }
1487
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001488 lock_sock(sk);
1489
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001490 switch (sk->sk_state) {
1491 case BT_CONNECT:
1492 case BT_CONNECT2:
1493 case BT_CONFIG:
1494 /* Already connecting */
1495 err = 0;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001496 release_sock(sk);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001497 goto done;
1498
1499 case BT_CONNECTED:
1500 /* Already connected */
1501 err = -EISCONN;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001502 release_sock(sk);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001503 goto done;
1504
1505 case BT_OPEN:
1506 case BT_BOUND:
1507 /* Can connect */
1508 break;
1509
1510 default:
1511 err = -EBADFD;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001512 release_sock(sk);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001513 goto done;
1514 }
1515
1516 /* Set destination address and psm */
Gustavo F. Padovan9219b2a2012-01-02 20:08:04 -02001517 bacpy(&bt_sk(sk)->dst, dst);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001518
1519 release_sock(sk);
1520
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001521 chan->psm = psm;
1522 chan->dcid = cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001524 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001525
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001526 if (chan->dcid == L2CAP_CID_LE_DATA)
Andre Guedes8e9f9892012-04-24 21:02:55 -03001527 hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
Andre Guedesb12f62c2012-04-24 21:02:54 -03001528 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001529 else
Andre Guedes8e9f9892012-04-24 21:02:55 -03001530 hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
Andre Guedesb12f62c2012-04-24 21:02:54 -03001531 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001532
Ville Tervo30e76272011-02-22 16:10:53 -03001533 if (IS_ERR(hcon)) {
1534 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001536 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537
1538 conn = l2cap_conn_add(hcon, 0);
1539 if (!conn) {
1540 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001541 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 goto done;
1543 }
1544
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -03001545 if (hcon->type == LE_LINK) {
1546 err = 0;
1547
1548 if (!list_empty(&conn->chan_l)) {
1549 err = -EBUSY;
1550 hci_conn_put(hcon);
1551 }
1552
1553 if (err)
1554 goto done;
1555 }
1556
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 /* Update source addr of the socket */
1558 bacpy(src, conn->src);
1559
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001560 l2cap_chan_unlock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001561 l2cap_chan_add(conn, chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001562 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001563
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001564 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001565 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566
1567 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001568 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001569 __clear_chan_timer(chan);
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001570 if (l2cap_chan_check_security(chan))
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001571 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001572 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001573 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 }
1575
Ville Tervo30e76272011-02-22 16:10:53 -03001576 err = 0;
1577
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578done:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001579 l2cap_chan_unlock(chan);
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001580 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 hci_dev_put(hdev);
1582 return err;
1583}
1584
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001585int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001586{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001587 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001588 DECLARE_WAITQUEUE(wait, current);
1589 int err = 0;
1590 int timeo = HZ/5;
1591
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001592 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001593 set_current_state(TASK_INTERRUPTIBLE);
1594 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001595 if (!timeo)
1596 timeo = HZ/5;
1597
1598 if (signal_pending(current)) {
1599 err = sock_intr_errno(timeo);
1600 break;
1601 }
1602
1603 release_sock(sk);
1604 timeo = schedule_timeout(timeo);
1605 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001606 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001607
1608 err = sock_error(sk);
1609 if (err)
1610 break;
1611 }
1612 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001613 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001614 return err;
1615}
1616
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001617static void l2cap_monitor_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001618{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001619 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1620 monitor_timer.work);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001621
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001622 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001623
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001624 l2cap_chan_lock(chan);
1625
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001626 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001627 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001628 l2cap_chan_unlock(chan);
Andrei Emeltchenko8d7e1c72012-03-23 09:42:15 +02001629 l2cap_chan_put(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001630 return;
1631 }
1632
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001633 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001634 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001635
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001636 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001637 l2cap_chan_unlock(chan);
Andrei Emeltchenko8d7e1c72012-03-23 09:42:15 +02001638 l2cap_chan_put(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001639}
1640
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001641static void l2cap_retrans_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001642{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001643 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1644 retrans_timer.work);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001645
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001646 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001647
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001648 l2cap_chan_lock(chan);
1649
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001650 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001651 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001652
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001653 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001654
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001655 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001656
1657 l2cap_chan_unlock(chan);
Andrei Emeltchenko8d7e1c72012-03-23 09:42:15 +02001658 l2cap_chan_put(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001659}
1660
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001661static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001662{
1663 struct sk_buff *skb;
1664
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001665 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001666 chan->unacked_frames) {
Mat Martineau3ce35142012-04-25 16:36:14 -07001667 if (bt_cb(skb)->control.txseq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001668 break;
1669
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001670 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001671 kfree_skb(skb);
1672
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001673 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001674 }
1675
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001676 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001677 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001678}
1679
Mat Martineau37339372012-05-17 20:53:33 -07001680static int l2cap_streaming_send(struct l2cap_chan *chan,
1681 struct sk_buff_head *skbs)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001682{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001683 struct sk_buff *skb;
Mat Martineau37339372012-05-17 20:53:33 -07001684 struct l2cap_ctrl *control;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001685
Mat Martineau37339372012-05-17 20:53:33 -07001686 BT_DBG("chan %p, skbs %p", chan, skbs);
1687
1688 if (chan->state != BT_CONNECTED)
1689 return -ENOTCONN;
1690
1691 skb_queue_splice_tail_init(skbs, &chan->tx_q);
1692
1693 while (!skb_queue_empty(&chan->tx_q)) {
1694
1695 skb = skb_dequeue(&chan->tx_q);
1696
1697 bt_cb(skb)->control.retries = 1;
1698 control = &bt_cb(skb)->control;
1699
1700 control->reqseq = 0;
1701 control->txseq = chan->next_tx_seq;
1702
1703 __pack_control(chan, control, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001704
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001705 if (chan->fcs == L2CAP_FCS_CRC16) {
Mat Martineau37339372012-05-17 20:53:33 -07001706 u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
1707 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001708 }
1709
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001710 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001711
Mat Martineau37339372012-05-17 20:53:33 -07001712 BT_DBG("Sent txseq %d", (int)control->txseq);
1713
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001714 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Mat Martineau37339372012-05-17 20:53:33 -07001715 chan->frames_sent++;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001716 }
Mat Martineau37339372012-05-17 20:53:33 -07001717
1718 return 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001719}
1720
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001721static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001722{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001723 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001724 u16 fcs;
1725 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001726
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001727 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001728 if (!skb)
1729 return;
1730
Mat Martineau3ce35142012-04-25 16:36:14 -07001731 while (bt_cb(skb)->control.txseq != tx_seq) {
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001732 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001733 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001734
Szymon Jancd1726b62011-11-16 09:32:20 +01001735 skb = skb_queue_next(&chan->tx_q, skb);
1736 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001737
Mat Martineau3ce35142012-04-25 16:36:14 -07001738 if (bt_cb(skb)->control.retries == chan->remote_max_tx &&
1739 chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001740 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001741 return;
1742 }
1743
1744 tx_skb = skb_clone(skb, GFP_ATOMIC);
Mat Martineau3ce35142012-04-25 16:36:14 -07001745 bt_cb(skb)->control.retries++;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001746
1747 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001748 control &= __get_sar_mask(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001749
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001750 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001751 control |= __set_ctrl_final(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001752
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001753 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001754 control |= __set_txseq(chan, tx_seq);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001755
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001756 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001757
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001758 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001759 fcs = crc16(0, (u8 *)tx_skb->data,
1760 tx_skb->len - L2CAP_FCS_SIZE);
1761 put_unaligned_le16(fcs,
1762 tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001763 }
1764
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001765 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001766}
1767
Szymon Janc67c9e842011-07-28 16:24:33 +02001768static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001769{
1770 struct sk_buff *skb, *tx_skb;
Mat Martineau18a48e72012-05-17 20:53:34 -07001771 struct l2cap_ctrl *control;
1772 int sent = 0;
1773
1774 BT_DBG("chan %p", chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001775
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001776 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001777 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001778
Mat Martineau94122bb2012-05-02 09:42:02 -07001779 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
1780 return 0;
1781
Mat Martineau18a48e72012-05-17 20:53:34 -07001782 while (chan->tx_send_head &&
1783 chan->unacked_frames < chan->remote_tx_win &&
1784 chan->tx_state == L2CAP_TX_STATE_XMIT) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001785
Mat Martineau18a48e72012-05-17 20:53:34 -07001786 skb = chan->tx_send_head;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001787
Mat Martineau18a48e72012-05-17 20:53:34 -07001788 bt_cb(skb)->control.retries = 1;
1789 control = &bt_cb(skb)->control;
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001790
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001791 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Mat Martineau18a48e72012-05-17 20:53:34 -07001792 control->final = 1;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001793
Mat Martineau18a48e72012-05-17 20:53:34 -07001794 control->reqseq = chan->buffer_seq;
1795 chan->last_acked_seq = chan->buffer_seq;
1796 control->txseq = chan->next_tx_seq;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001797
Mat Martineau18a48e72012-05-17 20:53:34 -07001798 __pack_control(chan, control, skb);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001799
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001800 if (chan->fcs == L2CAP_FCS_CRC16) {
Mat Martineau18a48e72012-05-17 20:53:34 -07001801 u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
1802 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001803 }
1804
Mat Martineau18a48e72012-05-17 20:53:34 -07001805 /* Clone after data has been modified. Data is assumed to be
1806 read-only (for locking purposes) on cloned sk_buffs.
1807 */
1808 tx_skb = skb_clone(skb, GFP_KERNEL);
1809
1810 if (!tx_skb)
1811 break;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001812
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001813 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001814
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001815 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Mat Martineau18a48e72012-05-17 20:53:34 -07001816 chan->unacked_frames++;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001817 chan->frames_sent++;
Mat Martineau18a48e72012-05-17 20:53:34 -07001818 sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001819
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001820 if (skb_queue_is_last(&chan->tx_q, skb))
1821 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001822 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001823 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Mat Martineau18a48e72012-05-17 20:53:34 -07001824
1825 l2cap_do_send(chan, tx_skb);
1826 BT_DBG("Sent txseq %d", (int)control->txseq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001827 }
1828
Mat Martineau18a48e72012-05-17 20:53:34 -07001829 BT_DBG("Sent %d, %d unacked, %d in ERTM queue", sent,
1830 (int) chan->unacked_frames, skb_queue_len(&chan->tx_q));
1831
1832 return sent;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001833}
1834
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001835static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001836{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001837 int ret;
1838
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001839 if (!skb_queue_empty(&chan->tx_q))
1840 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001841
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001842 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001843 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001844 return ret;
1845}
1846
Szymon Jancb17e73b2012-01-11 10:59:47 +01001847static void __l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001848{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001849 u32 control = 0;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001850
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001851 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001852
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001853 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001854 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001855 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001856 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001857 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001858
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001859 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001860 return;
1861
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001862 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001863}
1864
Szymon Jancb17e73b2012-01-11 10:59:47 +01001865static void l2cap_send_ack(struct l2cap_chan *chan)
1866{
1867 __clear_ack_timer(chan);
1868 __l2cap_send_ack(chan);
1869}
1870
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001871static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001872{
1873 struct srej_list *tail;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001874 u32 control;
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001875
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001876 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001877 control |= __set_ctrl_final(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001878
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001879 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001880 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001881}
1882
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001883static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
1884 struct msghdr *msg, int len,
1885 int count, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886{
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001887 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001888 struct sk_buff **frag;
Gustavo Padovan90338942012-04-06 20:15:47 -03001889 int sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001891 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001892 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893
1894 sent += count;
1895 len -= count;
1896
1897 /* Continuation fragments (no L2CAP header) */
1898 frag = &skb_shinfo(skb)->frag_list;
1899 while (len) {
Gustavo Padovanfbe00702012-05-15 13:22:55 -03001900 struct sk_buff *tmp;
1901
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 count = min_t(unsigned int, conn->mtu, len);
1903
Gustavo Padovanfbe00702012-05-15 13:22:55 -03001904 tmp = chan->ops->alloc_skb(chan, count,
1905 msg->msg_flags & MSG_DONTWAIT);
1906 if (IS_ERR(tmp))
1907 return PTR_ERR(tmp);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001908
Gustavo Padovanfbe00702012-05-15 13:22:55 -03001909 *frag = tmp;
1910
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001911 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1912 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001914 (*frag)->priority = skb->priority;
1915
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 sent += count;
1917 len -= count;
1918
Gustavo Padovan2d0ed3d2012-05-11 13:16:12 -03001919 skb->len += (*frag)->len;
1920 skb->data_len += (*frag)->len;
1921
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922 frag = &(*frag)->next;
1923 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924
1925 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001926}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001928static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
1929 struct msghdr *msg, size_t len,
1930 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001931{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001932 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001933 struct sk_buff *skb;
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001934 int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001935 struct l2cap_hdr *lh;
1936
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001937 BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001938
1939 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001940
1941 skb = chan->ops->alloc_skb(chan, count + hlen,
Gustavo Padovan90338942012-04-06 20:15:47 -03001942 msg->msg_flags & MSG_DONTWAIT);
1943 if (IS_ERR(skb))
1944 return skb;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001945
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001946 skb->priority = priority;
1947
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001948 /* Create L2CAP header */
1949 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001950 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenkodaf6a78c2012-05-03 10:55:52 +03001951 lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
1952 put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001953
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001954 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001955 if (unlikely(err < 0)) {
1956 kfree_skb(skb);
1957 return ERR_PTR(err);
1958 }
1959 return skb;
1960}
1961
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001962static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
1963 struct msghdr *msg, size_t len,
1964 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001965{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001966 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001967 struct sk_buff *skb;
Gustavo Padovanf2ba7fa2012-05-03 04:54:21 -03001968 int err, count;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001969 struct l2cap_hdr *lh;
1970
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001971 BT_DBG("chan %p len %d", chan, (int)len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001972
Gustavo Padovanf2ba7fa2012-05-03 04:54:21 -03001973 count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001974
Gustavo Padovanf2ba7fa2012-05-03 04:54:21 -03001975 skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE,
Gustavo Padovan90338942012-04-06 20:15:47 -03001976 msg->msg_flags & MSG_DONTWAIT);
1977 if (IS_ERR(skb))
1978 return skb;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001979
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001980 skb->priority = priority;
1981
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001982 /* Create L2CAP header */
1983 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001984 lh->cid = cpu_to_le16(chan->dcid);
Gustavo Padovan6ff9b5e2012-05-02 11:56:17 -03001985 lh->len = cpu_to_le16(len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001986
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001987 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001988 if (unlikely(err < 0)) {
1989 kfree_skb(skb);
1990 return ERR_PTR(err);
1991 }
1992 return skb;
1993}
1994
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001995static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1996 struct msghdr *msg, size_t len,
Mat Martineau94122bb2012-05-02 09:42:02 -07001997 u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001998{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001999 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002000 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03002001 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002002 struct l2cap_hdr *lh;
2003
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02002004 BT_DBG("chan %p len %d", chan, (int)len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002005
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03002006 if (!conn)
2007 return ERR_PTR(-ENOTCONN);
2008
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03002009 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2010 hlen = L2CAP_EXT_HDR_SIZE;
2011 else
2012 hlen = L2CAP_ENH_HDR_SIZE;
2013
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002014 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03002015 hlen += L2CAP_SDULEN_SIZE;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002016
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002017 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03002018 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002019
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002020 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02002021
2022 skb = chan->ops->alloc_skb(chan, count + hlen,
Gustavo Padovan90338942012-04-06 20:15:47 -03002023 msg->msg_flags & MSG_DONTWAIT);
2024 if (IS_ERR(skb))
2025 return skb;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002026
2027 /* Create L2CAP header */
2028 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002029 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002030 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03002031
Mat Martineau18a48e72012-05-17 20:53:34 -07002032 /* Control header is populated later */
2033 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2034 put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
2035 else
2036 put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03002037
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002038 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03002039 put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002040
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02002041 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002042 if (unlikely(err < 0)) {
2043 kfree_skb(skb);
2044 return ERR_PTR(err);
2045 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03002046
Mat Martineau18a48e72012-05-17 20:53:34 -07002047 bt_cb(skb)->control.fcs = chan->fcs;
Mat Martineau3ce35142012-04-25 16:36:14 -07002048 bt_cb(skb)->control.retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002049 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050}
2051
Mat Martineau94122bb2012-05-02 09:42:02 -07002052static int l2cap_segment_sdu(struct l2cap_chan *chan,
2053 struct sk_buff_head *seg_queue,
2054 struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002055{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002056 struct sk_buff *skb;
Mat Martineau94122bb2012-05-02 09:42:02 -07002057 u16 sdu_len;
2058 size_t pdu_len;
2059 int err = 0;
2060 u8 sar;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002061
Mat Martineau94122bb2012-05-02 09:42:02 -07002062 BT_DBG("chan %p, msg %p, len %d", chan, msg, (int)len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002063
Mat Martineau94122bb2012-05-02 09:42:02 -07002064 /* It is critical that ERTM PDUs fit in a single HCI fragment,
2065 * so fragmented skbs are not used. The HCI layer's handling
2066 * of fragmented skbs is not compatible with ERTM's queueing.
2067 */
2068
2069 /* PDU size is derived from the HCI MTU */
2070 pdu_len = chan->conn->mtu;
2071
2072 pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
2073
2074 /* Adjust for largest possible L2CAP overhead. */
2075 pdu_len -= L2CAP_EXT_HDR_SIZE + L2CAP_FCS_SIZE;
2076
2077 /* Remote device may have requested smaller PDUs */
2078 pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
2079
2080 if (len <= pdu_len) {
2081 sar = L2CAP_SAR_UNSEGMENTED;
2082 sdu_len = 0;
2083 pdu_len = len;
2084 } else {
2085 sar = L2CAP_SAR_START;
2086 sdu_len = len;
2087 pdu_len -= L2CAP_SDULEN_SIZE;
2088 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002089
2090 while (len > 0) {
Mat Martineau94122bb2012-05-02 09:42:02 -07002091 skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002092
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002093 if (IS_ERR(skb)) {
Mat Martineau94122bb2012-05-02 09:42:02 -07002094 __skb_queue_purge(seg_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002095 return PTR_ERR(skb);
2096 }
2097
Mat Martineau94122bb2012-05-02 09:42:02 -07002098 bt_cb(skb)->control.sar = sar;
2099 __skb_queue_tail(seg_queue, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002100
Mat Martineau94122bb2012-05-02 09:42:02 -07002101 len -= pdu_len;
2102 if (sdu_len) {
2103 sdu_len = 0;
2104 pdu_len += L2CAP_SDULEN_SIZE;
2105 }
2106
2107 if (len <= pdu_len) {
2108 sar = L2CAP_SAR_END;
2109 pdu_len = len;
2110 } else {
2111 sar = L2CAP_SAR_CONTINUE;
2112 }
2113 }
2114
2115 return err;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002116}
2117
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02002118int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
2119 u32 priority)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002120{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002121 struct sk_buff *skb;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002122 int err;
Mat Martineau94122bb2012-05-02 09:42:02 -07002123 struct sk_buff_head seg_queue;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002124
2125 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03002126 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02002127 skb = l2cap_create_connless_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002128 if (IS_ERR(skb))
2129 return PTR_ERR(skb);
2130
2131 l2cap_do_send(chan, skb);
2132 return len;
2133 }
2134
2135 switch (chan->mode) {
2136 case L2CAP_MODE_BASIC:
2137 /* Check outgoing MTU */
2138 if (len > chan->omtu)
2139 return -EMSGSIZE;
2140
2141 /* Create a basic PDU */
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02002142 skb = l2cap_create_basic_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002143 if (IS_ERR(skb))
2144 return PTR_ERR(skb);
2145
2146 l2cap_do_send(chan, skb);
2147 err = len;
2148 break;
2149
2150 case L2CAP_MODE_ERTM:
2151 case L2CAP_MODE_STREAMING:
Mat Martineau94122bb2012-05-02 09:42:02 -07002152 /* Check outgoing MTU */
2153 if (len > chan->omtu) {
2154 err = -EMSGSIZE;
2155 break;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002156 }
2157
Mat Martineau94122bb2012-05-02 09:42:02 -07002158 __skb_queue_head_init(&seg_queue);
2159
2160 /* Do segmentation before calling in to the state machine,
2161 * since it's possible to block while waiting for memory
2162 * allocation.
2163 */
2164 err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
2165
2166 /* The channel could have been closed while segmenting,
2167 * check that it is still connected.
2168 */
2169 if (chan->state != BT_CONNECTED) {
2170 __skb_queue_purge(&seg_queue);
2171 err = -ENOTCONN;
2172 }
2173
2174 if (err)
2175 break;
2176
Mat Martineau37339372012-05-17 20:53:33 -07002177 if (chan->mode == L2CAP_MODE_ERTM)
Mat Martineau608bcc62012-05-17 20:53:32 -07002178 err = l2cap_tx(chan, 0, &seg_queue,
2179 L2CAP_EV_DATA_REQUEST);
Mat Martineau37339372012-05-17 20:53:33 -07002180 else
2181 err = l2cap_streaming_send(chan, &seg_queue);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002182
Mat Martineau608bcc62012-05-17 20:53:32 -07002183 if (!err)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002184 err = len;
2185
Mat Martineau94122bb2012-05-02 09:42:02 -07002186 /* If the skbs were not queued for sending, they'll still be in
2187 * seg_queue and need to be purged.
2188 */
2189 __skb_queue_purge(&seg_queue);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002190 break;
2191
2192 default:
2193 BT_DBG("bad state %1.1x", chan->mode);
2194 err = -EBADFD;
2195 }
2196
2197 return err;
2198}
2199
Mat Martineau608bcc62012-05-17 20:53:32 -07002200static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq)
2201{
2202 struct sk_buff *acked_skb;
2203 u16 ackseq;
2204
2205 BT_DBG("chan %p, reqseq %d", chan, reqseq);
2206
2207 if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq)
2208 return;
2209
2210 BT_DBG("expected_ack_seq %d, unacked_frames %d",
2211 chan->expected_ack_seq, chan->unacked_frames);
2212
2213 for (ackseq = chan->expected_ack_seq; ackseq != reqseq;
2214 ackseq = __next_seq(chan, ackseq)) {
2215
2216 acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq);
2217 if (acked_skb) {
2218 skb_unlink(acked_skb, &chan->tx_q);
2219 kfree_skb(acked_skb);
2220 chan->unacked_frames--;
2221 }
2222 }
2223
2224 chan->expected_ack_seq = reqseq;
2225
2226 if (chan->unacked_frames == 0)
2227 __clear_retrans_timer(chan);
2228
2229 BT_DBG("unacked_frames %d", (int) chan->unacked_frames);
2230}
2231
2232static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan)
2233{
2234 BT_DBG("chan %p", chan);
2235
2236 chan->expected_tx_seq = chan->buffer_seq;
2237 l2cap_seq_list_clear(&chan->srej_list);
2238 skb_queue_purge(&chan->srej_q);
2239 chan->rx_state = L2CAP_RX_STATE_RECV;
2240}
2241
2242static int l2cap_tx_state_xmit(struct l2cap_chan *chan,
2243 struct l2cap_ctrl *control,
2244 struct sk_buff_head *skbs, u8 event)
2245{
2246 int err = 0;
2247
2248 BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2249 event);
2250
2251 switch (event) {
2252 case L2CAP_EV_DATA_REQUEST:
2253 if (chan->tx_send_head == NULL)
2254 chan->tx_send_head = skb_peek(skbs);
2255
2256 skb_queue_splice_tail_init(skbs, &chan->tx_q);
2257 l2cap_ertm_send(chan);
2258 break;
2259 case L2CAP_EV_LOCAL_BUSY_DETECTED:
2260 BT_DBG("Enter LOCAL_BUSY");
2261 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2262
2263 if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2264 /* The SREJ_SENT state must be aborted if we are to
2265 * enter the LOCAL_BUSY state.
2266 */
2267 l2cap_abort_rx_srej_sent(chan);
2268 }
2269
2270 l2cap_send_ack(chan);
2271
2272 break;
2273 case L2CAP_EV_LOCAL_BUSY_CLEAR:
2274 BT_DBG("Exit LOCAL_BUSY");
2275 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2276
2277 if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2278 struct l2cap_ctrl local_control;
2279
2280 memset(&local_control, 0, sizeof(local_control));
2281 local_control.sframe = 1;
2282 local_control.super = L2CAP_SUPER_RR;
2283 local_control.poll = 1;
2284 local_control.reqseq = chan->buffer_seq;
Mat Martineaua67d7f62012-05-17 20:53:35 -07002285 l2cap_send_sframe(chan, &local_control);
Mat Martineau608bcc62012-05-17 20:53:32 -07002286
2287 chan->retry_count = 1;
2288 __set_monitor_timer(chan);
2289 chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2290 }
2291 break;
2292 case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2293 l2cap_process_reqseq(chan, control->reqseq);
2294 break;
2295 case L2CAP_EV_EXPLICIT_POLL:
2296 l2cap_send_rr_or_rnr(chan, 1);
2297 chan->retry_count = 1;
2298 __set_monitor_timer(chan);
2299 __clear_ack_timer(chan);
2300 chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2301 break;
2302 case L2CAP_EV_RETRANS_TO:
2303 l2cap_send_rr_or_rnr(chan, 1);
2304 chan->retry_count = 1;
2305 __set_monitor_timer(chan);
2306 chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2307 break;
2308 case L2CAP_EV_RECV_FBIT:
2309 /* Nothing to process */
2310 break;
2311 default:
2312 break;
2313 }
2314
2315 return err;
2316}
2317
2318static int l2cap_tx_state_wait_f(struct l2cap_chan *chan,
2319 struct l2cap_ctrl *control,
2320 struct sk_buff_head *skbs, u8 event)
2321{
2322 int err = 0;
2323
2324 BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2325 event);
2326
2327 switch (event) {
2328 case L2CAP_EV_DATA_REQUEST:
2329 if (chan->tx_send_head == NULL)
2330 chan->tx_send_head = skb_peek(skbs);
2331 /* Queue data, but don't send. */
2332 skb_queue_splice_tail_init(skbs, &chan->tx_q);
2333 break;
2334 case L2CAP_EV_LOCAL_BUSY_DETECTED:
2335 BT_DBG("Enter LOCAL_BUSY");
2336 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2337
2338 if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2339 /* The SREJ_SENT state must be aborted if we are to
2340 * enter the LOCAL_BUSY state.
2341 */
2342 l2cap_abort_rx_srej_sent(chan);
2343 }
2344
2345 l2cap_send_ack(chan);
2346
2347 break;
2348 case L2CAP_EV_LOCAL_BUSY_CLEAR:
2349 BT_DBG("Exit LOCAL_BUSY");
2350 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2351
2352 if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2353 struct l2cap_ctrl local_control;
2354 memset(&local_control, 0, sizeof(local_control));
2355 local_control.sframe = 1;
2356 local_control.super = L2CAP_SUPER_RR;
2357 local_control.poll = 1;
2358 local_control.reqseq = chan->buffer_seq;
Mat Martineaua67d7f62012-05-17 20:53:35 -07002359 l2cap_send_sframe(chan, &local_control);
Mat Martineau608bcc62012-05-17 20:53:32 -07002360
2361 chan->retry_count = 1;
2362 __set_monitor_timer(chan);
2363 chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2364 }
2365 break;
2366 case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2367 l2cap_process_reqseq(chan, control->reqseq);
2368
2369 /* Fall through */
2370
2371 case L2CAP_EV_RECV_FBIT:
2372 if (control && control->final) {
2373 __clear_monitor_timer(chan);
2374 if (chan->unacked_frames > 0)
2375 __set_retrans_timer(chan);
2376 chan->retry_count = 0;
2377 chan->tx_state = L2CAP_TX_STATE_XMIT;
2378 BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state);
2379 }
2380 break;
2381 case L2CAP_EV_EXPLICIT_POLL:
2382 /* Ignore */
2383 break;
2384 case L2CAP_EV_MONITOR_TO:
2385 if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) {
2386 l2cap_send_rr_or_rnr(chan, 1);
2387 __set_monitor_timer(chan);
2388 chan->retry_count++;
2389 } else {
2390 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
2391 }
2392 break;
2393 default:
2394 break;
2395 }
2396
2397 return err;
2398}
2399
2400static int l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
2401 struct sk_buff_head *skbs, u8 event)
2402{
2403 int err = 0;
2404
2405 BT_DBG("chan %p, control %p, skbs %p, event %d, state %d",
2406 chan, control, skbs, event, chan->tx_state);
2407
2408 switch (chan->tx_state) {
2409 case L2CAP_TX_STATE_XMIT:
2410 err = l2cap_tx_state_xmit(chan, control, skbs, event);
2411 break;
2412 case L2CAP_TX_STATE_WAIT_F:
2413 err = l2cap_tx_state_wait_f(chan, control, skbs, event);
2414 break;
2415 default:
2416 /* Ignore event */
2417 break;
2418 }
2419
2420 return err;
2421}
2422
Mat Martineau4b51dae92012-05-17 20:53:37 -07002423static void l2cap_pass_to_tx(struct l2cap_chan *chan,
2424 struct l2cap_ctrl *control)
2425{
2426 BT_DBG("chan %p, control %p", chan, control);
2427 l2cap_tx(chan, control, 0, L2CAP_EV_RECV_REQSEQ_AND_FBIT);
2428}
2429
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430/* Copy frame to all raw sockets on that connection */
2431static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
2432{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002434 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435
2436 BT_DBG("conn %p", conn);
2437
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002438 mutex_lock(&conn->chan_lock);
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02002439
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002440 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002441 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03002442 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 continue;
2444
2445 /* Don't send frame to the socket it came from */
2446 if (skb->sk == sk)
2447 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002448 nskb = skb_clone(skb, GFP_ATOMIC);
2449 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450 continue;
2451
Gustavo F. Padovan23070492011-05-16 17:57:22 -03002452 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 kfree_skb(nskb);
2454 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02002455
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002456 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457}
2458
2459/* ---- L2CAP signalling commands ---- */
2460static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
2461 u8 code, u8 ident, u16 dlen, void *data)
2462{
2463 struct sk_buff *skb, **frag;
2464 struct l2cap_cmd_hdr *cmd;
2465 struct l2cap_hdr *lh;
2466 int len, count;
2467
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002468 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
2469 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470
2471 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
2472 count = min_t(unsigned int, conn->mtu, len);
2473
2474 skb = bt_skb_alloc(count, GFP_ATOMIC);
2475 if (!skb)
2476 return NULL;
2477
2478 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002479 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002480
2481 if (conn->hcon->type == LE_LINK)
2482 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
2483 else
2484 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485
2486 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
2487 cmd->code = code;
2488 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002489 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490
2491 if (dlen) {
2492 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
2493 memcpy(skb_put(skb, count), data, count);
2494 data += count;
2495 }
2496
2497 len -= skb->len;
2498
2499 /* Continuation fragments (no L2CAP header) */
2500 frag = &skb_shinfo(skb)->frag_list;
2501 while (len) {
2502 count = min_t(unsigned int, conn->mtu, len);
2503
2504 *frag = bt_skb_alloc(count, GFP_ATOMIC);
2505 if (!*frag)
2506 goto fail;
2507
2508 memcpy(skb_put(*frag, count), data, count);
2509
2510 len -= count;
2511 data += count;
2512
2513 frag = &(*frag)->next;
2514 }
2515
2516 return skb;
2517
2518fail:
2519 kfree_skb(skb);
2520 return NULL;
2521}
2522
2523static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
2524{
2525 struct l2cap_conf_opt *opt = *ptr;
2526 int len;
2527
2528 len = L2CAP_CONF_OPT_SIZE + opt->len;
2529 *ptr += len;
2530
2531 *type = opt->type;
2532 *olen = opt->len;
2533
2534 switch (opt->len) {
2535 case 1:
2536 *val = *((u8 *) opt->val);
2537 break;
2538
2539 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04002540 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541 break;
2542
2543 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04002544 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545 break;
2546
2547 default:
2548 *val = (unsigned long) opt->val;
2549 break;
2550 }
2551
2552 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
2553 return len;
2554}
2555
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
2557{
2558 struct l2cap_conf_opt *opt = *ptr;
2559
2560 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
2561
2562 opt->type = type;
2563 opt->len = len;
2564
2565 switch (len) {
2566 case 1:
2567 *((u8 *) opt->val) = val;
2568 break;
2569
2570 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02002571 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572 break;
2573
2574 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02002575 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576 break;
2577
2578 default:
2579 memcpy(opt->val, (void *) val, len);
2580 break;
2581 }
2582
2583 *ptr += L2CAP_CONF_OPT_SIZE + len;
2584}
2585
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002586static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
2587{
2588 struct l2cap_conf_efs efs;
2589
Szymon Janc1ec918c2011-11-16 09:32:21 +01002590 switch (chan->mode) {
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002591 case L2CAP_MODE_ERTM:
2592 efs.id = chan->local_id;
2593 efs.stype = chan->local_stype;
2594 efs.msdu = cpu_to_le16(chan->local_msdu);
2595 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
2596 efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
2597 efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
2598 break;
2599
2600 case L2CAP_MODE_STREAMING:
2601 efs.id = 1;
2602 efs.stype = L2CAP_SERV_BESTEFFORT;
2603 efs.msdu = cpu_to_le16(chan->local_msdu);
2604 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
2605 efs.acc_lat = 0;
2606 efs.flush_to = 0;
2607 break;
2608
2609 default:
2610 return;
2611 }
2612
2613 l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
2614 (unsigned long) &efs);
2615}
2616
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002617static void l2cap_ack_timeout(struct work_struct *work)
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002618{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002619 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2620 ack_timer.work);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002621
Gustavo F. Padovan2fb9b3d2011-12-22 16:56:05 -02002622 BT_DBG("chan %p", chan);
2623
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02002624 l2cap_chan_lock(chan);
2625
Szymon Jancb17e73b2012-01-11 10:59:47 +01002626 __l2cap_send_ack(chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02002627
2628 l2cap_chan_unlock(chan);
Szymon Janc09bfb2e2012-01-11 10:59:49 +01002629
2630 l2cap_chan_put(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002631}
2632
Mat Martineau3c588192012-04-11 10:48:42 -07002633static inline int l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002634{
Mat Martineau3c588192012-04-11 10:48:42 -07002635 int err;
2636
Mat Martineau105bdf92012-04-27 16:50:48 -07002637 chan->next_tx_seq = 0;
2638 chan->expected_tx_seq = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002639 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002640 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002641 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002642 chan->num_acked = 0;
2643 chan->frames_sent = 0;
Mat Martineau105bdf92012-04-27 16:50:48 -07002644 chan->last_acked_seq = 0;
2645 chan->sdu = NULL;
2646 chan->sdu_last_frag = NULL;
2647 chan->sdu_len = 0;
2648
Mat Martineaud34c34f2012-05-14 14:49:27 -07002649 skb_queue_head_init(&chan->tx_q);
2650
Mat Martineau105bdf92012-04-27 16:50:48 -07002651 if (chan->mode != L2CAP_MODE_ERTM)
2652 return 0;
2653
2654 chan->rx_state = L2CAP_RX_STATE_RECV;
2655 chan->tx_state = L2CAP_TX_STATE_XMIT;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002656
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002657 INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2658 INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2659 INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002660
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002661 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002662
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03002663 INIT_LIST_HEAD(&chan->srej_l);
Mat Martineau3c588192012-04-11 10:48:42 -07002664 err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
2665 if (err < 0)
2666 return err;
2667
Mat Martineau9dc9aff2012-05-17 16:20:14 -07002668 err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
2669 if (err < 0)
2670 l2cap_seq_list_free(&chan->srej_list);
2671
2672 return err;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002673}
2674
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002675static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2676{
2677 switch (mode) {
2678 case L2CAP_MODE_STREAMING:
2679 case L2CAP_MODE_ERTM:
2680 if (l2cap_mode_supported(mode, remote_feat_mask))
2681 return mode;
2682 /* fall through */
2683 default:
2684 return L2CAP_MODE_BASIC;
2685 }
2686}
2687
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002688static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
2689{
2690 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
2691}
2692
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002693static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2694{
2695 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2696}
2697
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002698static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
2699{
2700 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002701 __l2cap_ews_supported(chan)) {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002702 /* use extended control field */
2703 set_bit(FLAG_EXT_CTRL, &chan->flags);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002704 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2705 } else {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002706 chan->tx_win = min_t(u16, chan->tx_win,
2707 L2CAP_DEFAULT_TX_WINDOW);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002708 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2709 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002710}
2711
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002712static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002715 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716 void *ptr = req->data;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002717 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002719 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002721 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002722 goto done;
2723
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002724 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002725 case L2CAP_MODE_STREAMING:
2726 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002727 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002728 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002729
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002730 if (__l2cap_efs_supported(chan))
2731 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2732
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002733 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002734 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002735 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002736 break;
2737 }
2738
2739done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002740 if (chan->imtu != L2CAP_DEFAULT_MTU)
2741 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002742
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002743 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002744 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002745 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2746 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002747 break;
2748
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002749 rfc.mode = L2CAP_MODE_BASIC;
2750 rfc.txwin_size = 0;
2751 rfc.max_transmit = 0;
2752 rfc.retrans_timeout = 0;
2753 rfc.monitor_timeout = 0;
2754 rfc.max_pdu_size = 0;
2755
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002756 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2757 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002758 break;
2759
2760 case L2CAP_MODE_ERTM:
2761 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002762 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002763 rfc.retrans_timeout = 0;
2764 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002765
2766 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2767 L2CAP_EXT_HDR_SIZE -
2768 L2CAP_SDULEN_SIZE -
2769 L2CAP_FCS_SIZE);
2770 rfc.max_pdu_size = cpu_to_le16(size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002771
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002772 l2cap_txwin_setup(chan);
2773
2774 rfc.txwin_size = min_t(u16, chan->tx_win,
2775 L2CAP_DEFAULT_TX_WINDOW);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002776
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002777 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2778 (unsigned long) &rfc);
2779
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002780 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2781 l2cap_add_opt_efs(&ptr, chan);
2782
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002783 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002784 break;
2785
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002786 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002787 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002788 chan->fcs = L2CAP_FCS_NONE;
2789 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002790 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002791
2792 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2793 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2794 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002795 break;
2796
2797 case L2CAP_MODE_STREAMING:
2798 rfc.mode = L2CAP_MODE_STREAMING;
2799 rfc.txwin_size = 0;
2800 rfc.max_transmit = 0;
2801 rfc.retrans_timeout = 0;
2802 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002803
2804 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2805 L2CAP_EXT_HDR_SIZE -
2806 L2CAP_SDULEN_SIZE -
2807 L2CAP_FCS_SIZE);
2808 rfc.max_pdu_size = cpu_to_le16(size);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002809
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002810 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2811 (unsigned long) &rfc);
2812
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002813 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2814 l2cap_add_opt_efs(&ptr, chan);
2815
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002816 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002817 break;
2818
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002819 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002820 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002821 chan->fcs = L2CAP_FCS_NONE;
2822 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002823 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002824 break;
2825 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002827 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002828 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829
2830 return ptr - data;
2831}
2832
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002833static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002835 struct l2cap_conf_rsp *rsp = data;
2836 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002837 void *req = chan->conf_req;
2838 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002839 int type, hint, olen;
2840 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002841 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002842 struct l2cap_conf_efs efs;
2843 u8 remote_efs = 0;
Marcel Holtmann861d6882007-10-20 13:37:06 +02002844 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002845 u16 result = L2CAP_CONF_SUCCESS;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002846 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002848 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002849
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002850 while (len >= L2CAP_CONF_OPT_SIZE) {
2851 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002853 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002854 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002855
2856 switch (type) {
2857 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002858 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002859 break;
2860
2861 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002862 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002863 break;
2864
2865 case L2CAP_CONF_QOS:
2866 break;
2867
Marcel Holtmann6464f352007-10-20 13:39:51 +02002868 case L2CAP_CONF_RFC:
2869 if (olen == sizeof(rfc))
2870 memcpy(&rfc, (void *) val, olen);
2871 break;
2872
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002873 case L2CAP_CONF_FCS:
2874 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002875 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002876 break;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002877
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002878 case L2CAP_CONF_EFS:
2879 remote_efs = 1;
2880 if (olen == sizeof(efs))
2881 memcpy(&efs, (void *) val, olen);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002882 break;
2883
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002884 case L2CAP_CONF_EWS:
2885 if (!enable_hs)
2886 return -ECONNREFUSED;
2887
2888 set_bit(FLAG_EXT_CTRL, &chan->flags);
2889 set_bit(CONF_EWS_RECV, &chan->conf_state);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002890 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002891 chan->remote_tx_win = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002892 break;
2893
2894 default:
2895 if (hint)
2896 break;
2897
2898 result = L2CAP_CONF_UNKNOWN;
2899 *((u8 *) ptr++) = type;
2900 break;
2901 }
2902 }
2903
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002904 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002905 goto done;
2906
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002907 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002908 case L2CAP_MODE_STREAMING:
2909 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002910 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002911 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002912 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002913 break;
2914 }
2915
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002916 if (remote_efs) {
2917 if (__l2cap_efs_supported(chan))
2918 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2919 else
2920 return -ECONNREFUSED;
2921 }
2922
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002923 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002924 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002925
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002926 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002927 }
2928
2929done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002930 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002931 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002932 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002933
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002934 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002935 return -ECONNREFUSED;
2936
2937 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2938 sizeof(rfc), (unsigned long) &rfc);
2939 }
2940
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002941 if (result == L2CAP_CONF_SUCCESS) {
2942 /* Configure output options and let the other side know
2943 * which ones we don't like. */
2944
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002945 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2946 result = L2CAP_CONF_UNACCEPT;
2947 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002948 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002949 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002950 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002951 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002952
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002953 if (remote_efs) {
2954 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2955 efs.stype != L2CAP_SERV_NOTRAFIC &&
2956 efs.stype != chan->local_stype) {
2957
2958 result = L2CAP_CONF_UNACCEPT;
2959
2960 if (chan->num_conf_req >= 1)
2961 return -ECONNREFUSED;
2962
2963 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002964 sizeof(efs),
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002965 (unsigned long) &efs);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002966 } else {
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002967 /* Send PENDING Conf Rsp */
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002968 result = L2CAP_CONF_PENDING;
2969 set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002970 }
2971 }
2972
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002973 switch (rfc.mode) {
2974 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002975 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002976 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002977 break;
2978
2979 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002980 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2981 chan->remote_tx_win = rfc.txwin_size;
2982 else
2983 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2984
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002985 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002986
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002987 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2988 chan->conn->mtu -
2989 L2CAP_EXT_HDR_SIZE -
2990 L2CAP_SDULEN_SIZE -
2991 L2CAP_FCS_SIZE);
2992 rfc.max_pdu_size = cpu_to_le16(size);
2993 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002994
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002995 rfc.retrans_timeout =
Andrei Emeltchenko4fd21a82012-03-12 12:13:10 +02002996 __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002997 rfc.monitor_timeout =
Andrei Emeltchenko4fd21a82012-03-12 12:13:10 +02002998 __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002999
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003000 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03003001
3002 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
3003 sizeof(rfc), (unsigned long) &rfc);
3004
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03003005 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
3006 chan->remote_id = efs.id;
3007 chan->remote_stype = efs.stype;
3008 chan->remote_msdu = le16_to_cpu(efs.msdu);
3009 chan->remote_flush_to =
3010 le32_to_cpu(efs.flush_to);
3011 chan->remote_acc_lat =
3012 le32_to_cpu(efs.acc_lat);
3013 chan->remote_sdu_itime =
3014 le32_to_cpu(efs.sdu_itime);
3015 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
3016 sizeof(efs), (unsigned long) &efs);
3017 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003018 break;
3019
3020 case L2CAP_MODE_STREAMING:
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03003021 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
3022 chan->conn->mtu -
3023 L2CAP_EXT_HDR_SIZE -
3024 L2CAP_SDULEN_SIZE -
3025 L2CAP_FCS_SIZE);
3026 rfc.max_pdu_size = cpu_to_le16(size);
3027 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003028
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003029 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03003030
3031 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
3032 sizeof(rfc), (unsigned long) &rfc);
3033
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003034 break;
3035
3036 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02003037 result = L2CAP_CONF_UNACCEPT;
3038
3039 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003040 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02003041 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003042
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003043 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003044 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003045 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003046 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003047 rsp->result = cpu_to_le16(result);
3048 rsp->flags = cpu_to_le16(0x0000);
3049
3050 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003051}
3052
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003053static 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 -03003054{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003055 struct l2cap_conf_req *req = data;
3056 void *ptr = req->data;
3057 int type, olen;
3058 unsigned long val;
Mat Martineau36e999a2011-12-08 17:23:21 -08003059 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02003060 struct l2cap_conf_efs efs;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003061
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003062 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003063
3064 while (len >= L2CAP_CONF_OPT_SIZE) {
3065 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
3066
3067 switch (type) {
3068 case L2CAP_CONF_MTU:
3069 if (val < L2CAP_DEFAULT_MIN_MTU) {
3070 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003071 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003072 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003073 chan->imtu = val;
3074 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003075 break;
3076
3077 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003078 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003079 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003080 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003081 break;
3082
3083 case L2CAP_CONF_RFC:
3084 if (olen == sizeof(rfc))
3085 memcpy(&rfc, (void *)val, olen);
3086
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003087 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003088 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003089 return -ECONNREFUSED;
3090
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003091 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003092
3093 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
3094 sizeof(rfc), (unsigned long) &rfc);
3095 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003096
3097 case L2CAP_CONF_EWS:
3098 chan->tx_win = min_t(u16, val,
3099 L2CAP_DEFAULT_EXT_WINDOW);
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02003100 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
3101 chan->tx_win);
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003102 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02003103
3104 case L2CAP_CONF_EFS:
3105 if (olen == sizeof(efs))
3106 memcpy(&efs, (void *)val, olen);
3107
3108 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
3109 efs.stype != L2CAP_SERV_NOTRAFIC &&
3110 efs.stype != chan->local_stype)
3111 return -ECONNREFUSED;
3112
3113 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
3114 sizeof(efs), (unsigned long) &efs);
3115 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003116 }
3117 }
3118
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003119 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03003120 return -ECONNREFUSED;
3121
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003122 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03003123
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003124 if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003125 switch (rfc.mode) {
3126 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003127 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
3128 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
3129 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02003130
3131 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
3132 chan->local_msdu = le16_to_cpu(efs.msdu);
3133 chan->local_sdu_itime =
3134 le32_to_cpu(efs.sdu_itime);
3135 chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
3136 chan->local_flush_to =
3137 le32_to_cpu(efs.flush_to);
3138 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003139 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02003140
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003141 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003142 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003143 }
3144 }
3145
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003146 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003147 req->flags = cpu_to_le16(0x0000);
3148
3149 return ptr - data;
3150}
3151
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003152static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003153{
3154 struct l2cap_conf_rsp *rsp = data;
3155 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003156
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003157 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003159 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003160 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003161 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162
3163 return ptr - data;
3164}
3165
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003166void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03003167{
3168 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003169 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03003170 u8 buf[128];
3171
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003172 rsp.scid = cpu_to_le16(chan->dcid);
3173 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03003174 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
3175 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
3176 l2cap_send_cmd(conn, chan->ident,
3177 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
3178
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003179 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03003180 return;
3181
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03003182 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3183 l2cap_build_conf_req(chan, buf), buf);
3184 chan->num_conf_req++;
3185}
3186
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003187static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003188{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003189 int type, olen;
3190 unsigned long val;
3191 struct l2cap_conf_rfc rfc;
3192
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003193 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003194
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003195 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003196 return;
3197
3198 while (len >= L2CAP_CONF_OPT_SIZE) {
3199 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
3200
3201 switch (type) {
3202 case L2CAP_CONF_RFC:
3203 if (olen == sizeof(rfc))
3204 memcpy(&rfc, (void *)val, olen);
3205 goto done;
3206 }
3207 }
3208
Mat Martineau36e999a2011-12-08 17:23:21 -08003209 /* Use sane default values in case a misbehaving remote device
3210 * did not send an RFC option.
3211 */
3212 rfc.mode = chan->mode;
3213 rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
3214 rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
3215 rfc.max_pdu_size = cpu_to_le16(chan->imtu);
3216
3217 BT_ERR("Expected RFC option was not found, using defaults");
3218
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003219done:
3220 switch (rfc.mode) {
3221 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003222 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
3223 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
3224 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003225 break;
3226 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003227 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003228 }
3229}
3230
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003231static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3232{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003233 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003234
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003235 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003236 return 0;
3237
3238 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
3239 cmd->ident == conn->info_ident) {
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02003240 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01003241
3242 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003243 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003244
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003245 l2cap_conn_start(conn);
3246 }
3247
3248 return 0;
3249}
3250
Linus Torvalds1da177e2005-04-16 15:20:36 -07003251static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3252{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003253 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
3254 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003255 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04003256 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003257 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003258
3259 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003260 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261
Andrei Emeltchenko097db762012-03-09 14:16:17 +02003262 BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263
3264 /* Check if we have socket listening on psm */
Ido Yarivc2287682012-04-20 15:46:07 -03003265 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003266 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267 result = L2CAP_CR_BAD_PSM;
3268 goto sendresp;
3269 }
3270
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003271 parent = pchan->sk;
3272
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003273 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003274 lock_sock(parent);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003275
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003276 /* Check if the ACL is secure enough (if not SDP) */
3277 if (psm != cpu_to_le16(0x0001) &&
3278 !hci_conn_check_link_mode(conn->hcon)) {
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003279 conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003280 result = L2CAP_CR_SEC_BLOCK;
3281 goto response;
3282 }
3283
Linus Torvalds1da177e2005-04-16 15:20:36 -07003284 result = L2CAP_CR_NO_MEM;
3285
3286 /* Check for backlog size */
3287 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09003288 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003289 goto response;
3290 }
3291
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03003292 chan = pchan->ops->new_connection(pchan->data);
3293 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003294 goto response;
3295
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03003296 sk = chan->sk;
3297
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003299 if (__l2cap_get_chan_by_dcid(conn, scid)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003300 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003301 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003302 goto response;
3303 }
3304
3305 hci_conn_hold(conn->hcon);
3306
Linus Torvalds1da177e2005-04-16 15:20:36 -07003307 bacpy(&bt_sk(sk)->src, conn->src);
3308 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003309 chan->psm = psm;
3310 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003311
Gustavo F. Padovand1010242011-03-25 00:39:48 -03003312 bt_accept_enqueue(parent, sk);
3313
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003314 __l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003315
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003316 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003317
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03003318 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003319
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003320 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003321
Marcel Holtmann984947d2009-02-06 23:35:19 +01003322 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02003323 if (l2cap_chan_check_security(chan)) {
Gustavo Padovanc5daa682012-05-16 12:17:10 -03003324 if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02003325 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01003326 result = L2CAP_CR_PEND;
3327 status = L2CAP_CS_AUTHOR_PEND;
3328 parent->sk_data_ready(parent, 0);
3329 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02003330 __l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01003331 result = L2CAP_CR_SUCCESS;
3332 status = L2CAP_CS_NO_INFO;
3333 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003334 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02003335 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003336 result = L2CAP_CR_PEND;
3337 status = L2CAP_CS_AUTHEN_PEND;
3338 }
3339 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02003340 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003341 result = L2CAP_CR_PEND;
3342 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003343 }
3344
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345response:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003346 release_sock(parent);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003347 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003348
3349sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003350 rsp.scid = cpu_to_le16(scid);
3351 rsp.dcid = cpu_to_le16(dcid);
3352 rsp.result = cpu_to_le16(result);
3353 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003355
3356 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
3357 struct l2cap_info_req info;
3358 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3359
3360 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
3361 conn->info_ident = l2cap_get_ident(conn);
3362
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08003363 schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003364
3365 l2cap_send_cmd(conn, conn->info_ident,
3366 L2CAP_INFO_REQ, sizeof(info), &info);
3367 }
3368
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003369 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003370 result == L2CAP_CR_SUCCESS) {
3371 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003372 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003373 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003374 l2cap_build_conf_req(chan, buf), buf);
3375 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003376 }
3377
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378 return 0;
3379}
3380
3381static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3382{
3383 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
3384 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003385 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003386 u8 req[128];
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003387 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388
3389 scid = __le16_to_cpu(rsp->scid);
3390 dcid = __le16_to_cpu(rsp->dcid);
3391 result = __le16_to_cpu(rsp->result);
3392 status = __le16_to_cpu(rsp->status);
3393
Andrei Emeltchenko1b009c92012-02-21 12:54:54 +02003394 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
3395 dcid, scid, result, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003397 mutex_lock(&conn->chan_lock);
3398
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399 if (scid) {
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003400 chan = __l2cap_get_chan_by_scid(conn, scid);
3401 if (!chan) {
3402 err = -EFAULT;
3403 goto unlock;
3404 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405 } else {
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003406 chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
3407 if (!chan) {
3408 err = -EFAULT;
3409 goto unlock;
3410 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411 }
3412
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003413 err = 0;
3414
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003415 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003416
Linus Torvalds1da177e2005-04-16 15:20:36 -07003417 switch (result) {
3418 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003419 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003420 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003421 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003422 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003423
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003424 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003425 break;
3426
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003428 l2cap_build_conf_req(chan, req), req);
3429 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003430 break;
3431
3432 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003433 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434 break;
3435
3436 default:
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003437 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003438 break;
3439 }
3440
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003441 l2cap_chan_unlock(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003442
3443unlock:
3444 mutex_unlock(&conn->chan_lock);
3445
3446 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003447}
3448
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003449static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07003450{
3451 /* FCS is enabled only in ERTM or streaming mode, if one or both
3452 * sides request it.
3453 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003454 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003455 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003456 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003457 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07003458}
3459
Al Viro88219a02007-07-29 00:17:25 -07003460static 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 -07003461{
3462 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
3463 u16 dcid, flags;
3464 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003465 struct l2cap_chan *chan;
Mat Martineau3c588192012-04-11 10:48:42 -07003466 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467
3468 dcid = __le16_to_cpu(req->dcid);
3469 flags = __le16_to_cpu(req->flags);
3470
3471 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
3472
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003473 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003474 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003475 return -ENOENT;
3476
David S. Miller033b1142011-07-21 13:38:42 -07003477 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003478 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003479
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003480 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
3481 rej.scid = cpu_to_le16(chan->scid);
3482 rej.dcid = cpu_to_le16(chan->dcid);
3483
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003484 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
3485 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003486 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003487 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003488
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003489 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07003490 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04003491 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003492 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003493 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003494 L2CAP_CONF_REJECT, flags), rsp);
3495 goto unlock;
3496 }
3497
3498 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003499 memcpy(chan->conf_req + chan->conf_len, req->data, len);
3500 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501
3502 if (flags & 0x0001) {
3503 /* Incomplete config. Send empty response. */
3504 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003505 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003506 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507 goto unlock;
3508 }
3509
3510 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003511 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003512 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003513 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003515 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003516
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003517 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003518 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003519
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003520 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003521 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003522
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003523 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02003524 goto unlock;
3525
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003526 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003527 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003528
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003529 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003530
Mat Martineau105bdf92012-04-27 16:50:48 -07003531 if (chan->mode == L2CAP_MODE_ERTM ||
3532 chan->mode == L2CAP_MODE_STREAMING)
Mat Martineau3c588192012-04-11 10:48:42 -07003533 err = l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003534
Mat Martineau3c588192012-04-11 10:48:42 -07003535 if (err < 0)
3536 l2cap_send_disconn_req(chan->conn, chan, -err);
3537 else
3538 l2cap_chan_ready(chan);
3539
Marcel Holtmann876d9482007-10-20 13:35:42 +02003540 goto unlock;
3541 }
3542
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003543 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003544 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003545 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003546 l2cap_build_conf_req(chan, buf), buf);
3547 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003548 }
3549
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003550 /* Got Conf Rsp PENDING from remote side and asume we sent
3551 Conf Rsp PENDING in the code above */
3552 if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
3553 test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
3554
3555 /* check compatibility */
3556
3557 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
3558 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
3559
3560 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02003561 l2cap_build_conf_rsp(chan, rsp,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003562 L2CAP_CONF_SUCCESS, 0x0000), rsp);
3563 }
3564
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565unlock:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003566 l2cap_chan_unlock(chan);
Mat Martineau3c588192012-04-11 10:48:42 -07003567 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568}
3569
3570static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3571{
3572 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
3573 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003574 struct l2cap_chan *chan;
Andrei Emeltchenko61386cb2012-03-12 12:13:07 +02003575 int len = le16_to_cpu(cmd->len) - sizeof(*rsp);
Mat Martineau3c588192012-04-11 10:48:42 -07003576 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003577
3578 scid = __le16_to_cpu(rsp->scid);
3579 flags = __le16_to_cpu(rsp->flags);
3580 result = __le16_to_cpu(rsp->result);
3581
Andrei Emeltchenko61386cb2012-03-12 12:13:07 +02003582 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
3583 result, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003585 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003586 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003587 return 0;
3588
3589 switch (result) {
3590 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003591 l2cap_conf_rfc_get(chan, rsp->data, len);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003592 clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003593 break;
3594
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003595 case L2CAP_CONF_PENDING:
3596 set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
3597
3598 if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
3599 char buf[64];
3600
3601 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
3602 buf, &result);
3603 if (len < 0) {
3604 l2cap_send_disconn_req(conn, chan, ECONNRESET);
3605 goto done;
3606 }
3607
3608 /* check compatibility */
3609
3610 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
3611 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
3612
3613 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02003614 l2cap_build_conf_rsp(chan, buf,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003615 L2CAP_CONF_SUCCESS, 0x0000), buf);
3616 }
3617 goto done;
3618
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003620 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003621 char req[64];
3622
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003623 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003624 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003625 goto done;
3626 }
3627
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003628 /* throw out any old stored conf requests */
3629 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003630 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
3631 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003632 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003633 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003634 goto done;
3635 }
3636
3637 l2cap_send_cmd(conn, l2cap_get_ident(conn),
3638 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003639 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003640 if (result != L2CAP_CONF_SUCCESS)
3641 goto done;
3642 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643 }
3644
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09003645 default:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003646 l2cap_chan_set_err(chan, ECONNRESET);
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +02003647
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08003648 __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003649 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003650 goto done;
3651 }
3652
3653 if (flags & 0x01)
3654 goto done;
3655
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003656 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003658 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003659 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003660
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003661 l2cap_state_change(chan, BT_CONNECTED);
Mat Martineau105bdf92012-04-27 16:50:48 -07003662 if (chan->mode == L2CAP_MODE_ERTM ||
3663 chan->mode == L2CAP_MODE_STREAMING)
Mat Martineau3c588192012-04-11 10:48:42 -07003664 err = l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003665
Mat Martineau3c588192012-04-11 10:48:42 -07003666 if (err < 0)
3667 l2cap_send_disconn_req(chan->conn, chan, -err);
3668 else
3669 l2cap_chan_ready(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670 }
3671
3672done:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003673 l2cap_chan_unlock(chan);
Mat Martineau3c588192012-04-11 10:48:42 -07003674 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675}
3676
3677static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3678{
3679 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3680 struct l2cap_disconn_rsp rsp;
3681 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003682 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003683 struct sock *sk;
3684
3685 scid = __le16_to_cpu(req->scid);
3686 dcid = __le16_to_cpu(req->dcid);
3687
3688 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3689
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003690 mutex_lock(&conn->chan_lock);
3691
3692 chan = __l2cap_get_chan_by_scid(conn, dcid);
3693 if (!chan) {
3694 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003695 return 0;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003696 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003698 l2cap_chan_lock(chan);
3699
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003700 sk = chan->sk;
3701
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003702 rsp.dcid = cpu_to_le16(chan->scid);
3703 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3705
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003706 lock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707 sk->sk_shutdown = SHUTDOWN_MASK;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003708 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709
Mat Martineau61d6ef32012-04-27 16:50:50 -07003710 l2cap_chan_hold(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003711 l2cap_chan_del(chan, ECONNRESET);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003712
3713 l2cap_chan_unlock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003715 chan->ops->close(chan->data);
Mat Martineau61d6ef32012-04-27 16:50:50 -07003716 l2cap_chan_put(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003717
3718 mutex_unlock(&conn->chan_lock);
3719
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720 return 0;
3721}
3722
3723static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3724{
3725 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3726 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003727 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003728
3729 scid = __le16_to_cpu(rsp->scid);
3730 dcid = __le16_to_cpu(rsp->dcid);
3731
3732 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3733
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003734 mutex_lock(&conn->chan_lock);
3735
3736 chan = __l2cap_get_chan_by_scid(conn, scid);
3737 if (!chan) {
3738 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003739 return 0;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003740 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003741
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003742 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003743
Mat Martineau61d6ef32012-04-27 16:50:50 -07003744 l2cap_chan_hold(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003745 l2cap_chan_del(chan, 0);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003746
3747 l2cap_chan_unlock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003748
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003749 chan->ops->close(chan->data);
Mat Martineau61d6ef32012-04-27 16:50:50 -07003750 l2cap_chan_put(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003751
3752 mutex_unlock(&conn->chan_lock);
3753
Linus Torvalds1da177e2005-04-16 15:20:36 -07003754 return 0;
3755}
3756
3757static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3758{
3759 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760 u16 type;
3761
3762 type = __le16_to_cpu(req->type);
3763
3764 BT_DBG("type 0x%4.4x", type);
3765
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003766 if (type == L2CAP_IT_FEAT_MASK) {
3767 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003768 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003769 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3770 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3771 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003772 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003773 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3774 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003775 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003776 feat_mask |= L2CAP_FEAT_EXT_FLOW
3777 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003778
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003779 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003780 l2cap_send_cmd(conn, cmd->ident,
3781 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003782 } else if (type == L2CAP_IT_FIXED_CHAN) {
3783 u8 buf[12];
3784 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
Mat Martineau50a147c2011-11-02 16:18:34 -07003785
3786 if (enable_hs)
3787 l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
3788 else
3789 l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
3790
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003791 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3792 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003793 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003794 l2cap_send_cmd(conn, cmd->ident,
3795 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003796 } else {
3797 struct l2cap_info_rsp rsp;
3798 rsp.type = cpu_to_le16(type);
3799 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3800 l2cap_send_cmd(conn, cmd->ident,
3801 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3802 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003803
3804 return 0;
3805}
3806
3807static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3808{
3809 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3810 u16 type, result;
3811
3812 type = __le16_to_cpu(rsp->type);
3813 result = __le16_to_cpu(rsp->result);
3814
3815 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3816
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003817 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3818 if (cmd->ident != conn->info_ident ||
3819 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3820 return 0;
3821
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02003822 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003823
Ville Tervoadb08ed2010-08-04 09:43:33 +03003824 if (result != L2CAP_IR_SUCCESS) {
3825 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3826 conn->info_ident = 0;
3827
3828 l2cap_conn_start(conn);
3829
3830 return 0;
3831 }
3832
Andrei Emeltchenko978c93b2012-02-29 10:41:41 +02003833 switch (type) {
3834 case L2CAP_IT_FEAT_MASK:
Harvey Harrison83985312008-05-02 16:25:46 -07003835 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003836
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003837 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003838 struct l2cap_info_req req;
3839 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3840
3841 conn->info_ident = l2cap_get_ident(conn);
3842
3843 l2cap_send_cmd(conn, conn->info_ident,
3844 L2CAP_INFO_REQ, sizeof(req), &req);
3845 } else {
3846 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3847 conn->info_ident = 0;
3848
3849 l2cap_conn_start(conn);
3850 }
Andrei Emeltchenko978c93b2012-02-29 10:41:41 +02003851 break;
3852
3853 case L2CAP_IT_FIXED_CHAN:
3854 conn->fixed_chan_mask = rsp->data[0];
Marcel Holtmann984947d2009-02-06 23:35:19 +01003855 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003856 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003857
3858 l2cap_conn_start(conn);
Andrei Emeltchenko978c93b2012-02-29 10:41:41 +02003859 break;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003860 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003861
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862 return 0;
3863}
3864
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003865static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3866 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3867 void *data)
3868{
3869 struct l2cap_create_chan_req *req = data;
3870 struct l2cap_create_chan_rsp rsp;
3871 u16 psm, scid;
3872
3873 if (cmd_len != sizeof(*req))
3874 return -EPROTO;
3875
3876 if (!enable_hs)
3877 return -EINVAL;
3878
3879 psm = le16_to_cpu(req->psm);
3880 scid = le16_to_cpu(req->scid);
3881
3882 BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3883
3884 /* Placeholder: Always reject */
3885 rsp.dcid = 0;
3886 rsp.scid = cpu_to_le16(scid);
Andrei Emeltchenko8ce0c492012-03-12 12:13:09 +02003887 rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
3888 rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003889
3890 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3891 sizeof(rsp), &rsp);
3892
3893 return 0;
3894}
3895
3896static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3897 struct l2cap_cmd_hdr *cmd, void *data)
3898{
3899 BT_DBG("conn %p", conn);
3900
3901 return l2cap_connect_rsp(conn, cmd, data);
3902}
3903
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003904static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
3905 u16 icid, u16 result)
3906{
3907 struct l2cap_move_chan_rsp rsp;
3908
3909 BT_DBG("icid %d, result %d", icid, result);
3910
3911 rsp.icid = cpu_to_le16(icid);
3912 rsp.result = cpu_to_le16(result);
3913
3914 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
3915}
3916
3917static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
3918 struct l2cap_chan *chan, u16 icid, u16 result)
3919{
3920 struct l2cap_move_chan_cfm cfm;
3921 u8 ident;
3922
3923 BT_DBG("icid %d, result %d", icid, result);
3924
3925 ident = l2cap_get_ident(conn);
3926 if (chan)
3927 chan->ident = ident;
3928
3929 cfm.icid = cpu_to_le16(icid);
3930 cfm.result = cpu_to_le16(result);
3931
3932 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
3933}
3934
3935static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
3936 u16 icid)
3937{
3938 struct l2cap_move_chan_cfm_rsp rsp;
3939
3940 BT_DBG("icid %d", icid);
3941
3942 rsp.icid = cpu_to_le16(icid);
3943 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
3944}
3945
3946static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
3947 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3948{
3949 struct l2cap_move_chan_req *req = data;
3950 u16 icid = 0;
3951 u16 result = L2CAP_MR_NOT_ALLOWED;
3952
3953 if (cmd_len != sizeof(*req))
3954 return -EPROTO;
3955
3956 icid = le16_to_cpu(req->icid);
3957
3958 BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
3959
3960 if (!enable_hs)
3961 return -EINVAL;
3962
3963 /* Placeholder: Always refuse */
3964 l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
3965
3966 return 0;
3967}
3968
3969static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
3970 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3971{
3972 struct l2cap_move_chan_rsp *rsp = data;
3973 u16 icid, result;
3974
3975 if (cmd_len != sizeof(*rsp))
3976 return -EPROTO;
3977
3978 icid = le16_to_cpu(rsp->icid);
3979 result = le16_to_cpu(rsp->result);
3980
3981 BT_DBG("icid %d, result %d", icid, result);
3982
3983 /* Placeholder: Always unconfirmed */
3984 l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
3985
3986 return 0;
3987}
3988
3989static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
3990 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3991{
3992 struct l2cap_move_chan_cfm *cfm = data;
3993 u16 icid, result;
3994
3995 if (cmd_len != sizeof(*cfm))
3996 return -EPROTO;
3997
3998 icid = le16_to_cpu(cfm->icid);
3999 result = le16_to_cpu(cfm->result);
4000
4001 BT_DBG("icid %d, result %d", icid, result);
4002
4003 l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
4004
4005 return 0;
4006}
4007
4008static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
4009 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
4010{
4011 struct l2cap_move_chan_cfm_rsp *rsp = data;
4012 u16 icid;
4013
4014 if (cmd_len != sizeof(*rsp))
4015 return -EPROTO;
4016
4017 icid = le16_to_cpu(rsp->icid);
4018
4019 BT_DBG("icid %d", icid);
4020
4021 return 0;
4022}
4023
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03004024static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02004025 u16 to_multiplier)
4026{
4027 u16 max_latency;
4028
4029 if (min > max || min < 6 || max > 3200)
4030 return -EINVAL;
4031
4032 if (to_multiplier < 10 || to_multiplier > 3200)
4033 return -EINVAL;
4034
4035 if (max >= to_multiplier * 8)
4036 return -EINVAL;
4037
4038 max_latency = (to_multiplier * 8 / max) - 1;
4039 if (latency > 499 || latency > max_latency)
4040 return -EINVAL;
4041
4042 return 0;
4043}
4044
4045static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
4046 struct l2cap_cmd_hdr *cmd, u8 *data)
4047{
4048 struct hci_conn *hcon = conn->hcon;
4049 struct l2cap_conn_param_update_req *req;
4050 struct l2cap_conn_param_update_rsp rsp;
4051 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02004052 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02004053
4054 if (!(hcon->link_mode & HCI_LM_MASTER))
4055 return -EINVAL;
4056
4057 cmd_len = __le16_to_cpu(cmd->len);
4058 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
4059 return -EPROTO;
4060
4061 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03004062 min = __le16_to_cpu(req->min);
4063 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02004064 latency = __le16_to_cpu(req->latency);
4065 to_multiplier = __le16_to_cpu(req->to_multiplier);
4066
4067 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
4068 min, max, latency, to_multiplier);
4069
4070 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02004071
4072 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
4073 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02004074 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
4075 else
4076 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
4077
4078 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
4079 sizeof(rsp), &rsp);
4080
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02004081 if (!err)
4082 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
4083
Claudio Takahaside731152011-02-11 19:28:55 -02004084 return 0;
4085}
4086
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004087static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
4088 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
4089{
4090 int err = 0;
4091
4092 switch (cmd->code) {
4093 case L2CAP_COMMAND_REJ:
4094 l2cap_command_rej(conn, cmd, data);
4095 break;
4096
4097 case L2CAP_CONN_REQ:
4098 err = l2cap_connect_req(conn, cmd, data);
4099 break;
4100
4101 case L2CAP_CONN_RSP:
4102 err = l2cap_connect_rsp(conn, cmd, data);
4103 break;
4104
4105 case L2CAP_CONF_REQ:
4106 err = l2cap_config_req(conn, cmd, cmd_len, data);
4107 break;
4108
4109 case L2CAP_CONF_RSP:
4110 err = l2cap_config_rsp(conn, cmd, data);
4111 break;
4112
4113 case L2CAP_DISCONN_REQ:
4114 err = l2cap_disconnect_req(conn, cmd, data);
4115 break;
4116
4117 case L2CAP_DISCONN_RSP:
4118 err = l2cap_disconnect_rsp(conn, cmd, data);
4119 break;
4120
4121 case L2CAP_ECHO_REQ:
4122 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
4123 break;
4124
4125 case L2CAP_ECHO_RSP:
4126 break;
4127
4128 case L2CAP_INFO_REQ:
4129 err = l2cap_information_req(conn, cmd, data);
4130 break;
4131
4132 case L2CAP_INFO_RSP:
4133 err = l2cap_information_rsp(conn, cmd, data);
4134 break;
4135
Mat Martineauf94ff6f2011-11-02 16:18:32 -07004136 case L2CAP_CREATE_CHAN_REQ:
4137 err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
4138 break;
4139
4140 case L2CAP_CREATE_CHAN_RSP:
4141 err = l2cap_create_channel_rsp(conn, cmd, data);
4142 break;
4143
Mat Martineau8d5a04a2011-11-02 16:18:35 -07004144 case L2CAP_MOVE_CHAN_REQ:
4145 err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
4146 break;
4147
4148 case L2CAP_MOVE_CHAN_RSP:
4149 err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
4150 break;
4151
4152 case L2CAP_MOVE_CHAN_CFM:
4153 err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
4154 break;
4155
4156 case L2CAP_MOVE_CHAN_CFM_RSP:
4157 err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
4158 break;
4159
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004160 default:
4161 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
4162 err = -EINVAL;
4163 break;
4164 }
4165
4166 return err;
4167}
4168
4169static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
4170 struct l2cap_cmd_hdr *cmd, u8 *data)
4171{
4172 switch (cmd->code) {
4173 case L2CAP_COMMAND_REJ:
4174 return 0;
4175
4176 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02004177 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004178
4179 case L2CAP_CONN_PARAM_UPDATE_RSP:
4180 return 0;
4181
4182 default:
4183 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
4184 return -EINVAL;
4185 }
4186}
4187
4188static inline void l2cap_sig_channel(struct l2cap_conn *conn,
4189 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004190{
4191 u8 *data = skb->data;
4192 int len = skb->len;
4193 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004194 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004195
4196 l2cap_raw_recv(conn, skb);
4197
4198 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07004199 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004200 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
4201 data += L2CAP_CMD_HDR_SIZE;
4202 len -= L2CAP_CMD_HDR_SIZE;
4203
Al Viro88219a02007-07-29 00:17:25 -07004204 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205
Al Viro88219a02007-07-29 00:17:25 -07004206 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 -07004207
Al Viro88219a02007-07-29 00:17:25 -07004208 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209 BT_DBG("corrupted command");
4210 break;
4211 }
4212
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004213 if (conn->hcon->type == LE_LINK)
4214 err = l2cap_le_sig_cmd(conn, &cmd, data);
4215 else
4216 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217
4218 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03004219 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03004220
4221 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222
4223 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03004224 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
4226 }
4227
Al Viro88219a02007-07-29 00:17:25 -07004228 data += cmd_len;
4229 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230 }
4231
4232 kfree_skb(skb);
4233}
4234
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004235static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004236{
4237 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03004238 int hdr_size;
4239
4240 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
4241 hdr_size = L2CAP_EXT_HDR_SIZE;
4242 else
4243 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004244
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004245 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004246 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004247 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
4248 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
4249
4250 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03004251 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004252 }
4253 return 0;
4254}
4255
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004256static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03004257{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004258 u32 control = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03004259
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004260 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03004261
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004262 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03004263
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004264 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004265 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004266 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03004267 }
4268
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004269 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004270 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03004271
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004272 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03004273
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004274 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004275 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004276 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03004277 }
4278}
4279
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004280static 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 -03004281{
4282 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03004283 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004284
Mat Martineau3ce35142012-04-25 16:36:14 -07004285 bt_cb(skb)->control.txseq = tx_seq;
4286 bt_cb(skb)->control.sar = sar;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004287
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004288 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004289
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004290 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03004291
Szymon Janc039d9572011-11-16 09:32:19 +01004292 while (next_skb) {
Mat Martineau3ce35142012-04-25 16:36:14 -07004293 if (bt_cb(next_skb)->control.txseq == tx_seq)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004294 return -EINVAL;
4295
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004296 next_tx_seq_offset = __seq_offset(chan,
Mat Martineau3ce35142012-04-25 16:36:14 -07004297 bt_cb(next_skb)->control.txseq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03004298
4299 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004300 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004301 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004302 }
4303
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004304 if (skb_queue_is_last(&chan->srej_q, next_skb))
Szymon Janc039d9572011-11-16 09:32:19 +01004305 next_skb = NULL;
4306 else
4307 next_skb = skb_queue_next(&chan->srej_q, next_skb);
4308 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004309
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004310 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004311
4312 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004313}
4314
Mat Martineau84084a32011-07-22 14:54:00 -07004315static void append_skb_frag(struct sk_buff *skb,
4316 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004317{
Mat Martineau84084a32011-07-22 14:54:00 -07004318 /* skb->len reflects data in skb as well as all fragments
4319 * skb->data_len reflects only data in fragments
4320 */
4321 if (!skb_has_frag_list(skb))
4322 skb_shinfo(skb)->frag_list = new_frag;
4323
4324 new_frag->next = NULL;
4325
4326 (*last_frag)->next = new_frag;
4327 *last_frag = new_frag;
4328
4329 skb->len += new_frag->len;
4330 skb->data_len += new_frag->len;
4331 skb->truesize += new_frag->truesize;
4332}
4333
Mat Martineau4b51dae92012-05-17 20:53:37 -07004334static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
4335 struct l2cap_ctrl *control)
Mat Martineau84084a32011-07-22 14:54:00 -07004336{
4337 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004338
Mat Martineau4b51dae92012-05-17 20:53:37 -07004339 switch (control->sar) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004340 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07004341 if (chan->sdu)
4342 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004343
Mat Martineau84084a32011-07-22 14:54:00 -07004344 err = chan->ops->recv(chan->data, skb);
4345 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004346
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004347 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07004348 if (chan->sdu)
4349 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004350
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03004351 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004352 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004353
Mat Martineau84084a32011-07-22 14:54:00 -07004354 if (chan->sdu_len > chan->imtu) {
4355 err = -EMSGSIZE;
4356 break;
4357 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004358
Mat Martineau84084a32011-07-22 14:54:00 -07004359 if (skb->len >= chan->sdu_len)
4360 break;
4361
4362 chan->sdu = skb;
4363 chan->sdu_last_frag = skb;
4364
4365 skb = NULL;
4366 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004367 break;
4368
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004369 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03004370 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07004371 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004372
Mat Martineau84084a32011-07-22 14:54:00 -07004373 append_skb_frag(chan->sdu, skb,
4374 &chan->sdu_last_frag);
4375 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004376
Mat Martineau84084a32011-07-22 14:54:00 -07004377 if (chan->sdu->len >= chan->sdu_len)
4378 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03004379
Mat Martineau84084a32011-07-22 14:54:00 -07004380 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004381 break;
4382
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004383 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03004384 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07004385 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004386
Mat Martineau84084a32011-07-22 14:54:00 -07004387 append_skb_frag(chan->sdu, skb,
4388 &chan->sdu_last_frag);
4389 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004390
Mat Martineau84084a32011-07-22 14:54:00 -07004391 if (chan->sdu->len != chan->sdu_len)
4392 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004393
Mat Martineau84084a32011-07-22 14:54:00 -07004394 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03004395
Mat Martineau84084a32011-07-22 14:54:00 -07004396 if (!err) {
4397 /* Reassembly complete */
4398 chan->sdu = NULL;
4399 chan->sdu_last_frag = NULL;
4400 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004401 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004402 break;
4403 }
4404
Mat Martineau84084a32011-07-22 14:54:00 -07004405 if (err) {
4406 kfree_skb(skb);
4407 kfree_skb(chan->sdu);
4408 chan->sdu = NULL;
4409 chan->sdu_last_frag = NULL;
4410 chan->sdu_len = 0;
4411 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004412
Mat Martineau84084a32011-07-22 14:54:00 -07004413 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004414}
4415
Mat Martineau26f880d2011-07-07 09:39:01 -07004416static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004417{
Mat Martineau26f880d2011-07-07 09:39:01 -07004418 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004419
Mat Martineau26f880d2011-07-07 09:39:01 -07004420 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
Mat Martineau3c588192012-04-11 10:48:42 -07004421 l2cap_seq_list_clear(&chan->srej_list);
Mat Martineau26f880d2011-07-07 09:39:01 -07004422
Szymon Janc77f918b2012-01-11 10:59:48 +01004423 __set_ack_timer(chan);
Mat Martineau26f880d2011-07-07 09:39:01 -07004424}
4425
4426static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
4427{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004428 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004429
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004430 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004431 goto done;
4432
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004433 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004434 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004435 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004436 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004437
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004438 __clear_retrans_timer(chan);
4439 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004440
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004441 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004442
4443done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004444 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
4445 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004446
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004447 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03004448}
4449
Mat Martineaue3281402011-07-07 09:39:02 -07004450void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03004451{
Mat Martineaue3281402011-07-07 09:39:02 -07004452 if (chan->mode == L2CAP_MODE_ERTM) {
4453 if (busy)
4454 l2cap_ertm_enter_local_busy(chan);
4455 else
4456 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03004457 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004458}
4459
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004460static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004461{
4462 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004463 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004464
Mat Martineaue3281402011-07-07 09:39:02 -07004465 while ((skb = skb_peek(&chan->srej_q)) &&
4466 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4467 int err;
4468
Mat Martineau3ce35142012-04-25 16:36:14 -07004469 if (bt_cb(skb)->control.txseq != tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004470 break;
4471
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004472 skb = skb_dequeue(&chan->srej_q);
Mat Martineau3ce35142012-04-25 16:36:14 -07004473 control = __set_ctrl_sar(chan, bt_cb(skb)->control.sar);
Mat Martineaue3281402011-07-07 09:39:02 -07004474
4475 if (err < 0) {
4476 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4477 break;
4478 }
4479
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004480 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
4481 tx_seq = __next_seq(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004482 }
4483}
4484
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004485static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004486{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004487 struct srej_list *l, *tmp;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004488 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004489
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004490 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004491 if (l->tx_seq == tx_seq) {
4492 list_del(&l->list);
4493 kfree(l);
4494 return;
4495 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004496 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004497 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004498 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004499 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004500 }
4501}
4502
Szymon Jancaef89f22011-11-16 09:32:18 +01004503static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004504{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004505 struct srej_list *new;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004506 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004507
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004508 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004509 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004510 control |= __set_reqseq(chan, chan->expected_tx_seq);
Mat Martineau3c588192012-04-11 10:48:42 -07004511 l2cap_seq_list_append(&chan->srej_list, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004512
4513 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Szymon Jancaef89f22011-11-16 09:32:18 +01004514 if (!new)
4515 return -ENOMEM;
4516
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004517 new->tx_seq = chan->expected_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004518
4519 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
4520
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004521 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004522 }
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004523
4524 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Szymon Jancaef89f22011-11-16 09:32:18 +01004525
4526 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004527}
4528
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004529static 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 -03004530{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004531 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004532 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004533 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03004534 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004535 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004536 int err = 0;
4537
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004538 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 -03004539 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004540
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004541 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004542 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004543 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004544 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004545 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004546 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004547 }
4548
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004549 chan->expected_ack_seq = req_seq;
4550 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03004551
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004552 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004553
4554 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004555 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004556 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004557 goto drop;
4558 }
4559
Szymon Janc77f918b2012-01-11 10:59:48 +01004560 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4561 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
4562 l2cap_send_ack(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004563 goto drop;
Szymon Janc77f918b2012-01-11 10:59:48 +01004564 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004565
Mat Martineau02f1b642011-06-29 14:35:19 -07004566 if (tx_seq == chan->expected_tx_seq)
4567 goto expected;
4568
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004569 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004570 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004571
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004572 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004573 struct srej_list, list);
4574 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004575 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004576 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004577
4578 list_del(&first->list);
4579 kfree(first);
4580
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004581 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004582 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004583 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004584 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004585 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004586 }
4587 } else {
4588 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004589
4590 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004591 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004592 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004593
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004594 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004595 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004596 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004597 return 0;
4598 }
4599 }
Szymon Jancaef89f22011-11-16 09:32:18 +01004600
4601 err = l2cap_send_srejframe(chan, tx_seq);
4602 if (err < 0) {
4603 l2cap_send_disconn_req(chan->conn, chan, -err);
4604 return err;
4605 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004606 }
4607 } else {
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004608 expected_tx_seq_offset = __seq_offset(chan,
4609 chan->expected_tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004610
4611 /* duplicated tx_seq */
4612 if (tx_seq_offset < expected_tx_seq_offset)
4613 goto drop;
4614
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004615 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004616
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004617 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004618
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004619 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004620 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004621
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004622 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004623 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004624
Szymon Janc0ef3ef02012-01-11 10:59:46 +01004625 /* Set P-bit only if there are some I-frames to ack. */
4626 if (__clear_ack_timer(chan))
4627 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03004628
Szymon Jancaef89f22011-11-16 09:32:18 +01004629 err = l2cap_send_srejframe(chan, tx_seq);
4630 if (err < 0) {
4631 l2cap_send_disconn_req(chan->conn, chan, -err);
4632 return err;
4633 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004634 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004635 return 0;
4636
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004637expected:
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004638 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004639
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004640 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Mat Martineau3ce35142012-04-25 16:36:14 -07004641 bt_cb(skb)->control.txseq = tx_seq;
4642 bt_cb(skb)->control.sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004643 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004644 return 0;
4645 }
4646
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004647 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
4648
Mat Martineaue3281402011-07-07 09:39:02 -07004649 if (err < 0) {
4650 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4651 return err;
4652 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03004653
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004654 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004655 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004656 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03004657 }
4658
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03004659
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004660 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
4661 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004662 l2cap_send_ack(chan);
Gustavo F. Padovan4d611e42011-06-23 19:30:48 -03004663 else
4664 __set_ack_timer(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03004665
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004666 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004667
4668drop:
4669 kfree_skb(skb);
4670 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004671}
4672
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004673static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004674{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004675 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004676 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004677
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004678 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004679 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004680
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004681 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004682 set_bit(CONN_SEND_FBIT, &chan->conn_state);
4683 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
4684 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004685 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004686 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004687
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004688 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004689 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004690 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004691 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004692 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004693
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004694 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004695 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004696
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004697 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004698 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004699
4700 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004701 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004702 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004703 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004704
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004705 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4706 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004707 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02004708 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004709 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004710 }
4711}
4712
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004713static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004714{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004715 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004716
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004717 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004718
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004719 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004720
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004721 chan->expected_ack_seq = tx_seq;
4722 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004723
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004724 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004725 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004726 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004727 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004728 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004729
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004730 if (test_bit(CONN_WAIT_F, &chan->conn_state))
4731 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004732 }
4733}
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004734static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004735{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004736 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004737
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004738 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004739
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004740 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004741
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004742 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004743 chan->expected_ack_seq = tx_seq;
4744 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004745
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004746 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004747 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004748
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004749 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004750
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004751 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004752 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004753 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004754 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004755 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004756 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004757 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004758 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004759 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004760 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004761 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004762 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004763 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004764 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004765 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004766 }
4767 }
4768}
4769
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004770static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004771{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004772 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004773
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004774 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004775
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004776 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004777 chan->expected_ack_seq = tx_seq;
4778 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004779
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004780 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004781 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004782
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004783 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004784 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004785 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004786 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004787 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004788 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004789
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004790 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004791 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004792 } else {
4793 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004794 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004795}
4796
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004797static 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 -03004798{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004799 BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004800
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004801 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004802 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004803 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004804 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004805 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004806 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004807 }
4808
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004809 switch (__get_ctrl_super(chan, rx_control)) {
4810 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004811 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004812 break;
4813
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004814 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004815 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004816 break;
4817
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004818 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004819 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004820 break;
4821
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004822 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004823 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004824 break;
4825 }
4826
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004827 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004828 return 0;
4829}
4830
Mat Martineau4b51dae92012-05-17 20:53:37 -07004831static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
4832{
4833 BT_DBG("chan %p, txseq %d", chan, txseq);
4834
4835 BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq,
4836 chan->expected_tx_seq);
4837
4838 if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
4839 if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
4840 chan->tx_win) {
4841 /* See notes below regarding "double poll" and
4842 * invalid packets.
4843 */
4844 if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
4845 BT_DBG("Invalid/Ignore - after SREJ");
4846 return L2CAP_TXSEQ_INVALID_IGNORE;
4847 } else {
4848 BT_DBG("Invalid - in window after SREJ sent");
4849 return L2CAP_TXSEQ_INVALID;
4850 }
4851 }
4852
4853 if (chan->srej_list.head == txseq) {
4854 BT_DBG("Expected SREJ");
4855 return L2CAP_TXSEQ_EXPECTED_SREJ;
4856 }
4857
4858 if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) {
4859 BT_DBG("Duplicate SREJ - txseq already stored");
4860 return L2CAP_TXSEQ_DUPLICATE_SREJ;
4861 }
4862
4863 if (l2cap_seq_list_contains(&chan->srej_list, txseq)) {
4864 BT_DBG("Unexpected SREJ - not requested");
4865 return L2CAP_TXSEQ_UNEXPECTED_SREJ;
4866 }
4867 }
4868
4869 if (chan->expected_tx_seq == txseq) {
4870 if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
4871 chan->tx_win) {
4872 BT_DBG("Invalid - txseq outside tx window");
4873 return L2CAP_TXSEQ_INVALID;
4874 } else {
4875 BT_DBG("Expected");
4876 return L2CAP_TXSEQ_EXPECTED;
4877 }
4878 }
4879
4880 if (__seq_offset(chan, txseq, chan->last_acked_seq) <
4881 __seq_offset(chan, chan->expected_tx_seq,
4882 chan->last_acked_seq)){
4883 BT_DBG("Duplicate - expected_tx_seq later than txseq");
4884 return L2CAP_TXSEQ_DUPLICATE;
4885 }
4886
4887 if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) {
4888 /* A source of invalid packets is a "double poll" condition,
4889 * where delays cause us to send multiple poll packets. If
4890 * the remote stack receives and processes both polls,
4891 * sequence numbers can wrap around in such a way that a
4892 * resent frame has a sequence number that looks like new data
4893 * with a sequence gap. This would trigger an erroneous SREJ
4894 * request.
4895 *
4896 * Fortunately, this is impossible with a tx window that's
4897 * less than half of the maximum sequence number, which allows
4898 * invalid frames to be safely ignored.
4899 *
4900 * With tx window sizes greater than half of the tx window
4901 * maximum, the frame is invalid and cannot be ignored. This
4902 * causes a disconnect.
4903 */
4904
4905 if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
4906 BT_DBG("Invalid/Ignore - txseq outside tx window");
4907 return L2CAP_TXSEQ_INVALID_IGNORE;
4908 } else {
4909 BT_DBG("Invalid - txseq outside tx window");
4910 return L2CAP_TXSEQ_INVALID;
4911 }
4912 } else {
4913 BT_DBG("Unexpected - txseq indicates missing frames");
4914 return L2CAP_TXSEQ_UNEXPECTED;
4915 }
4916}
4917
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07004918static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
4919 struct sk_buff *skb, u8 event)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004920{
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07004921 /* Placeholder */
4922 return -ENOTSUPP;
4923}
4924
4925static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
4926 struct sk_buff *skb)
4927{
Mat Martineau4b51dae92012-05-17 20:53:37 -07004928 int err = 0;
4929
4930 BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
4931 chan->rx_state);
4932
4933 if (l2cap_classify_txseq(chan, control->txseq) ==
4934 L2CAP_TXSEQ_EXPECTED) {
4935 l2cap_pass_to_tx(chan, control);
4936
4937 BT_DBG("buffer_seq %d->%d", chan->buffer_seq,
4938 __next_seq(chan, chan->buffer_seq));
4939
4940 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
4941
4942 l2cap_reassemble_sdu(chan, skb, control);
4943 } else {
4944 if (chan->sdu) {
4945 kfree_skb(chan->sdu);
4946 chan->sdu = NULL;
4947 }
4948 chan->sdu_last_frag = NULL;
4949 chan->sdu_len = 0;
4950
4951 if (skb) {
4952 BT_DBG("Freeing %p", skb);
4953 kfree_skb(skb);
4954 }
4955 }
4956
4957 chan->last_acked_seq = control->txseq;
4958 chan->expected_tx_seq = __next_seq(chan, control->txseq);
4959
4960 return err;
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07004961}
4962
4963static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
4964{
4965 struct l2cap_ctrl *control = &bt_cb(skb)->control;
4966 u16 len;
4967 u8 event;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004968
Mat Martineaub76bbd62012-04-11 10:48:43 -07004969 __unpack_control(chan, skb);
4970
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004971 len = skb->len;
4972
4973 /*
4974 * We can just drop the corrupted I-frame here.
4975 * Receiver will miss it and start proper recovery
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07004976 * procedures and ask for retransmission.
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004977 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004978 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004979 goto drop;
4980
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07004981 if (!control->sframe && control->sar == L2CAP_SAR_START)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004982 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004983
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004984 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004985 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004986
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004987 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004988 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004989 goto drop;
4990 }
4991
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07004992 if (!control->sframe) {
4993 int err;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004994
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07004995 BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
4996 control->sar, control->reqseq, control->final,
4997 control->txseq);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004998
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07004999 /* Validate F-bit - F=0 always valid, F=1 only
5000 * valid in TX WAIT_F
5001 */
5002 if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005003 goto drop;
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07005004
5005 if (chan->mode != L2CAP_MODE_STREAMING) {
5006 event = L2CAP_EV_RECV_IFRAME;
5007 err = l2cap_rx(chan, control, skb, event);
5008 } else {
5009 err = l2cap_stream_rx(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005010 }
5011
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07005012 if (err)
5013 l2cap_send_disconn_req(chan->conn, chan,
5014 ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005015 } else {
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07005016 const u8 rx_func_to_event[4] = {
5017 L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
5018 L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
5019 };
5020
5021 /* Only I-frames are expected in streaming mode */
5022 if (chan->mode == L2CAP_MODE_STREAMING)
5023 goto drop;
5024
5025 BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
5026 control->reqseq, control->final, control->poll,
5027 control->super);
5028
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005029 if (len != 0) {
5030 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03005031 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005032 goto drop;
5033 }
5034
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07005035 /* Validate F and P bits */
5036 if (control->final && (control->poll ||
5037 chan->tx_state != L2CAP_TX_STATE_WAIT_F))
5038 goto drop;
5039
5040 event = rx_func_to_event[control->super];
5041 if (l2cap_rx(chan, control, skb, event))
5042 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005043 }
5044
5045 return 0;
5046
5047drop:
5048 kfree_skb(skb);
5049 return 0;
5050}
5051
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
5053{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03005054 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005055
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03005056 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03005057 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005058 BT_DBG("unknown cid 0x%4.4x", cid);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02005059 /* Drop packet and return */
Dan Carpenter33790132012-02-28 09:52:46 +03005060 kfree_skb(skb);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02005061 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005062 }
5063
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03005064 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005065
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03005066 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005067 goto drop;
5068
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03005069 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03005070 case L2CAP_MODE_BASIC:
5071 /* If socket recv buffers overflows we drop data here
5072 * which is *bad* because L2CAP has to be reliable.
5073 * But we don't have any other choice. L2CAP doesn't
5074 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005075
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03005076 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03005077 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005078
Gustavo F. Padovan23070492011-05-16 17:57:22 -03005079 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03005080 goto done;
5081 break;
5082
5083 case L2CAP_MODE_ERTM:
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03005084 case L2CAP_MODE_STREAMING:
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07005085 l2cap_data_rcv(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03005086 goto done;
5087
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03005088 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03005089 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03005090 break;
5091 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005092
5093drop:
5094 kfree_skb(skb);
5095
5096done:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02005097 l2cap_chan_unlock(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +02005098
Linus Torvalds1da177e2005-04-16 15:20:36 -07005099 return 0;
5100}
5101
Al Viro8e036fc2007-07-29 00:16:36 -07005102static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005103{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005104 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005105
Ido Yarivc2287682012-04-20 15:46:07 -03005106 chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005107 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005108 goto drop;
5109
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02005110 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005111
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03005112 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005113 goto drop;
5114
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03005115 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005116 goto drop;
5117
Gustavo F. Padovan23070492011-05-16 17:57:22 -03005118 if (!chan->ops->recv(chan->data, skb))
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02005119 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005120
5121drop:
5122 kfree_skb(skb);
5123
Linus Torvalds1da177e2005-04-16 15:20:36 -07005124 return 0;
5125}
5126
Andrei Emeltchenkod9b88702012-03-12 12:13:08 +02005127static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid,
5128 struct sk_buff *skb)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03005129{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005130 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03005131
Ido Yarivc2287682012-04-20 15:46:07 -03005132 chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005133 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03005134 goto drop;
5135
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02005136 BT_DBG("chan %p, len %d", chan, skb->len);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03005137
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03005138 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03005139 goto drop;
5140
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03005141 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03005142 goto drop;
5143
Gustavo F. Padovan23070492011-05-16 17:57:22 -03005144 if (!chan->ops->recv(chan->data, skb))
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02005145 return 0;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03005146
5147drop:
5148 kfree_skb(skb);
5149
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03005150 return 0;
5151}
5152
Linus Torvalds1da177e2005-04-16 15:20:36 -07005153static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
5154{
5155 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07005156 u16 cid, len;
5157 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005158
5159 skb_pull(skb, L2CAP_HDR_SIZE);
5160 cid = __le16_to_cpu(lh->cid);
5161 len = __le16_to_cpu(lh->len);
5162
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03005163 if (len != skb->len) {
5164 kfree_skb(skb);
5165 return;
5166 }
5167
Linus Torvalds1da177e2005-04-16 15:20:36 -07005168 BT_DBG("len %d, cid 0x%4.4x", len, cid);
5169
5170 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02005171 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03005172 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07005173 l2cap_sig_channel(conn, skb);
5174 break;
5175
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03005176 case L2CAP_CID_CONN_LESS:
Andrei Emeltchenko097db762012-03-09 14:16:17 +02005177 psm = get_unaligned((__le16 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005178 skb_pull(skb, 2);
5179 l2cap_conless_channel(conn, psm, skb);
5180 break;
5181
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03005182 case L2CAP_CID_LE_DATA:
5183 l2cap_att_channel(conn, cid, skb);
5184 break;
5185
Anderson Brigliab501d6a2011-06-07 18:46:31 -03005186 case L2CAP_CID_SMP:
5187 if (smp_sig_channel(conn, skb))
5188 l2cap_conn_del(conn->hcon, EACCES);
5189 break;
5190
Linus Torvalds1da177e2005-04-16 15:20:36 -07005191 default:
5192 l2cap_data_channel(conn, cid, skb);
5193 break;
5194 }
5195}
5196
5197/* ---- L2CAP interface with lower layer (HCI) ---- */
5198
Ulisses Furquim686ebf22011-12-21 10:11:33 -02005199int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005200{
5201 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005202 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005203
Linus Torvalds1da177e2005-04-16 15:20:36 -07005204 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
5205
5206 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005207 read_lock(&chan_list_lock);
5208 list_for_each_entry(c, &chan_list, global_l) {
5209 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03005210
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03005211 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005212 continue;
5213
5214 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01005215 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03005216 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01005217 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005218 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01005219 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
5220 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03005221 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01005222 lm2 |= HCI_LM_MASTER;
5223 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005224 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005225 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005226
5227 return exact ? lm1 : lm2;
5228}
5229
Ulisses Furquim686ebf22011-12-21 10:11:33 -02005230int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005231{
Marcel Holtmann01394182006-07-03 10:02:46 +02005232 struct l2cap_conn *conn;
5233
Linus Torvalds1da177e2005-04-16 15:20:36 -07005234 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
5235
Linus Torvalds1da177e2005-04-16 15:20:36 -07005236 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005237 conn = l2cap_conn_add(hcon, status);
5238 if (conn)
5239 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02005240 } else
Joe Perchese1750722011-06-29 18:18:29 -07005241 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005242
5243 return 0;
5244}
5245
Ulisses Furquim686ebf22011-12-21 10:11:33 -02005246int l2cap_disconn_ind(struct hci_conn *hcon)
Marcel Holtmann2950f212009-02-12 14:02:50 +01005247{
5248 struct l2cap_conn *conn = hcon->l2cap_data;
5249
5250 BT_DBG("hcon %p", hcon);
5251
Ulisses Furquim686ebf22011-12-21 10:11:33 -02005252 if (!conn)
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02005253 return HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01005254 return conn->disc_reason;
5255}
5256
Ulisses Furquim686ebf22011-12-21 10:11:33 -02005257int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005258{
5259 BT_DBG("hcon %p reason %d", hcon, reason);
5260
Joe Perchese1750722011-06-29 18:18:29 -07005261 l2cap_conn_del(hcon, bt_to_errno(reason));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005262 return 0;
5263}
5264
Gustavo F. Padovan43434782011-04-12 18:31:57 -03005265static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01005266{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03005267 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01005268 return;
5269
Marcel Holtmannf62e4322009-01-15 21:58:44 +01005270 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03005271 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08005272 __set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03005273 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03005274 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01005275 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03005276 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03005277 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01005278 }
5279}
5280
Ulisses Furquim686ebf22011-12-21 10:11:33 -02005281int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005282{
Marcel Holtmann40be4922008-07-14 20:13:50 +02005283 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03005284 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005285
Marcel Holtmann01394182006-07-03 10:02:46 +02005286 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005287 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02005288
Linus Torvalds1da177e2005-04-16 15:20:36 -07005289 BT_DBG("conn %p", conn);
5290
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03005291 if (hcon->type == LE_LINK) {
Hemant Gupta35d4adcc2012-04-18 14:46:26 +05305292 if (!status && encrypt)
5293 smp_distribute_keys(conn, 0);
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02005294 cancel_delayed_work(&conn->security_timer);
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03005295 }
5296
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02005297 mutex_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005298
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02005299 list_for_each_entry(chan, &conn->chan_l, list) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02005300 l2cap_chan_lock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005301
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03005302 BT_DBG("chan->scid %d", chan->scid);
5303
5304 if (chan->scid == L2CAP_CID_LE_DATA) {
5305 if (!status && encrypt) {
5306 chan->sec_level = hcon->sec_level;
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02005307 l2cap_chan_ready(chan);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03005308 }
5309
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02005310 l2cap_chan_unlock(chan);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03005311 continue;
5312 }
5313
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03005314 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02005315 l2cap_chan_unlock(chan);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01005316 continue;
5317 }
5318
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03005319 if (!status && (chan->state == BT_CONNECTED ||
5320 chan->state == BT_CONFIG)) {
Gustavo Padovana7d77232012-05-13 03:20:07 -03005321 struct sock *sk = chan->sk;
5322
Gustavo Padovanc5daa682012-05-16 12:17:10 -03005323 clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
Gustavo Padovana7d77232012-05-13 03:20:07 -03005324 sk->sk_state_change(sk);
5325
Gustavo F. Padovan43434782011-04-12 18:31:57 -03005326 l2cap_check_encryption(chan, encrypt);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02005327 l2cap_chan_unlock(chan);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02005328 continue;
5329 }
5330
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03005331 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02005332 if (!status) {
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +02005333 l2cap_send_conn_req(chan);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02005334 } else {
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08005335 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02005336 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03005337 } else if (chan->state == BT_CONNECT2) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02005338 struct sock *sk = chan->sk;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02005339 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03005340 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02005341
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02005342 lock_sock(sk);
5343
Marcel Holtmannb1235d72008-07-14 20:13:54 +02005344 if (!status) {
Gustavo Padovanc5daa682012-05-16 12:17:10 -03005345 if (test_bit(BT_SK_DEFER_SETUP,
5346 &bt_sk(sk)->flags)) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03005347 struct sock *parent = bt_sk(sk)->parent;
5348 res = L2CAP_CR_PEND;
5349 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00005350 if (parent)
5351 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03005352 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02005353 __l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03005354 res = L2CAP_CR_SUCCESS;
5355 stat = L2CAP_CS_NO_INFO;
5356 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02005357 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02005358 __l2cap_state_change(chan, BT_DISCONN);
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08005359 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03005360 res = L2CAP_CR_SEC_BLOCK;
5361 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02005362 }
5363
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02005364 release_sock(sk);
5365
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03005366 rsp.scid = cpu_to_le16(chan->dcid);
5367 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03005368 rsp.result = cpu_to_le16(res);
5369 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03005370 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
5371 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005372 }
5373
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02005374 l2cap_chan_unlock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005375 }
5376
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02005377 mutex_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02005378
Linus Torvalds1da177e2005-04-16 15:20:36 -07005379 return 0;
5380}
5381
Ulisses Furquim686ebf22011-12-21 10:11:33 -02005382int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005383{
5384 struct l2cap_conn *conn = hcon->l2cap_data;
5385
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02005386 if (!conn)
5387 conn = l2cap_conn_add(hcon, 0);
5388
5389 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005390 goto drop;
5391
5392 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
5393
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02005394 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005395 struct l2cap_hdr *hdr;
5396 int len;
5397
5398 if (conn->rx_len) {
5399 BT_ERR("Unexpected start frame (len %d)", skb->len);
5400 kfree_skb(conn->rx_skb);
5401 conn->rx_skb = NULL;
5402 conn->rx_len = 0;
5403 l2cap_conn_unreliable(conn, ECOMM);
5404 }
5405
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03005406 /* Start fragment always begin with Basic L2CAP header */
5407 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005408 BT_ERR("Frame is too short (len %d)", skb->len);
5409 l2cap_conn_unreliable(conn, ECOMM);
5410 goto drop;
5411 }
5412
5413 hdr = (struct l2cap_hdr *) skb->data;
5414 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
5415
5416 if (len == skb->len) {
5417 /* Complete frame received */
5418 l2cap_recv_frame(conn, skb);
5419 return 0;
5420 }
5421
5422 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
5423
5424 if (skb->len > len) {
5425 BT_ERR("Frame is too long (len %d, expected len %d)",
5426 skb->len, len);
5427 l2cap_conn_unreliable(conn, ECOMM);
5428 goto drop;
5429 }
5430
5431 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03005432 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
5433 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005434 goto drop;
5435
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03005436 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01005437 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005438 conn->rx_len = len - skb->len;
5439 } else {
5440 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
5441
5442 if (!conn->rx_len) {
5443 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
5444 l2cap_conn_unreliable(conn, ECOMM);
5445 goto drop;
5446 }
5447
5448 if (skb->len > conn->rx_len) {
5449 BT_ERR("Fragment is too long (len %d, expected %d)",
5450 skb->len, conn->rx_len);
5451 kfree_skb(conn->rx_skb);
5452 conn->rx_skb = NULL;
5453 conn->rx_len = 0;
5454 l2cap_conn_unreliable(conn, ECOMM);
5455 goto drop;
5456 }
5457
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03005458 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01005459 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005460 conn->rx_len -= skb->len;
5461
5462 if (!conn->rx_len) {
5463 /* Complete frame received */
5464 l2cap_recv_frame(conn, conn->rx_skb);
5465 conn->rx_skb = NULL;
5466 }
5467 }
5468
5469drop:
5470 kfree_skb(skb);
5471 return 0;
5472}
5473
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005474static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005475{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005476 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005477
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02005478 read_lock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005479
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005480 list_for_each_entry(c, &chan_list, global_l) {
5481 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005482
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02005483 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 +01005484 batostr(&bt_sk(sk)->src),
5485 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03005486 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005487 c->scid, c->dcid, c->imtu, c->omtu,
5488 c->sec_level, c->mode);
Andrei Emeltchenko61e1b4b2012-01-19 11:19:50 +02005489 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005490
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02005491 read_unlock(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08005492
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005493 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005494}
5495
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005496static int l2cap_debugfs_open(struct inode *inode, struct file *file)
5497{
5498 return single_open(file, l2cap_debugfs_show, inode->i_private);
5499}
5500
5501static const struct file_operations l2cap_debugfs_fops = {
5502 .open = l2cap_debugfs_open,
5503 .read = seq_read,
5504 .llseek = seq_lseek,
5505 .release = single_release,
5506};
5507
5508static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005509
Gustavo F. Padovan64274512011-02-07 20:08:52 -02005510int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005511{
5512 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08005513
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02005514 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005515 if (err < 0)
5516 return err;
5517
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005518 if (bt_debugfs) {
5519 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
5520 bt_debugfs, NULL, &l2cap_debugfs_fops);
5521 if (!l2cap_debugfs)
5522 BT_ERR("Failed to create L2CAP debug file");
5523 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005524
Linus Torvalds1da177e2005-04-16 15:20:36 -07005525 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005526}
5527
Gustavo F. Padovan64274512011-02-07 20:08:52 -02005528void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005529{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005530 debugfs_remove(l2cap_debugfs);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02005531 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005532}
5533
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03005534module_param(disable_ertm, bool, 0644);
5535MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");