blob: 08efc256c9313382bbc666335ea645670eab087e [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
Marcel Holtmannaef7d972010-03-21 05:27:45 +010033#include <linux/debugfs.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030034#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
36#include <net/bluetooth/bluetooth.h>
37#include <net/bluetooth/hci_core.h>
38#include <net/bluetooth/l2cap.h>
Anderson Brigliab501d6a2011-06-07 18:46:31 -030039#include <net/bluetooth/smp.h>
Andrei Emeltchenko97e8e892012-05-29 13:59:17 +030040#include <net/bluetooth/a2mp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
Mat Martineaud1de6d42012-05-17 20:53:55 -070042bool disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020043
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070044static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Mat Martineau50a147c2011-11-02 16:18:34 -070045static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
Johannes Bergb5ad8b72011-06-01 08:54:45 +020047static LIST_HEAD(chan_list);
48static DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
Linus Torvalds1da177e2005-04-16 15:20:36 -070050static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
Gustavo Padovan2d792812012-10-06 10:07:01 +010051 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030052static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
Gustavo Padovan2d792812012-10-06 10:07:01 +010053 void *data);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -030054static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030055static void l2cap_send_disconn_req(struct l2cap_conn *conn,
Gustavo Padovanc5daa682012-05-16 12:17:10 -030056 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
Gustavo Padovand6603662012-05-21 13:58:22 -030058static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
Gustavo Padovan2d792812012-10-06 10:07:01 +010059 struct sk_buff_head *skbs, u8 event);
Mat Martineau608bcc62012-05-17 20:53:32 -070060
Marcel Holtmann01394182006-07-03 10:02:46 +020061/* ---- L2CAP channels ---- */
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -030062
Gustavo Padovan2d792812012-10-06 10:07:01 +010063static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
64 u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020065{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020066 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030067
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020068 list_for_each_entry(c, &conn->chan_l, list) {
69 if (c->dcid == cid)
70 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020071 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020072 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +020073}
74
Gustavo Padovan2d792812012-10-06 10:07:01 +010075static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn,
76 u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020077{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020078 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030079
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020080 list_for_each_entry(c, &conn->chan_l, list) {
81 if (c->scid == cid)
82 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020083 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020084 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +020085}
86
87/* Find channel with given SCID.
Mat Martineauef191ad2012-05-02 09:42:00 -070088 * Returns locked channel. */
Gustavo Padovan2d792812012-10-06 10:07:01 +010089static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn,
90 u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020091{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030092 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030093
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020094 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030095 c = __l2cap_get_chan_by_scid(conn, cid);
Mat Martineauef191ad2012-05-02 09:42:00 -070096 if (c)
97 l2cap_chan_lock(c);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020098 mutex_unlock(&conn->chan_lock);
99
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300100 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200101}
102
Gustavo Padovan2d792812012-10-06 10:07:01 +0100103static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn,
104 u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200105{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200106 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300107
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200108 list_for_each_entry(c, &conn->chan_l, list) {
109 if (c->ident == ident)
110 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200111 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200112 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200113}
114
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300115static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300116{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300117 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300118
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300119 list_for_each_entry(c, &chan_list, global_l) {
120 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Szymon Janc250938c2011-11-16 09:32:22 +0100121 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300122 }
Szymon Janc250938c2011-11-16 09:32:22 +0100123 return NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300124}
125
126int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
127{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300128 int err;
129
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200130 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300131
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300132 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300133 err = -EADDRINUSE;
134 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300135 }
136
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300137 if (psm) {
138 chan->psm = psm;
139 chan->sport = psm;
140 err = 0;
141 } else {
142 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300143
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300144 err = -EINVAL;
145 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300146 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300147 chan->psm = cpu_to_le16(p);
148 chan->sport = cpu_to_le16(p);
149 err = 0;
150 break;
151 }
152 }
153
154done:
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200155 write_unlock(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300156 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300157}
158
159int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
160{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200161 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300162
163 chan->scid = scid;
164
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200165 write_unlock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300166
167 return 0;
168}
169
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300170static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200171{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300172 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200173
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300174 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300175 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200176 return cid;
177 }
178
179 return 0;
180}
181
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200182static void __l2cap_state_change(struct l2cap_chan *chan, int state)
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300183{
Andrei Emeltchenko42d2d872012-02-17 11:40:57 +0200184 BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
Gustavo Padovan2d792812012-10-06 10:07:01 +0100185 state_to_string(state));
Gustavo F. Padovanbadaaa02011-11-23 20:11:46 -0200186
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300187 chan->state = state;
Gustavo Padovan80b98022012-05-27 22:27:51 -0300188 chan->ops->state_change(chan, state);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300189}
190
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200191static void l2cap_state_change(struct l2cap_chan *chan, int state)
192{
193 struct sock *sk = chan->sk;
194
195 lock_sock(sk);
196 __l2cap_state_change(chan, state);
197 release_sock(sk);
198}
199
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +0200200static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err)
201{
202 struct sock *sk = chan->sk;
203
204 sk->sk_err = err;
205}
206
207static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
208{
209 struct sock *sk = chan->sk;
210
211 lock_sock(sk);
212 __l2cap_chan_set_err(chan, err);
213 release_sock(sk);
214}
215
Mat Martineau4239d162012-05-17 20:53:49 -0700216static void __set_retrans_timer(struct l2cap_chan *chan)
217{
218 if (!delayed_work_pending(&chan->monitor_timer) &&
219 chan->retrans_timeout) {
220 l2cap_set_timer(chan, &chan->retrans_timer,
221 msecs_to_jiffies(chan->retrans_timeout));
222 }
223}
224
225static void __set_monitor_timer(struct l2cap_chan *chan)
226{
227 __clear_retrans_timer(chan);
228 if (chan->monitor_timeout) {
229 l2cap_set_timer(chan, &chan->monitor_timer,
230 msecs_to_jiffies(chan->monitor_timeout));
231 }
232}
233
Mat Martineau608bcc62012-05-17 20:53:32 -0700234static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head,
235 u16 seq)
236{
237 struct sk_buff *skb;
238
239 skb_queue_walk(head, skb) {
240 if (bt_cb(skb)->control.txseq == seq)
241 return skb;
242 }
243
244 return NULL;
245}
246
Mat Martineau3c588192012-04-11 10:48:42 -0700247/* ---- L2CAP sequence number lists ---- */
248
249/* For ERTM, ordered lists of sequence numbers must be tracked for
250 * SREJ requests that are received and for frames that are to be
251 * retransmitted. These seq_list functions implement a singly-linked
252 * list in an array, where membership in the list can also be checked
253 * in constant time. Items can also be added to the tail of the list
254 * and removed from the head in constant time, without further memory
255 * allocs or frees.
256 */
257
258static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
259{
260 size_t alloc_size, i;
261
262 /* Allocated size is a power of 2 to map sequence numbers
263 * (which may be up to 14 bits) in to a smaller array that is
264 * sized for the negotiated ERTM transmit windows.
265 */
266 alloc_size = roundup_pow_of_two(size);
267
268 seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL);
269 if (!seq_list->list)
270 return -ENOMEM;
271
272 seq_list->mask = alloc_size - 1;
273 seq_list->head = L2CAP_SEQ_LIST_CLEAR;
274 seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
275 for (i = 0; i < alloc_size; i++)
276 seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
277
278 return 0;
279}
280
281static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
282{
283 kfree(seq_list->list);
284}
285
286static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
287 u16 seq)
288{
289 /* Constant-time check for list membership */
290 return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
291}
292
293static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq)
294{
295 u16 mask = seq_list->mask;
296
297 if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) {
298 /* In case someone tries to pop the head of an empty list */
299 return L2CAP_SEQ_LIST_CLEAR;
300 } else if (seq_list->head == seq) {
301 /* Head can be removed in constant time */
302 seq_list->head = seq_list->list[seq & mask];
303 seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
304
305 if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
306 seq_list->head = L2CAP_SEQ_LIST_CLEAR;
307 seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
308 }
309 } else {
310 /* Walk the list to find the sequence number */
311 u16 prev = seq_list->head;
312 while (seq_list->list[prev & mask] != seq) {
313 prev = seq_list->list[prev & mask];
314 if (prev == L2CAP_SEQ_LIST_TAIL)
315 return L2CAP_SEQ_LIST_CLEAR;
316 }
317
318 /* Unlink the number from the list and clear it */
319 seq_list->list[prev & mask] = seq_list->list[seq & mask];
320 seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
321 if (seq_list->tail == seq)
322 seq_list->tail = prev;
323 }
324 return seq;
325}
326
327static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
328{
329 /* Remove the head in constant time */
330 return l2cap_seq_list_remove(seq_list, seq_list->head);
331}
332
333static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
334{
Gustavo Padovanf522ae32012-05-09 18:28:00 -0300335 u16 i;
Mat Martineau3c588192012-04-11 10:48:42 -0700336
Gustavo Padovanf522ae32012-05-09 18:28:00 -0300337 if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
338 return;
339
340 for (i = 0; i <= seq_list->mask; i++)
341 seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
342
343 seq_list->head = L2CAP_SEQ_LIST_CLEAR;
344 seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
Mat Martineau3c588192012-04-11 10:48:42 -0700345}
346
347static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
348{
349 u16 mask = seq_list->mask;
350
351 /* All appends happen in constant time */
352
Gustavo Padovanf522ae32012-05-09 18:28:00 -0300353 if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
354 return;
Mat Martineau3c588192012-04-11 10:48:42 -0700355
Gustavo Padovanf522ae32012-05-09 18:28:00 -0300356 if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
357 seq_list->head = seq;
358 else
359 seq_list->list[seq_list->tail & mask] = seq;
360
361 seq_list->tail = seq;
362 seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
Mat Martineau3c588192012-04-11 10:48:42 -0700363}
364
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300365static void l2cap_chan_timeout(struct work_struct *work)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300366{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300367 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
Gustavo Padovan2d792812012-10-06 10:07:01 +0100368 chan_timer.work);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200369 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300370 int reason;
371
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200372 BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300373
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200374 mutex_lock(&conn->chan_lock);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200375 l2cap_chan_lock(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300376
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300377 if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300378 reason = ECONNREFUSED;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300379 else if (chan->state == BT_CONNECT &&
Gustavo Padovan2d792812012-10-06 10:07:01 +0100380 chan->sec_level != BT_SECURITY_SDP)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300381 reason = ECONNREFUSED;
382 else
383 reason = ETIMEDOUT;
384
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300385 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300386
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200387 l2cap_chan_unlock(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300388
Gustavo Padovan80b98022012-05-27 22:27:51 -0300389 chan->ops->close(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200390 mutex_unlock(&conn->chan_lock);
391
Ulisses Furquim371fd832011-12-21 20:02:36 -0200392 l2cap_chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300393}
394
Gustavo Padovaneef1d9b2012-03-25 13:59:16 -0300395struct l2cap_chan *l2cap_chan_create(void)
Marcel Holtmann01394182006-07-03 10:02:46 +0200396{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300397 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200398
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300399 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
400 if (!chan)
401 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200402
Andrei Emeltchenkoc03b3552012-02-21 12:54:56 +0200403 mutex_init(&chan->lock);
404
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200405 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300406 list_add(&chan->global_l, &chan_list);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200407 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300408
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300409 INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300410
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300411 chan->state = BT_OPEN;
412
Syam Sidhardhan144ad332012-07-27 23:51:21 +0530413 kref_init(&chan->kref);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300414
Mat Martineau28270112012-05-17 21:14:09 -0700415 /* This flag is cleared in l2cap_chan_ready() */
416 set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
417
Gustavo Padovaneef1d9b2012-03-25 13:59:16 -0300418 BT_DBG("chan %p", chan);
Szymon Jancabc545b2011-11-03 16:05:44 +0100419
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300420 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200421}
422
Syam Sidhardhan144ad332012-07-27 23:51:21 +0530423static void l2cap_chan_destroy(struct kref *kref)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300424{
Syam Sidhardhan144ad332012-07-27 23:51:21 +0530425 struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref);
426
Jaganath Kanakkassery4af66c62012-07-13 18:17:55 +0530427 BT_DBG("chan %p", chan);
428
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200429 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300430 list_del(&chan->global_l);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200431 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300432
Jaganath Kanakkassery4af66c62012-07-13 18:17:55 +0530433 kfree(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300434}
435
Jaganath Kanakkassery30648372012-07-13 18:17:54 +0530436void l2cap_chan_hold(struct l2cap_chan *c)
437{
Syam Sidhardhan144ad332012-07-27 23:51:21 +0530438 BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount));
Jaganath Kanakkassery30648372012-07-13 18:17:54 +0530439
Syam Sidhardhan144ad332012-07-27 23:51:21 +0530440 kref_get(&c->kref);
Jaganath Kanakkassery30648372012-07-13 18:17:54 +0530441}
442
443void l2cap_chan_put(struct l2cap_chan *c)
444{
Syam Sidhardhan144ad332012-07-27 23:51:21 +0530445 BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount));
Jaganath Kanakkassery30648372012-07-13 18:17:54 +0530446
Syam Sidhardhan144ad332012-07-27 23:51:21 +0530447 kref_put(&c->kref, l2cap_chan_destroy);
Jaganath Kanakkassery30648372012-07-13 18:17:54 +0530448}
449
Andrei Emeltchenkobd4b1652012-03-28 16:31:25 +0300450void l2cap_chan_set_defaults(struct l2cap_chan *chan)
451{
452 chan->fcs = L2CAP_FCS_CRC16;
453 chan->max_tx = L2CAP_DEFAULT_MAX_TX;
454 chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
455 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
Mat Martineauc20f8e32012-07-10 05:47:07 -0700456 chan->ack_win = L2CAP_DEFAULT_TX_WINDOW;
Andrei Emeltchenkobd4b1652012-03-28 16:31:25 +0300457 chan->sec_level = BT_SECURITY_LOW;
458
459 set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
460}
461
Andrei Emeltchenko93c3e8f2012-09-27 17:26:16 +0300462void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200463{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300464 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Andrei Emeltchenko097db762012-03-09 14:16:17 +0200465 __le16_to_cpu(chan->psm), chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200466
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +0200467 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +0100468
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300469 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200470
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200471 switch (chan->chan_type) {
472 case L2CAP_CHAN_CONN_ORIENTED:
Ville Tervob62f3282011-02-10 22:38:50 -0300473 if (conn->hcon->type == LE_LINK) {
474 /* LE connection */
Andre Guedes6fcb06a2012-05-31 17:01:33 -0300475 chan->omtu = L2CAP_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300476 chan->scid = L2CAP_CID_LE_DATA;
477 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300478 } else {
479 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300480 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300481 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300482 }
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200483 break;
484
485 case L2CAP_CHAN_CONN_LESS:
Marcel Holtmann01394182006-07-03 10:02:46 +0200486 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300487 chan->scid = L2CAP_CID_CONN_LESS;
488 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300489 chan->omtu = L2CAP_DEFAULT_MTU;
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200490 break;
491
Andrei Emeltchenko416fa752012-05-29 13:59:16 +0300492 case L2CAP_CHAN_CONN_FIX_A2MP:
493 chan->scid = L2CAP_CID_A2MP;
494 chan->dcid = L2CAP_CID_A2MP;
495 chan->omtu = L2CAP_A2MP_DEFAULT_MTU;
496 chan->imtu = L2CAP_A2MP_DEFAULT_MTU;
497 break;
498
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200499 default:
Marcel Holtmann01394182006-07-03 10:02:46 +0200500 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300501 chan->scid = L2CAP_CID_SIGNALING;
502 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300503 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200504 }
505
Andrei Emeltchenko8f7975b2011-10-13 16:18:54 +0300506 chan->local_id = L2CAP_BESTEFFORT_ID;
507 chan->local_stype = L2CAP_SERV_BESTEFFORT;
508 chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
509 chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
510 chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
Andrei Emeltchenko8936fa62012-10-08 11:14:41 +0300511 chan->local_flush_to = L2CAP_EFS_DEFAULT_FLUSH_TO;
Andrei Emeltchenko8f7975b2011-10-13 16:18:54 +0300512
Ulisses Furquim371fd832011-12-21 20:02:36 -0200513 l2cap_chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300514
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200515 list_add(&chan->list, &conn->chan_l);
Andrei Emeltchenko643162a2012-02-22 17:11:55 +0200516}
517
Andrei Emeltchenko466f8002012-05-29 13:59:01 +0300518void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Andrei Emeltchenko643162a2012-02-22 17:11:55 +0200519{
520 mutex_lock(&conn->chan_lock);
521 __l2cap_chan_add(conn, chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200522 mutex_unlock(&conn->chan_lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200523}
524
Andrei Emeltchenko466f8002012-05-29 13:59:01 +0300525void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200526{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300527 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200528
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300529 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200530
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300531 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200532
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900533 if (conn) {
Andrei Emeltchenko56f60982012-10-15 11:58:44 +0300534 struct amp_mgr *mgr = conn->hcon->amp_mgr;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300535 /* Delete from channel list */
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200536 list_del(&chan->list);
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200537
Ulisses Furquim371fd832011-12-21 20:02:36 -0200538 l2cap_chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300539
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300540 chan->conn = NULL;
Andrei Emeltchenko3cabbfd2012-05-31 11:01:37 +0300541
542 if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP)
543 hci_conn_put(conn->hcon);
Andrei Emeltchenko56f60982012-10-15 11:58:44 +0300544
545 if (mgr && mgr->bredr_chan == chan)
546 mgr->bredr_chan = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200547 }
548
Gustavo Padovanb699ec02012-10-06 11:51:54 +0100549 chan->ops->teardown(chan, err);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200550
Mat Martineau28270112012-05-17 21:14:09 -0700551 if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300552 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300553
Gustavo Padovanee556f62012-05-18 20:22:38 -0300554 switch(chan->mode) {
555 case L2CAP_MODE_BASIC:
556 break;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300557
Gustavo Padovanee556f62012-05-18 20:22:38 -0300558 case L2CAP_MODE_ERTM:
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300559 __clear_retrans_timer(chan);
560 __clear_monitor_timer(chan);
561 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300562
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300563 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300564
Mat Martineau3c588192012-04-11 10:48:42 -0700565 l2cap_seq_list_free(&chan->srej_list);
566 l2cap_seq_list_free(&chan->retrans_list);
Gustavo Padovanee556f62012-05-18 20:22:38 -0300567
568 /* fall through */
569
570 case L2CAP_MODE_STREAMING:
571 skb_queue_purge(&chan->tx_q);
572 break;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300573 }
Gustavo Padovanee556f62012-05-18 20:22:38 -0300574
575 return;
Marcel Holtmann01394182006-07-03 10:02:46 +0200576}
577
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300578void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300579{
580 struct l2cap_conn *conn = chan->conn;
581 struct sock *sk = chan->sk;
582
Gustavo Padovan2d792812012-10-06 10:07:01 +0100583 BT_DBG("chan %p state %s sk %p", chan, state_to_string(chan->state),
584 sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300585
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300586 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300587 case BT_LISTEN:
Gustavo Padovanb699ec02012-10-06 11:51:54 +0100588 chan->ops->teardown(chan, 0);
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 Padovan2d792812012-10-06 10:07:01 +0100594 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 Padovan2d792812012-10-06 10:07:01 +0100603 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300604 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);
Andrei Emeltchenkoac734982012-05-24 15:42:51 +0300616 rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300617 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
Gustavo Padovan2d792812012-10-06 10:07:01 +0100618 sizeof(rsp), &rsp);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300619 }
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:
Gustavo Padovanb699ec02012-10-06 11:51:54 +0100630 chan->ops->teardown(chan, 0);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300631 break;
632 }
633}
634
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300635static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530636{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300637 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300638 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530639 case BT_SECURITY_HIGH:
640 return HCI_AT_DEDICATED_BONDING_MITM;
641 case BT_SECURITY_MEDIUM:
642 return HCI_AT_DEDICATED_BONDING;
643 default:
644 return HCI_AT_NO_BONDING;
645 }
Andrei Emeltchenko2983fd62012-05-24 15:42:50 +0300646 } else if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300647 if (chan->sec_level == BT_SECURITY_LOW)
648 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530649
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300650 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530651 return HCI_AT_NO_BONDING_MITM;
652 else
653 return HCI_AT_NO_BONDING;
654 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300655 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530656 case BT_SECURITY_HIGH:
657 return HCI_AT_GENERAL_BONDING_MITM;
658 case BT_SECURITY_MEDIUM:
659 return HCI_AT_GENERAL_BONDING;
660 default:
661 return HCI_AT_NO_BONDING;
662 }
663 }
664}
665
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200666/* Service level security */
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200667int l2cap_chan_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200668{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300669 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100670 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200671
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300672 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100673
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300674 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200675}
676
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200677static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200678{
679 u8 id;
680
681 /* Get next available identificator.
682 * 1 - 128 are used by kernel.
683 * 129 - 199 are reserved.
684 * 200 - 254 are used by utilities like l2ping, etc.
685 */
686
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200687 spin_lock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200688
689 if (++conn->tx_ident > 128)
690 conn->tx_ident = 1;
691
692 id = conn->tx_ident;
693
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200694 spin_unlock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200695
696 return id;
697}
698
Gustavo Padovan2d792812012-10-06 10:07:01 +0100699static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
700 void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200701{
702 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200703 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200704
705 BT_DBG("code 0x%2.2x", code);
706
707 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300708 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200709
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200710 if (lmp_no_flush_capable(conn->hcon->hdev))
711 flags = ACL_START_NO_FLUSH;
712 else
713 flags = ACL_START;
714
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700715 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +0200716 skb->priority = HCI_PRIO_MAX;
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700717
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200718 hci_send_acl(conn->hchan, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200719}
720
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200721static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
722{
723 struct hci_conn *hcon = chan->conn->hcon;
724 u16 flags;
725
726 BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
Gustavo Padovan2d792812012-10-06 10:07:01 +0100727 skb->priority);
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200728
729 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
Gustavo Padovan2d792812012-10-06 10:07:01 +0100730 lmp_no_flush_capable(hcon->hdev))
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200731 flags = ACL_START_NO_FLUSH;
732 else
733 flags = ACL_START;
734
735 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
736 hci_send_acl(chan->conn->hchan, skb, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737}
738
Mat Martineaub5c6aae2012-04-25 16:36:15 -0700739static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
740{
741 control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
742 control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
743
744 if (enh & L2CAP_CTRL_FRAME_TYPE) {
745 /* S-Frame */
746 control->sframe = 1;
747 control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
748 control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
749
750 control->sar = 0;
751 control->txseq = 0;
752 } else {
753 /* I-Frame */
754 control->sframe = 0;
755 control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
756 control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
757
758 control->poll = 0;
759 control->super = 0;
760 }
761}
762
763static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
764{
765 control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
766 control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
767
768 if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
769 /* S-Frame */
770 control->sframe = 1;
771 control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
772 control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
773
774 control->sar = 0;
775 control->txseq = 0;
776 } else {
777 /* I-Frame */
778 control->sframe = 0;
779 control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
780 control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
781
782 control->poll = 0;
783 control->super = 0;
784 }
785}
786
787static inline void __unpack_control(struct l2cap_chan *chan,
788 struct sk_buff *skb)
789{
790 if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
791 __unpack_extended_control(get_unaligned_le32(skb->data),
792 &bt_cb(skb)->control);
Mat Martineaucec8ab6e2012-05-17 20:53:36 -0700793 skb_pull(skb, L2CAP_EXT_CTRL_SIZE);
Mat Martineaub5c6aae2012-04-25 16:36:15 -0700794 } else {
795 __unpack_enhanced_control(get_unaligned_le16(skb->data),
796 &bt_cb(skb)->control);
Mat Martineaucec8ab6e2012-05-17 20:53:36 -0700797 skb_pull(skb, L2CAP_ENH_CTRL_SIZE);
Mat Martineaub5c6aae2012-04-25 16:36:15 -0700798 }
799}
800
801static u32 __pack_extended_control(struct l2cap_ctrl *control)
802{
803 u32 packed;
804
805 packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
806 packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
807
808 if (control->sframe) {
809 packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
810 packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
811 packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
812 } else {
813 packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
814 packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
815 }
816
817 return packed;
818}
819
820static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
821{
822 u16 packed;
823
824 packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
825 packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
826
827 if (control->sframe) {
828 packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
829 packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
830 packed |= L2CAP_CTRL_FRAME_TYPE;
831 } else {
832 packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
833 packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
834 }
835
836 return packed;
837}
838
839static inline void __pack_control(struct l2cap_chan *chan,
840 struct l2cap_ctrl *control,
841 struct sk_buff *skb)
842{
843 if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
844 put_unaligned_le32(__pack_extended_control(control),
845 skb->data + L2CAP_HDR_SIZE);
846 } else {
847 put_unaligned_le16(__pack_enhanced_control(control),
848 skb->data + L2CAP_HDR_SIZE);
849 }
850}
851
Gustavo Padovanba7aa642012-05-29 13:29:16 -0300852static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan)
853{
854 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
855 return L2CAP_EXT_HDR_SIZE;
856 else
857 return L2CAP_ENH_HDR_SIZE;
858}
859
Mat Martineaua67d7f62012-05-17 20:53:35 -0700860static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
861 u32 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300862{
863 struct sk_buff *skb;
864 struct l2cap_hdr *lh;
Gustavo Padovanba7aa642012-05-29 13:29:16 -0300865 int hlen = __ertm_hdr_size(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300866
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300867 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300868 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300869
Mat Martineaua67d7f62012-05-17 20:53:35 -0700870 skb = bt_skb_alloc(hlen, GFP_KERNEL);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300871
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300872 if (!skb)
Mat Martineaua67d7f62012-05-17 20:53:35 -0700873 return ERR_PTR(-ENOMEM);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300874
875 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300876 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300877 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300878
Mat Martineaua67d7f62012-05-17 20:53:35 -0700879 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
880 put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
881 else
882 put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300883
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300884 if (chan->fcs == L2CAP_FCS_CRC16) {
Mat Martineaua67d7f62012-05-17 20:53:35 -0700885 u16 fcs = crc16(0, (u8 *)skb->data, skb->len);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300886 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300887 }
888
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200889 skb->priority = HCI_PRIO_MAX;
Mat Martineaua67d7f62012-05-17 20:53:35 -0700890 return skb;
891}
892
893static void l2cap_send_sframe(struct l2cap_chan *chan,
894 struct l2cap_ctrl *control)
895{
896 struct sk_buff *skb;
897 u32 control_field;
898
899 BT_DBG("chan %p, control %p", chan, control);
900
901 if (!control->sframe)
902 return;
903
904 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
905 !control->poll)
906 control->final = 1;
907
908 if (control->super == L2CAP_SUPER_RR)
909 clear_bit(CONN_RNR_SENT, &chan->conn_state);
910 else if (control->super == L2CAP_SUPER_RNR)
911 set_bit(CONN_RNR_SENT, &chan->conn_state);
912
913 if (control->super != L2CAP_SUPER_SREJ) {
914 chan->last_acked_seq = control->reqseq;
915 __clear_ack_timer(chan);
916 }
917
918 BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq,
919 control->final, control->poll, control->super);
920
921 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
922 control_field = __pack_extended_control(control);
923 else
924 control_field = __pack_enhanced_control(control);
925
926 skb = l2cap_create_sframe_pdu(chan, control_field);
927 if (!IS_ERR(skb))
928 l2cap_do_send(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300929}
930
Mat Martineauc9e3d5e2012-05-17 20:53:48 -0700931static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300932{
Mat Martineauc9e3d5e2012-05-17 20:53:48 -0700933 struct l2cap_ctrl control;
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300934
Mat Martineauc9e3d5e2012-05-17 20:53:48 -0700935 BT_DBG("chan %p, poll %d", chan, poll);
936
937 memset(&control, 0, sizeof(control));
938 control.sframe = 1;
939 control.poll = poll;
940
941 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
942 control.super = L2CAP_SUPER_RNR;
943 else
944 control.super = L2CAP_SUPER_RR;
945
946 control.reqseq = chan->buffer_seq;
947 l2cap_send_sframe(chan, &control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300948}
949
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300950static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300951{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300952 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300953}
954
Andrei Emeltchenko93c3e8f2012-09-27 17:26:16 +0300955static bool __amp_capable(struct l2cap_chan *chan)
956{
957 struct l2cap_conn *conn = chan->conn;
958
959 if (enable_hs &&
960 chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED &&
961 conn->fixed_chan_mask & L2CAP_FC_A2MP)
962 return true;
963 else
964 return false;
965}
966
Andrei Emeltchenko2766be42012-09-27 17:26:21 +0300967void l2cap_send_conn_req(struct l2cap_chan *chan)
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +0200968{
969 struct l2cap_conn *conn = chan->conn;
970 struct l2cap_conn_req req;
971
972 req.scid = cpu_to_le16(chan->scid);
973 req.psm = chan->psm;
974
975 chan->ident = l2cap_get_ident(conn);
976
977 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
978
979 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
980}
981
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300982static void l2cap_chan_ready(struct l2cap_chan *chan)
983{
Mat Martineau28270112012-05-17 21:14:09 -0700984 /* This clears all conf flags, including CONF_NOT_COMPLETE */
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300985 chan->conf_state = 0;
986 __clear_chan_timer(chan);
987
Andrei Emeltchenko54a59aa2012-05-27 22:27:53 -0300988 chan->state = BT_CONNECTED;
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300989
Andrei Emeltchenkofd83e2c2012-05-30 09:55:32 +0300990 chan->ops->ready(chan);
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300991}
992
Andrei Emeltchenko93c3e8f2012-09-27 17:26:16 +0300993static void l2cap_start_connection(struct l2cap_chan *chan)
994{
995 if (__amp_capable(chan)) {
996 BT_DBG("chan %p AMP capable: discover AMPs", chan);
997 a2mp_discover_amp(chan);
998 } else {
999 l2cap_send_conn_req(chan);
1000 }
1001}
1002
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001003static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001004{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001005 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001006
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -03001007 if (conn->hcon->type == LE_LINK) {
1008 l2cap_chan_ready(chan);
1009 return;
1010 }
1011
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001012 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01001013 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
1014 return;
1015
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001016 if (l2cap_chan_check_security(chan) &&
Gustavo Padovan2d792812012-10-06 10:07:01 +01001017 __l2cap_no_conn_pending(chan)) {
Andrei Emeltchenko93c3e8f2012-09-27 17:26:16 +03001018 l2cap_start_connection(chan);
1019 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001020 } else {
1021 struct l2cap_info_req req;
Andrei Emeltchenkoac734982012-05-24 15:42:51 +03001022 req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001023
1024 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
1025 conn->info_ident = l2cap_get_ident(conn);
1026
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08001027 schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001028
Gustavo Padovan2d792812012-10-06 10:07:01 +01001029 l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
1030 sizeof(req), &req);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001031 }
1032}
1033
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -03001034static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
1035{
1036 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03001037 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -03001038 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
1039
1040 switch (mode) {
1041 case L2CAP_MODE_ERTM:
1042 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
1043 case L2CAP_MODE_STREAMING:
1044 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
1045 default:
1046 return 0x00;
1047 }
1048}
1049
Gustavo Padovan2d792812012-10-06 10:07:01 +01001050static void l2cap_send_disconn_req(struct l2cap_conn *conn,
1051 struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -03001052{
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001053 struct sock *sk = chan->sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -03001054 struct l2cap_disconn_req req;
1055
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001056 if (!conn)
1057 return;
1058
Andrei Emeltchenkoaad3d0e2012-09-06 15:05:42 +03001059 if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001060 __clear_retrans_timer(chan);
1061 __clear_monitor_timer(chan);
1062 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001063 }
1064
Andrei Emeltchenko416fa752012-05-29 13:59:16 +03001065 if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
Gustavo Padovand1177732012-10-06 11:47:38 +01001066 l2cap_state_change(chan, BT_DISCONN);
Andrei Emeltchenko416fa752012-05-29 13:59:16 +03001067 return;
1068 }
1069
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001070 req.dcid = cpu_to_le16(chan->dcid);
1071 req.scid = cpu_to_le16(chan->scid);
Gustavo Padovan2d792812012-10-06 10:07:01 +01001072 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ,
1073 sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001074
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001075 lock_sock(sk);
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001076 __l2cap_state_change(chan, BT_DISCONN);
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +02001077 __l2cap_chan_set_err(chan, err);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001078 release_sock(sk);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -03001079}
1080
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001082static void l2cap_conn_start(struct l2cap_conn *conn)
1083{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001084 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001085
1086 BT_DBG("conn %p", conn);
1087
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001088 mutex_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001089
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001090 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001091 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001092
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001093 l2cap_chan_lock(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001094
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001095 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001096 l2cap_chan_unlock(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001097 continue;
1098 }
1099
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001100 if (chan->state == BT_CONNECT) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001101 if (!l2cap_chan_check_security(chan) ||
Gustavo Padovan2d792812012-10-06 10:07:01 +01001102 !__l2cap_no_conn_pending(chan)) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001103 l2cap_chan_unlock(chan);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -03001104 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02001105 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -03001106
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001107 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
Gustavo Padovan2d792812012-10-06 10:07:01 +01001108 && test_bit(CONF_STATE2_DEVICE,
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001109 &chan->conf_state)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001110 l2cap_chan_close(chan, ECONNRESET);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001111 l2cap_chan_unlock(chan);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -03001112 continue;
1113 }
1114
Andrei Emeltchenko93c3e8f2012-09-27 17:26:16 +03001115 l2cap_start_connection(chan);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -03001116
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001117 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001118 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001119 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001120 rsp.scid = cpu_to_le16(chan->dcid);
1121 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001122
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001123 if (l2cap_chan_check_security(chan)) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001124 lock_sock(sk);
Gustavo Padovanc5daa682012-05-16 12:17:10 -03001125 if (test_bit(BT_SK_DEFER_SETUP,
1126 &bt_sk(sk)->flags)) {
Andrei Emeltchenkoac734982012-05-24 15:42:51 +03001127 rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
1128 rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Gustavo Padovan2dc4e512012-10-12 19:35:24 +08001129 chan->ops->defer(chan);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001130
1131 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001132 __l2cap_state_change(chan, BT_CONFIG);
Andrei Emeltchenkoac734982012-05-24 15:42:51 +03001133 rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
1134 rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001135 }
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001136 release_sock(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001137 } else {
Andrei Emeltchenkoac734982012-05-24 15:42:51 +03001138 rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
1139 rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001140 }
1141
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001142 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
Gustavo Padovan2d792812012-10-06 10:07:01 +01001143 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001144
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001145 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo Padovan2d792812012-10-06 10:07:01 +01001146 rsp.result != L2CAP_CR_SUCCESS) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001147 l2cap_chan_unlock(chan);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001148 continue;
1149 }
1150
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001151 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001152 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo Padovan2d792812012-10-06 10:07:01 +01001153 l2cap_build_conf_req(chan, buf), buf);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001154 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001155 }
1156
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001157 l2cap_chan_unlock(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001158 }
1159
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001160 mutex_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001161}
1162
Ido Yarivc2287682012-04-20 15:46:07 -03001163/* Find socket with cid and source/destination bdaddr.
Ville Tervob62f3282011-02-10 22:38:50 -03001164 * Returns closest match, locked.
1165 */
Andrei Emeltchenkod9b88702012-03-12 12:13:08 +02001166static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
Ido Yarivc2287682012-04-20 15:46:07 -03001167 bdaddr_t *src,
1168 bdaddr_t *dst)
Ville Tervob62f3282011-02-10 22:38:50 -03001169{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001170 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -03001171
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001172 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -03001173
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001174 list_for_each_entry(c, &chan_list, global_l) {
1175 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001176
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001177 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -03001178 continue;
1179
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001180 if (c->scid == cid) {
Ido Yarivc2287682012-04-20 15:46:07 -03001181 int src_match, dst_match;
1182 int src_any, dst_any;
1183
Ville Tervob62f3282011-02-10 22:38:50 -03001184 /* Exact match. */
Ido Yarivc2287682012-04-20 15:46:07 -03001185 src_match = !bacmp(&bt_sk(sk)->src, src);
1186 dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1187 if (src_match && dst_match) {
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001188 read_unlock(&chan_list_lock);
1189 return c;
1190 }
Ville Tervob62f3282011-02-10 22:38:50 -03001191
1192 /* Closest match */
Ido Yarivc2287682012-04-20 15:46:07 -03001193 src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1194 dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1195 if ((src_match && dst_any) || (src_any && dst_match) ||
1196 (src_any && dst_any))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001197 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -03001198 }
1199 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -03001200
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001201 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -03001202
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001203 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -03001204}
1205
1206static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1207{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -03001208 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001209 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -03001210
1211 BT_DBG("");
1212
1213 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001214 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ido Yarivc2287682012-04-20 15:46:07 -03001215 conn->src, conn->dst);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001216 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -03001217 return;
1218
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001219 parent = pchan->sk;
1220
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001221 lock_sock(parent);
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -03001222
Gustavo Padovan80b98022012-05-27 22:27:51 -03001223 chan = pchan->ops->new_connection(pchan);
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03001224 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -03001225 goto clean;
1226
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03001227 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001228
Ville Tervob62f3282011-02-10 22:38:50 -03001229 hci_conn_hold(conn->hcon);
Szymon Janca9ea3ed2012-07-19 14:46:08 +02001230 conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
Ville Tervob62f3282011-02-10 22:38:50 -03001231
Ville Tervob62f3282011-02-10 22:38:50 -03001232 bacpy(&bt_sk(sk)->src, conn->src);
1233 bacpy(&bt_sk(sk)->dst, conn->dst);
1234
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001235 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001236
Gustavo Padovan6754e0d2012-05-25 09:30:56 -03001237 l2cap_chan_ready(chan);
Ville Tervob62f3282011-02-10 22:38:50 -03001238
Ville Tervob62f3282011-02-10 22:38:50 -03001239clean:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001240 release_sock(parent);
Ville Tervob62f3282011-02-10 22:38:50 -03001241}
1242
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001243static void l2cap_conn_ready(struct l2cap_conn *conn)
1244{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001245 struct l2cap_chan *chan;
Vinicius Costa Gomescc110922012-08-23 21:32:43 -03001246 struct hci_conn *hcon = conn->hcon;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001247
1248 BT_DBG("conn %p", conn);
1249
Vinicius Costa Gomescc110922012-08-23 21:32:43 -03001250 if (!hcon->out && hcon->type == LE_LINK)
Ville Tervob62f3282011-02-10 22:38:50 -03001251 l2cap_le_conn_ready(conn);
1252
Vinicius Costa Gomescc110922012-08-23 21:32:43 -03001253 if (hcon->out && hcon->type == LE_LINK)
1254 smp_conn_security(hcon, hcon->pending_sec_level);
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03001255
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001256 mutex_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001257
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001258 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001259
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001260 l2cap_chan_lock(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001261
Andrei Emeltchenko416fa752012-05-29 13:59:16 +03001262 if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
1263 l2cap_chan_unlock(chan);
1264 continue;
1265 }
1266
Vinicius Costa Gomescc110922012-08-23 21:32:43 -03001267 if (hcon->type == LE_LINK) {
1268 if (smp_conn_security(hcon, chan->sec_level))
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02001269 l2cap_chan_ready(chan);
Ville Tervoacd7d372011-02-10 22:38:49 -03001270
Vinicius Costa Gomes63128452011-06-17 22:46:26 -03001271 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001272 struct sock *sk = chan->sk;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001273 __clear_chan_timer(chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001274 lock_sock(sk);
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001275 __l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001276 sk->sk_state_change(sk);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001277 release_sock(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -03001278
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001279 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001280 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001281
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001282 l2cap_chan_unlock(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001283 }
1284
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001285 mutex_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001286}
1287
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001288/* Notify sockets that we cannot guaranty reliability anymore */
1289static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
1290{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001291 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001292
1293 BT_DBG("conn %p", conn);
1294
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001295 mutex_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001296
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001297 list_for_each_entry(chan, &conn->chan_l, list) {
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +03001298 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Gustavo Padovan1d8b1fd2012-10-06 11:34:52 +01001299 l2cap_chan_set_err(chan, err);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001300 }
1301
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001302 mutex_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001303}
1304
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -02001305static void l2cap_info_timeout(struct work_struct *work)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001306{
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -02001307 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
Gustavo Padovan2d792812012-10-06 10:07:01 +01001308 info_timer.work);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001309
Marcel Holtmann984947d2009-02-06 23:35:19 +01001310 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01001311 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01001312
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001313 l2cap_conn_start(conn);
1314}
1315
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001316static void l2cap_conn_del(struct hci_conn *hcon, int err)
1317{
1318 struct l2cap_conn *conn = hcon->l2cap_data;
1319 struct l2cap_chan *chan, *l;
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001320
1321 if (!conn)
1322 return;
1323
1324 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
1325
1326 kfree_skb(conn->rx_skb);
1327
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001328 mutex_lock(&conn->chan_lock);
1329
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001330 /* Kill channels */
1331 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Mat Martineau61d6ef32012-04-27 16:50:50 -07001332 l2cap_chan_hold(chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001333 l2cap_chan_lock(chan);
1334
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001335 l2cap_chan_del(chan, err);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001336
1337 l2cap_chan_unlock(chan);
1338
Gustavo Padovan80b98022012-05-27 22:27:51 -03001339 chan->ops->close(chan);
Mat Martineau61d6ef32012-04-27 16:50:50 -07001340 l2cap_chan_put(chan);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001341 }
1342
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001343 mutex_unlock(&conn->chan_lock);
1344
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001345 hci_chan_del(conn->hchan);
1346
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001347 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
Ulisses Furquim127074b2012-01-30 18:26:29 -02001348 cancel_delayed_work_sync(&conn->info_timer);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001349
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001350 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
Ulisses Furquim127074b2012-01-30 18:26:29 -02001351 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001352 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001353 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001354
1355 hcon->l2cap_data = NULL;
1356 kfree(conn);
1357}
1358
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001359static void security_timeout(struct work_struct *work)
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001360{
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001361 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
Gustavo Padovan2d792812012-10-06 10:07:01 +01001362 security_timer.work);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001363
Johan Hedbergd06cc412012-06-06 18:44:11 +08001364 BT_DBG("conn %p", conn);
1365
1366 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) {
1367 smp_chan_destroy(conn);
1368 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1369 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001370}
1371
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1373{
Marcel Holtmann01394182006-07-03 10:02:46 +02001374 struct l2cap_conn *conn = hcon->l2cap_data;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001375 struct hci_chan *hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376
Marcel Holtmann01394182006-07-03 10:02:46 +02001377 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 return conn;
1379
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001380 hchan = hci_chan_create(hcon);
1381 if (!hchan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383
Gustavo Padovan8bcde1f2012-05-28 19:18:14 -03001384 conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL);
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001385 if (!conn) {
1386 hci_chan_del(hchan);
1387 return NULL;
1388 }
1389
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 hcon->l2cap_data = conn;
1391 conn->hcon = hcon;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001392 conn->hchan = hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001394 BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
Marcel Holtmann01394182006-07-03 10:02:46 +02001395
Andrei Emeltchenkodcc042d2012-10-05 16:56:57 +03001396 switch (hcon->type) {
1397 case AMP_LINK:
1398 conn->mtu = hcon->hdev->block_mtu;
1399 break;
1400
1401 case LE_LINK:
1402 if (hcon->hdev->le_mtu) {
1403 conn->mtu = hcon->hdev->le_mtu;
1404 break;
1405 }
1406 /* fall through */
1407
1408 default:
Ville Tervoacd7d372011-02-10 22:38:49 -03001409 conn->mtu = hcon->hdev->acl_mtu;
Andrei Emeltchenkodcc042d2012-10-05 16:56:57 +03001410 break;
1411 }
Ville Tervoacd7d372011-02-10 22:38:49 -03001412
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 conn->src = &hcon->hdev->bdaddr;
1414 conn->dst = &hcon->dst;
1415
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001416 conn->feat_mask = 0;
1417
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 spin_lock_init(&conn->lock);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001419 mutex_init(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001420
1421 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001423 if (hcon->type == LE_LINK)
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001424 INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001425 else
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02001426 INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
Dave Young45054dc2009-10-18 20:28:30 +00001427
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001428 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01001429
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430 return conn;
1431}
1432
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434
Ido Yarivc2287682012-04-20 15:46:07 -03001435/* Find socket with psm and source / destination bdaddr.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 * Returns closest match.
1437 */
Ido Yarivc2287682012-04-20 15:46:07 -03001438static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1439 bdaddr_t *src,
1440 bdaddr_t *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001442 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001444 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001445
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001446 list_for_each_entry(c, &chan_list, global_l) {
1447 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001448
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001449 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 continue;
1451
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001452 if (c->psm == psm) {
Ido Yarivc2287682012-04-20 15:46:07 -03001453 int src_match, dst_match;
1454 int src_any, dst_any;
1455
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 /* Exact match. */
Ido Yarivc2287682012-04-20 15:46:07 -03001457 src_match = !bacmp(&bt_sk(sk)->src, src);
1458 dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1459 if (src_match && dst_match) {
Johannes Berga7567b22011-06-01 08:29:54 +02001460 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001461 return c;
1462 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463
1464 /* Closest match */
Ido Yarivc2287682012-04-20 15:46:07 -03001465 src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1466 dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1467 if ((src_match && dst_any) || (src_any && dst_match) ||
1468 (src_any && dst_any))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001469 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 }
1471 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001473 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001474
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001475 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476}
1477
Andre Guedes8e9f9892012-04-24 21:02:55 -03001478int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
1479 bdaddr_t *dst, u8 dst_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001481 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 bdaddr_t *src = &bt_sk(sk)->src;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 struct l2cap_conn *conn;
1484 struct hci_conn *hcon;
1485 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001486 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001487 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03001489 BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", src, dst,
Syam Sidhardhanab195162012-07-27 23:51:22 +05301490 dst_type, __le16_to_cpu(psm));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001492 hdev = hci_get_route(dst, src);
1493 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 return -EHOSTUNREACH;
1495
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001496 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001498 l2cap_chan_lock(chan);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001499
1500 /* PSM must be odd and lsb of upper byte must be 0 */
1501 if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
Gustavo Padovan2d792812012-10-06 10:07:01 +01001502 chan->chan_type != L2CAP_CHAN_RAW) {
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001503 err = -EINVAL;
1504 goto done;
1505 }
1506
1507 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
1508 err = -EINVAL;
1509 goto done;
1510 }
1511
1512 switch (chan->mode) {
1513 case L2CAP_MODE_BASIC:
1514 break;
1515 case L2CAP_MODE_ERTM:
1516 case L2CAP_MODE_STREAMING:
1517 if (!disable_ertm)
1518 break;
1519 /* fall through */
1520 default:
1521 err = -ENOTSUPP;
1522 goto done;
1523 }
1524
Gustavo Padovan0797e012012-05-27 22:27:54 -03001525 switch (chan->state) {
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001526 case BT_CONNECT:
1527 case BT_CONNECT2:
1528 case BT_CONFIG:
1529 /* Already connecting */
1530 err = 0;
1531 goto done;
1532
1533 case BT_CONNECTED:
1534 /* Already connected */
1535 err = -EISCONN;
1536 goto done;
1537
1538 case BT_OPEN:
1539 case BT_BOUND:
1540 /* Can connect */
1541 break;
1542
1543 default:
1544 err = -EBADFD;
1545 goto done;
1546 }
1547
1548 /* Set destination address and psm */
Gustavo Padovan0797e012012-05-27 22:27:54 -03001549 lock_sock(sk);
Gustavo F. Padovan9219b2a2012-01-02 20:08:04 -02001550 bacpy(&bt_sk(sk)->dst, dst);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001551 release_sock(sk);
1552
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001553 chan->psm = psm;
1554 chan->dcid = cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001556 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001557
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001558 if (chan->dcid == L2CAP_CID_LE_DATA)
Andre Guedes8e9f9892012-04-24 21:02:55 -03001559 hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
Andre Guedesb12f62c2012-04-24 21:02:54 -03001560 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001561 else
Andre Guedes8e9f9892012-04-24 21:02:55 -03001562 hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
Andre Guedesb12f62c2012-04-24 21:02:54 -03001563 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001564
Ville Tervo30e76272011-02-22 16:10:53 -03001565 if (IS_ERR(hcon)) {
1566 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001568 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569
1570 conn = l2cap_conn_add(hcon, 0);
1571 if (!conn) {
1572 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001573 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 goto done;
1575 }
1576
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -03001577 if (hcon->type == LE_LINK) {
1578 err = 0;
1579
1580 if (!list_empty(&conn->chan_l)) {
1581 err = -EBUSY;
1582 hci_conn_put(hcon);
1583 }
1584
1585 if (err)
1586 goto done;
1587 }
1588
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 /* Update source addr of the socket */
1590 bacpy(src, conn->src);
1591
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001592 l2cap_chan_unlock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001593 l2cap_chan_add(conn, chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001594 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001595
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001596 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001597 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598
1599 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001600 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001601 __clear_chan_timer(chan);
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001602 if (l2cap_chan_check_security(chan))
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001603 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001604 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001605 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 }
1607
Ville Tervo30e76272011-02-22 16:10:53 -03001608 err = 0;
1609
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610done:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001611 l2cap_chan_unlock(chan);
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001612 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 hci_dev_put(hdev);
1614 return err;
1615}
1616
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001617int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001618{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001619 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001620 DECLARE_WAITQUEUE(wait, current);
1621 int err = 0;
1622 int timeo = HZ/5;
1623
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001624 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001625 set_current_state(TASK_INTERRUPTIBLE);
1626 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001627 if (!timeo)
1628 timeo = HZ/5;
1629
1630 if (signal_pending(current)) {
1631 err = sock_intr_errno(timeo);
1632 break;
1633 }
1634
1635 release_sock(sk);
1636 timeo = schedule_timeout(timeo);
1637 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001638 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001639
1640 err = sock_error(sk);
1641 if (err)
1642 break;
1643 }
1644 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001645 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001646 return err;
1647}
1648
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001649static void l2cap_monitor_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001650{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001651 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
Mat Martineau4239d162012-05-17 20:53:49 -07001652 monitor_timer.work);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001653
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001654 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001655
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001656 l2cap_chan_lock(chan);
1657
Mat Martineau80909e02012-05-17 20:53:50 -07001658 if (!chan->conn) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001659 l2cap_chan_unlock(chan);
Andrei Emeltchenko8d7e1c72012-03-23 09:42:15 +02001660 l2cap_chan_put(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001661 return;
1662 }
1663
Andrei Emeltchenko401bb1f2012-05-21 15:47:46 +03001664 l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001665
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001666 l2cap_chan_unlock(chan);
Andrei Emeltchenko8d7e1c72012-03-23 09:42:15 +02001667 l2cap_chan_put(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001668}
1669
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001670static void l2cap_retrans_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001671{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001672 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
Mat Martineau4239d162012-05-17 20:53:49 -07001673 retrans_timer.work);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001674
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001675 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001676
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001677 l2cap_chan_lock(chan);
1678
Mat Martineau80909e02012-05-17 20:53:50 -07001679 if (!chan->conn) {
1680 l2cap_chan_unlock(chan);
1681 l2cap_chan_put(chan);
1682 return;
1683 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001684
Andrei Emeltchenko401bb1f2012-05-21 15:47:46 +03001685 l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001686 l2cap_chan_unlock(chan);
Andrei Emeltchenko8d7e1c72012-03-23 09:42:15 +02001687 l2cap_chan_put(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001688}
1689
Gustavo Padovand6603662012-05-21 13:58:22 -03001690static void l2cap_streaming_send(struct l2cap_chan *chan,
1691 struct sk_buff_head *skbs)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001692{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001693 struct sk_buff *skb;
Mat Martineau37339372012-05-17 20:53:33 -07001694 struct l2cap_ctrl *control;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001695
Mat Martineau37339372012-05-17 20:53:33 -07001696 BT_DBG("chan %p, skbs %p", chan, skbs);
1697
Mat Martineau37339372012-05-17 20:53:33 -07001698 skb_queue_splice_tail_init(skbs, &chan->tx_q);
1699
1700 while (!skb_queue_empty(&chan->tx_q)) {
1701
1702 skb = skb_dequeue(&chan->tx_q);
1703
1704 bt_cb(skb)->control.retries = 1;
1705 control = &bt_cb(skb)->control;
1706
1707 control->reqseq = 0;
1708 control->txseq = chan->next_tx_seq;
1709
1710 __pack_control(chan, control, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001711
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001712 if (chan->fcs == L2CAP_FCS_CRC16) {
Mat Martineau37339372012-05-17 20:53:33 -07001713 u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
1714 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001715 }
1716
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001717 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001718
Andrei Emeltchenkob4400672012-07-10 15:27:49 +03001719 BT_DBG("Sent txseq %u", control->txseq);
Mat Martineau37339372012-05-17 20:53:33 -07001720
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001721 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Mat Martineau37339372012-05-17 20:53:33 -07001722 chan->frames_sent++;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001723 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001724}
1725
Szymon Janc67c9e842011-07-28 16:24:33 +02001726static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001727{
1728 struct sk_buff *skb, *tx_skb;
Mat Martineau18a48e72012-05-17 20:53:34 -07001729 struct l2cap_ctrl *control;
1730 int sent = 0;
1731
1732 BT_DBG("chan %p", chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001733
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001734 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001735 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001736
Mat Martineau94122bb2012-05-02 09:42:02 -07001737 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
1738 return 0;
1739
Mat Martineau18a48e72012-05-17 20:53:34 -07001740 while (chan->tx_send_head &&
1741 chan->unacked_frames < chan->remote_tx_win &&
1742 chan->tx_state == L2CAP_TX_STATE_XMIT) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001743
Mat Martineau18a48e72012-05-17 20:53:34 -07001744 skb = chan->tx_send_head;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001745
Mat Martineau18a48e72012-05-17 20:53:34 -07001746 bt_cb(skb)->control.retries = 1;
1747 control = &bt_cb(skb)->control;
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001748
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001749 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Mat Martineau18a48e72012-05-17 20:53:34 -07001750 control->final = 1;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001751
Mat Martineau18a48e72012-05-17 20:53:34 -07001752 control->reqseq = chan->buffer_seq;
1753 chan->last_acked_seq = chan->buffer_seq;
1754 control->txseq = chan->next_tx_seq;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001755
Mat Martineau18a48e72012-05-17 20:53:34 -07001756 __pack_control(chan, control, skb);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001757
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001758 if (chan->fcs == L2CAP_FCS_CRC16) {
Mat Martineau18a48e72012-05-17 20:53:34 -07001759 u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
1760 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001761 }
1762
Mat Martineau18a48e72012-05-17 20:53:34 -07001763 /* Clone after data has been modified. Data is assumed to be
1764 read-only (for locking purposes) on cloned sk_buffs.
1765 */
1766 tx_skb = skb_clone(skb, GFP_KERNEL);
1767
1768 if (!tx_skb)
1769 break;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001770
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001771 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001772
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001773 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Mat Martineau18a48e72012-05-17 20:53:34 -07001774 chan->unacked_frames++;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001775 chan->frames_sent++;
Mat Martineau18a48e72012-05-17 20:53:34 -07001776 sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001777
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001778 if (skb_queue_is_last(&chan->tx_q, skb))
1779 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001780 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001781 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Mat Martineau18a48e72012-05-17 20:53:34 -07001782
1783 l2cap_do_send(chan, tx_skb);
Andrei Emeltchenkob4400672012-07-10 15:27:49 +03001784 BT_DBG("Sent txseq %u", control->txseq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001785 }
1786
Andrei Emeltchenkob4400672012-07-10 15:27:49 +03001787 BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent,
1788 chan->unacked_frames, skb_queue_len(&chan->tx_q));
Mat Martineau18a48e72012-05-17 20:53:34 -07001789
1790 return sent;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001791}
1792
Mat Martineaue1fbd4c2012-05-17 20:53:43 -07001793static void l2cap_ertm_resend(struct l2cap_chan *chan)
1794{
1795 struct l2cap_ctrl control;
1796 struct sk_buff *skb;
1797 struct sk_buff *tx_skb;
1798 u16 seq;
1799
1800 BT_DBG("chan %p", chan);
1801
1802 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
1803 return;
1804
1805 while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
1806 seq = l2cap_seq_list_pop(&chan->retrans_list);
1807
1808 skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq);
1809 if (!skb) {
1810 BT_DBG("Error: Can't retransmit seq %d, frame missing",
Gustavo Padovan2d792812012-10-06 10:07:01 +01001811 seq);
Mat Martineaue1fbd4c2012-05-17 20:53:43 -07001812 continue;
1813 }
1814
1815 bt_cb(skb)->control.retries++;
1816 control = bt_cb(skb)->control;
1817
1818 if (chan->max_tx != 0 &&
1819 bt_cb(skb)->control.retries > chan->max_tx) {
1820 BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
1821 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
1822 l2cap_seq_list_clear(&chan->retrans_list);
1823 break;
1824 }
1825
1826 control.reqseq = chan->buffer_seq;
1827 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
1828 control.final = 1;
1829 else
1830 control.final = 0;
1831
1832 if (skb_cloned(skb)) {
1833 /* Cloned sk_buffs are read-only, so we need a
1834 * writeable copy
1835 */
Gustavo Padovan8bcde1f2012-05-28 19:18:14 -03001836 tx_skb = skb_copy(skb, GFP_KERNEL);
Mat Martineaue1fbd4c2012-05-17 20:53:43 -07001837 } else {
Gustavo Padovan8bcde1f2012-05-28 19:18:14 -03001838 tx_skb = skb_clone(skb, GFP_KERNEL);
Mat Martineaue1fbd4c2012-05-17 20:53:43 -07001839 }
1840
1841 if (!tx_skb) {
1842 l2cap_seq_list_clear(&chan->retrans_list);
1843 break;
1844 }
1845
1846 /* Update skb contents */
1847 if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
1848 put_unaligned_le32(__pack_extended_control(&control),
1849 tx_skb->data + L2CAP_HDR_SIZE);
1850 } else {
1851 put_unaligned_le16(__pack_enhanced_control(&control),
1852 tx_skb->data + L2CAP_HDR_SIZE);
1853 }
1854
1855 if (chan->fcs == L2CAP_FCS_CRC16) {
1856 u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len);
1857 put_unaligned_le16(fcs, skb_put(tx_skb,
1858 L2CAP_FCS_SIZE));
1859 }
1860
1861 l2cap_do_send(chan, tx_skb);
1862
1863 BT_DBG("Resent txseq %d", control.txseq);
1864
1865 chan->last_acked_seq = chan->buffer_seq;
1866 }
1867}
1868
Mat Martineauf80842a2012-05-17 20:53:46 -07001869static void l2cap_retransmit(struct l2cap_chan *chan,
1870 struct l2cap_ctrl *control)
1871{
1872 BT_DBG("chan %p, control %p", chan, control);
1873
1874 l2cap_seq_list_append(&chan->retrans_list, control->reqseq);
1875 l2cap_ertm_resend(chan);
1876}
1877
Mat Martineaud2a7ac52012-05-17 20:53:42 -07001878static void l2cap_retransmit_all(struct l2cap_chan *chan,
1879 struct l2cap_ctrl *control)
1880{
Mat Martineaue1fbd4c2012-05-17 20:53:43 -07001881 struct sk_buff *skb;
1882
1883 BT_DBG("chan %p, control %p", chan, control);
1884
1885 if (control->poll)
1886 set_bit(CONN_SEND_FBIT, &chan->conn_state);
1887
1888 l2cap_seq_list_clear(&chan->retrans_list);
1889
1890 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
1891 return;
1892
1893 if (chan->unacked_frames) {
1894 skb_queue_walk(&chan->tx_q, skb) {
1895 if (bt_cb(skb)->control.txseq == control->reqseq ||
Gustavo Padovan2d792812012-10-06 10:07:01 +01001896 skb == chan->tx_send_head)
Mat Martineaue1fbd4c2012-05-17 20:53:43 -07001897 break;
1898 }
1899
1900 skb_queue_walk_from(&chan->tx_q, skb) {
1901 if (skb == chan->tx_send_head)
1902 break;
1903
1904 l2cap_seq_list_append(&chan->retrans_list,
1905 bt_cb(skb)->control.txseq);
1906 }
1907
1908 l2cap_ertm_resend(chan);
1909 }
Mat Martineaud2a7ac52012-05-17 20:53:42 -07001910}
1911
Szymon Jancb17e73b2012-01-11 10:59:47 +01001912static void l2cap_send_ack(struct l2cap_chan *chan)
1913{
Mat Martineau0a0aba42012-05-17 20:53:39 -07001914 struct l2cap_ctrl control;
1915 u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq,
1916 chan->last_acked_seq);
1917 int threshold;
1918
1919 BT_DBG("chan %p last_acked_seq %d buffer_seq %d",
1920 chan, chan->last_acked_seq, chan->buffer_seq);
1921
1922 memset(&control, 0, sizeof(control));
1923 control.sframe = 1;
1924
1925 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
1926 chan->rx_state == L2CAP_RX_STATE_RECV) {
1927 __clear_ack_timer(chan);
1928 control.super = L2CAP_SUPER_RNR;
1929 control.reqseq = chan->buffer_seq;
1930 l2cap_send_sframe(chan, &control);
1931 } else {
1932 if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) {
1933 l2cap_ertm_send(chan);
1934 /* If any i-frames were sent, they included an ack */
1935 if (chan->buffer_seq == chan->last_acked_seq)
1936 frames_to_ack = 0;
1937 }
1938
Mat Martineauc20f8e32012-07-10 05:47:07 -07001939 /* Ack now if the window is 3/4ths full.
Mat Martineau0a0aba42012-05-17 20:53:39 -07001940 * Calculate without mul or div
1941 */
Mat Martineauc20f8e32012-07-10 05:47:07 -07001942 threshold = chan->ack_win;
Mat Martineau0a0aba42012-05-17 20:53:39 -07001943 threshold += threshold << 1;
1944 threshold >>= 2;
1945
Andrei Emeltchenkob4400672012-07-10 15:27:49 +03001946 BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack,
Mat Martineau0a0aba42012-05-17 20:53:39 -07001947 threshold);
1948
1949 if (frames_to_ack >= threshold) {
1950 __clear_ack_timer(chan);
1951 control.super = L2CAP_SUPER_RR;
1952 control.reqseq = chan->buffer_seq;
1953 l2cap_send_sframe(chan, &control);
1954 frames_to_ack = 0;
1955 }
1956
1957 if (frames_to_ack)
1958 __set_ack_timer(chan);
1959 }
Szymon Jancb17e73b2012-01-11 10:59:47 +01001960}
1961
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001962static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
1963 struct msghdr *msg, int len,
1964 int count, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965{
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001966 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001967 struct sk_buff **frag;
Gustavo Padovan90338942012-04-06 20:15:47 -03001968 int sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001970 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001971 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972
1973 sent += count;
1974 len -= count;
1975
1976 /* Continuation fragments (no L2CAP header) */
1977 frag = &skb_shinfo(skb)->frag_list;
1978 while (len) {
Gustavo Padovanfbe00702012-05-15 13:22:55 -03001979 struct sk_buff *tmp;
1980
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981 count = min_t(unsigned int, conn->mtu, len);
1982
Gustavo Padovanfbe00702012-05-15 13:22:55 -03001983 tmp = chan->ops->alloc_skb(chan, count,
1984 msg->msg_flags & MSG_DONTWAIT);
1985 if (IS_ERR(tmp))
1986 return PTR_ERR(tmp);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001987
Gustavo Padovanfbe00702012-05-15 13:22:55 -03001988 *frag = tmp;
1989
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001990 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1991 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001993 (*frag)->priority = skb->priority;
1994
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995 sent += count;
1996 len -= count;
1997
Gustavo Padovan2d0ed3d2012-05-11 13:16:12 -03001998 skb->len += (*frag)->len;
1999 skb->data_len += (*frag)->len;
2000
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 frag = &(*frag)->next;
2002 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003
2004 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002005}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02002007static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
Andrei Emeltchenkob4400672012-07-10 15:27:49 +03002008 struct msghdr *msg, size_t len,
2009 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002010{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002011 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002012 struct sk_buff *skb;
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03002013 int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002014 struct l2cap_hdr *lh;
2015
Andrei Emeltchenkob4400672012-07-10 15:27:49 +03002016 BT_DBG("chan %p len %zu priority %u", chan, len, priority);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002017
2018 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02002019
2020 skb = chan->ops->alloc_skb(chan, count + hlen,
Gustavo Padovan90338942012-04-06 20:15:47 -03002021 msg->msg_flags & MSG_DONTWAIT);
2022 if (IS_ERR(skb))
2023 return skb;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002024
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02002025 skb->priority = priority;
2026
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002027 /* 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);
Andrei Emeltchenkodaf6a78c2012-05-03 10:55:52 +03002030 lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
2031 put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002032
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02002033 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002034 if (unlikely(err < 0)) {
2035 kfree_skb(skb);
2036 return ERR_PTR(err);
2037 }
2038 return skb;
2039}
2040
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02002041static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
Andrei Emeltchenkob4400672012-07-10 15:27:49 +03002042 struct msghdr *msg, size_t len,
2043 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002044{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002045 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002046 struct sk_buff *skb;
Gustavo Padovanf2ba7fa2012-05-03 04:54:21 -03002047 int err, count;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002048 struct l2cap_hdr *lh;
2049
Andrei Emeltchenkob4400672012-07-10 15:27:49 +03002050 BT_DBG("chan %p len %zu", chan, len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002051
Gustavo Padovanf2ba7fa2012-05-03 04:54:21 -03002052 count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02002053
Gustavo Padovanf2ba7fa2012-05-03 04:54:21 -03002054 skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE,
Gustavo Padovan90338942012-04-06 20:15:47 -03002055 msg->msg_flags & MSG_DONTWAIT);
2056 if (IS_ERR(skb))
2057 return skb;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002058
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02002059 skb->priority = priority;
2060
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002061 /* Create L2CAP header */
2062 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002063 lh->cid = cpu_to_le16(chan->dcid);
Gustavo Padovan6ff9b5e2012-05-02 11:56:17 -03002064 lh->len = cpu_to_le16(len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002065
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02002066 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002067 if (unlikely(err < 0)) {
2068 kfree_skb(skb);
2069 return ERR_PTR(err);
2070 }
2071 return skb;
2072}
2073
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03002074static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
Andrei Emeltchenkob4400672012-07-10 15:27:49 +03002075 struct msghdr *msg, size_t len,
2076 u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002077{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002078 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002079 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03002080 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002081 struct l2cap_hdr *lh;
2082
Andrei Emeltchenkob4400672012-07-10 15:27:49 +03002083 BT_DBG("chan %p len %zu", chan, len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002084
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03002085 if (!conn)
2086 return ERR_PTR(-ENOTCONN);
2087
Gustavo Padovanba7aa642012-05-29 13:29:16 -03002088 hlen = __ertm_hdr_size(chan);
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03002089
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002090 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03002091 hlen += L2CAP_SDULEN_SIZE;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002092
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002093 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03002094 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002095
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002096 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02002097
2098 skb = chan->ops->alloc_skb(chan, count + hlen,
Gustavo Padovan90338942012-04-06 20:15:47 -03002099 msg->msg_flags & MSG_DONTWAIT);
2100 if (IS_ERR(skb))
2101 return skb;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002102
2103 /* Create L2CAP header */
2104 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002105 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002106 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03002107
Mat Martineau18a48e72012-05-17 20:53:34 -07002108 /* Control header is populated later */
2109 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2110 put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
2111 else
2112 put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03002113
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002114 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03002115 put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002116
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02002117 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002118 if (unlikely(err < 0)) {
2119 kfree_skb(skb);
2120 return ERR_PTR(err);
2121 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03002122
Mat Martineau18a48e72012-05-17 20:53:34 -07002123 bt_cb(skb)->control.fcs = chan->fcs;
Mat Martineau3ce35142012-04-25 16:36:14 -07002124 bt_cb(skb)->control.retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002125 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126}
2127
Mat Martineau94122bb2012-05-02 09:42:02 -07002128static int l2cap_segment_sdu(struct l2cap_chan *chan,
2129 struct sk_buff_head *seg_queue,
2130 struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002131{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002132 struct sk_buff *skb;
Mat Martineau94122bb2012-05-02 09:42:02 -07002133 u16 sdu_len;
2134 size_t pdu_len;
Mat Martineau94122bb2012-05-02 09:42:02 -07002135 u8 sar;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002136
Andrei Emeltchenkob4400672012-07-10 15:27:49 +03002137 BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002138
Mat Martineau94122bb2012-05-02 09:42:02 -07002139 /* It is critical that ERTM PDUs fit in a single HCI fragment,
2140 * so fragmented skbs are not used. The HCI layer's handling
2141 * of fragmented skbs is not compatible with ERTM's queueing.
2142 */
2143
2144 /* PDU size is derived from the HCI MTU */
2145 pdu_len = chan->conn->mtu;
2146
2147 pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
2148
2149 /* Adjust for largest possible L2CAP overhead. */
Gustavo Padovan35d401d2012-05-25 18:57:05 -03002150 if (chan->fcs)
2151 pdu_len -= L2CAP_FCS_SIZE;
2152
Gustavo Padovanba7aa642012-05-29 13:29:16 -03002153 pdu_len -= __ertm_hdr_size(chan);
Mat Martineau94122bb2012-05-02 09:42:02 -07002154
2155 /* Remote device may have requested smaller PDUs */
2156 pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
2157
2158 if (len <= pdu_len) {
2159 sar = L2CAP_SAR_UNSEGMENTED;
2160 sdu_len = 0;
2161 pdu_len = len;
2162 } else {
2163 sar = L2CAP_SAR_START;
2164 sdu_len = len;
2165 pdu_len -= L2CAP_SDULEN_SIZE;
2166 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002167
2168 while (len > 0) {
Mat Martineau94122bb2012-05-02 09:42:02 -07002169 skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002170
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002171 if (IS_ERR(skb)) {
Mat Martineau94122bb2012-05-02 09:42:02 -07002172 __skb_queue_purge(seg_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002173 return PTR_ERR(skb);
2174 }
2175
Mat Martineau94122bb2012-05-02 09:42:02 -07002176 bt_cb(skb)->control.sar = sar;
2177 __skb_queue_tail(seg_queue, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002178
Mat Martineau94122bb2012-05-02 09:42:02 -07002179 len -= pdu_len;
2180 if (sdu_len) {
2181 sdu_len = 0;
2182 pdu_len += L2CAP_SDULEN_SIZE;
2183 }
2184
2185 if (len <= pdu_len) {
2186 sar = L2CAP_SAR_END;
2187 pdu_len = len;
2188 } else {
2189 sar = L2CAP_SAR_CONTINUE;
2190 }
2191 }
2192
Gustavo Padovanf0f62792012-05-29 13:29:17 -03002193 return 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002194}
2195
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02002196int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
Gustavo Padovan2d792812012-10-06 10:07:01 +01002197 u32 priority)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002198{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002199 struct sk_buff *skb;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002200 int err;
Mat Martineau94122bb2012-05-02 09:42:02 -07002201 struct sk_buff_head seg_queue;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002202
2203 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03002204 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02002205 skb = l2cap_create_connless_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002206 if (IS_ERR(skb))
2207 return PTR_ERR(skb);
2208
2209 l2cap_do_send(chan, skb);
2210 return len;
2211 }
2212
2213 switch (chan->mode) {
2214 case L2CAP_MODE_BASIC:
2215 /* Check outgoing MTU */
2216 if (len > chan->omtu)
2217 return -EMSGSIZE;
2218
2219 /* Create a basic PDU */
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02002220 skb = l2cap_create_basic_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002221 if (IS_ERR(skb))
2222 return PTR_ERR(skb);
2223
2224 l2cap_do_send(chan, skb);
2225 err = len;
2226 break;
2227
2228 case L2CAP_MODE_ERTM:
2229 case L2CAP_MODE_STREAMING:
Mat Martineau94122bb2012-05-02 09:42:02 -07002230 /* Check outgoing MTU */
2231 if (len > chan->omtu) {
2232 err = -EMSGSIZE;
2233 break;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002234 }
2235
Mat Martineau94122bb2012-05-02 09:42:02 -07002236 __skb_queue_head_init(&seg_queue);
2237
2238 /* Do segmentation before calling in to the state machine,
2239 * since it's possible to block while waiting for memory
2240 * allocation.
2241 */
2242 err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
2243
2244 /* The channel could have been closed while segmenting,
2245 * check that it is still connected.
2246 */
2247 if (chan->state != BT_CONNECTED) {
2248 __skb_queue_purge(&seg_queue);
2249 err = -ENOTCONN;
2250 }
2251
2252 if (err)
2253 break;
2254
Mat Martineau37339372012-05-17 20:53:33 -07002255 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo Padovand6603662012-05-21 13:58:22 -03002256 l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST);
Mat Martineau37339372012-05-17 20:53:33 -07002257 else
Gustavo Padovand6603662012-05-21 13:58:22 -03002258 l2cap_streaming_send(chan, &seg_queue);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002259
Gustavo Padovand6603662012-05-21 13:58:22 -03002260 err = len;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002261
Mat Martineau94122bb2012-05-02 09:42:02 -07002262 /* If the skbs were not queued for sending, they'll still be in
2263 * seg_queue and need to be purged.
2264 */
2265 __skb_queue_purge(&seg_queue);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002266 break;
2267
2268 default:
2269 BT_DBG("bad state %1.1x", chan->mode);
2270 err = -EBADFD;
2271 }
2272
2273 return err;
2274}
2275
Mat Martineaud2a7ac52012-05-17 20:53:42 -07002276static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq)
2277{
Mat Martineaubed68bd2012-05-17 20:53:44 -07002278 struct l2cap_ctrl control;
2279 u16 seq;
2280
Andrei Emeltchenkob4400672012-07-10 15:27:49 +03002281 BT_DBG("chan %p, txseq %u", chan, txseq);
Mat Martineaubed68bd2012-05-17 20:53:44 -07002282
2283 memset(&control, 0, sizeof(control));
2284 control.sframe = 1;
2285 control.super = L2CAP_SUPER_SREJ;
2286
2287 for (seq = chan->expected_tx_seq; seq != txseq;
2288 seq = __next_seq(chan, seq)) {
2289 if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) {
2290 control.reqseq = seq;
2291 l2cap_send_sframe(chan, &control);
2292 l2cap_seq_list_append(&chan->srej_list, seq);
2293 }
2294 }
2295
2296 chan->expected_tx_seq = __next_seq(chan, txseq);
Mat Martineaud2a7ac52012-05-17 20:53:42 -07002297}
2298
2299static void l2cap_send_srej_tail(struct l2cap_chan *chan)
2300{
Mat Martineaubed68bd2012-05-17 20:53:44 -07002301 struct l2cap_ctrl control;
2302
2303 BT_DBG("chan %p", chan);
2304
2305 if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR)
2306 return;
2307
2308 memset(&control, 0, sizeof(control));
2309 control.sframe = 1;
2310 control.super = L2CAP_SUPER_SREJ;
2311 control.reqseq = chan->srej_list.tail;
2312 l2cap_send_sframe(chan, &control);
Mat Martineaud2a7ac52012-05-17 20:53:42 -07002313}
2314
2315static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq)
2316{
Mat Martineaubed68bd2012-05-17 20:53:44 -07002317 struct l2cap_ctrl control;
2318 u16 initial_head;
2319 u16 seq;
2320
Andrei Emeltchenkob4400672012-07-10 15:27:49 +03002321 BT_DBG("chan %p, txseq %u", chan, txseq);
Mat Martineaubed68bd2012-05-17 20:53:44 -07002322
2323 memset(&control, 0, sizeof(control));
2324 control.sframe = 1;
2325 control.super = L2CAP_SUPER_SREJ;
2326
2327 /* Capture initial list head to allow only one pass through the list. */
2328 initial_head = chan->srej_list.head;
2329
2330 do {
2331 seq = l2cap_seq_list_pop(&chan->srej_list);
2332 if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR)
2333 break;
2334
2335 control.reqseq = seq;
2336 l2cap_send_sframe(chan, &control);
2337 l2cap_seq_list_append(&chan->srej_list, seq);
2338 } while (chan->srej_list.head != initial_head);
Mat Martineaud2a7ac52012-05-17 20:53:42 -07002339}
2340
Mat Martineau608bcc62012-05-17 20:53:32 -07002341static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq)
2342{
2343 struct sk_buff *acked_skb;
2344 u16 ackseq;
2345
Andrei Emeltchenkob4400672012-07-10 15:27:49 +03002346 BT_DBG("chan %p, reqseq %u", chan, reqseq);
Mat Martineau608bcc62012-05-17 20:53:32 -07002347
2348 if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq)
2349 return;
2350
Andrei Emeltchenkob4400672012-07-10 15:27:49 +03002351 BT_DBG("expected_ack_seq %u, unacked_frames %u",
Mat Martineau608bcc62012-05-17 20:53:32 -07002352 chan->expected_ack_seq, chan->unacked_frames);
2353
2354 for (ackseq = chan->expected_ack_seq; ackseq != reqseq;
2355 ackseq = __next_seq(chan, ackseq)) {
2356
2357 acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq);
2358 if (acked_skb) {
2359 skb_unlink(acked_skb, &chan->tx_q);
2360 kfree_skb(acked_skb);
2361 chan->unacked_frames--;
2362 }
2363 }
2364
2365 chan->expected_ack_seq = reqseq;
2366
2367 if (chan->unacked_frames == 0)
2368 __clear_retrans_timer(chan);
2369
Andrei Emeltchenkob4400672012-07-10 15:27:49 +03002370 BT_DBG("unacked_frames %u", chan->unacked_frames);
Mat Martineau608bcc62012-05-17 20:53:32 -07002371}
2372
2373static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan)
2374{
2375 BT_DBG("chan %p", chan);
2376
2377 chan->expected_tx_seq = chan->buffer_seq;
2378 l2cap_seq_list_clear(&chan->srej_list);
2379 skb_queue_purge(&chan->srej_q);
2380 chan->rx_state = L2CAP_RX_STATE_RECV;
2381}
2382
Gustavo Padovand6603662012-05-21 13:58:22 -03002383static void l2cap_tx_state_xmit(struct l2cap_chan *chan,
2384 struct l2cap_ctrl *control,
2385 struct sk_buff_head *skbs, u8 event)
Mat Martineau608bcc62012-05-17 20:53:32 -07002386{
Mat Martineau608bcc62012-05-17 20:53:32 -07002387 BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2388 event);
2389
2390 switch (event) {
2391 case L2CAP_EV_DATA_REQUEST:
2392 if (chan->tx_send_head == NULL)
2393 chan->tx_send_head = skb_peek(skbs);
2394
2395 skb_queue_splice_tail_init(skbs, &chan->tx_q);
2396 l2cap_ertm_send(chan);
2397 break;
2398 case L2CAP_EV_LOCAL_BUSY_DETECTED:
2399 BT_DBG("Enter LOCAL_BUSY");
2400 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2401
2402 if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2403 /* The SREJ_SENT state must be aborted if we are to
2404 * enter the LOCAL_BUSY state.
2405 */
2406 l2cap_abort_rx_srej_sent(chan);
2407 }
2408
2409 l2cap_send_ack(chan);
2410
2411 break;
2412 case L2CAP_EV_LOCAL_BUSY_CLEAR:
2413 BT_DBG("Exit LOCAL_BUSY");
2414 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2415
2416 if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2417 struct l2cap_ctrl local_control;
2418
2419 memset(&local_control, 0, sizeof(local_control));
2420 local_control.sframe = 1;
2421 local_control.super = L2CAP_SUPER_RR;
2422 local_control.poll = 1;
2423 local_control.reqseq = chan->buffer_seq;
Mat Martineaua67d7f62012-05-17 20:53:35 -07002424 l2cap_send_sframe(chan, &local_control);
Mat Martineau608bcc62012-05-17 20:53:32 -07002425
2426 chan->retry_count = 1;
2427 __set_monitor_timer(chan);
2428 chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2429 }
2430 break;
2431 case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2432 l2cap_process_reqseq(chan, control->reqseq);
2433 break;
2434 case L2CAP_EV_EXPLICIT_POLL:
2435 l2cap_send_rr_or_rnr(chan, 1);
2436 chan->retry_count = 1;
2437 __set_monitor_timer(chan);
2438 __clear_ack_timer(chan);
2439 chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2440 break;
2441 case L2CAP_EV_RETRANS_TO:
2442 l2cap_send_rr_or_rnr(chan, 1);
2443 chan->retry_count = 1;
2444 __set_monitor_timer(chan);
2445 chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2446 break;
2447 case L2CAP_EV_RECV_FBIT:
2448 /* Nothing to process */
2449 break;
2450 default:
2451 break;
2452 }
Mat Martineau608bcc62012-05-17 20:53:32 -07002453}
2454
Gustavo Padovand6603662012-05-21 13:58:22 -03002455static void l2cap_tx_state_wait_f(struct l2cap_chan *chan,
2456 struct l2cap_ctrl *control,
2457 struct sk_buff_head *skbs, u8 event)
Mat Martineau608bcc62012-05-17 20:53:32 -07002458{
Mat Martineau608bcc62012-05-17 20:53:32 -07002459 BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2460 event);
2461
2462 switch (event) {
2463 case L2CAP_EV_DATA_REQUEST:
2464 if (chan->tx_send_head == NULL)
2465 chan->tx_send_head = skb_peek(skbs);
2466 /* Queue data, but don't send. */
2467 skb_queue_splice_tail_init(skbs, &chan->tx_q);
2468 break;
2469 case L2CAP_EV_LOCAL_BUSY_DETECTED:
2470 BT_DBG("Enter LOCAL_BUSY");
2471 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2472
2473 if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2474 /* The SREJ_SENT state must be aborted if we are to
2475 * enter the LOCAL_BUSY state.
2476 */
2477 l2cap_abort_rx_srej_sent(chan);
2478 }
2479
2480 l2cap_send_ack(chan);
2481
2482 break;
2483 case L2CAP_EV_LOCAL_BUSY_CLEAR:
2484 BT_DBG("Exit LOCAL_BUSY");
2485 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2486
2487 if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2488 struct l2cap_ctrl local_control;
2489 memset(&local_control, 0, sizeof(local_control));
2490 local_control.sframe = 1;
2491 local_control.super = L2CAP_SUPER_RR;
2492 local_control.poll = 1;
2493 local_control.reqseq = chan->buffer_seq;
Mat Martineaua67d7f62012-05-17 20:53:35 -07002494 l2cap_send_sframe(chan, &local_control);
Mat Martineau608bcc62012-05-17 20:53:32 -07002495
2496 chan->retry_count = 1;
2497 __set_monitor_timer(chan);
2498 chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2499 }
2500 break;
2501 case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2502 l2cap_process_reqseq(chan, control->reqseq);
2503
2504 /* Fall through */
2505
2506 case L2CAP_EV_RECV_FBIT:
2507 if (control && control->final) {
2508 __clear_monitor_timer(chan);
2509 if (chan->unacked_frames > 0)
2510 __set_retrans_timer(chan);
2511 chan->retry_count = 0;
2512 chan->tx_state = L2CAP_TX_STATE_XMIT;
2513 BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state);
2514 }
2515 break;
2516 case L2CAP_EV_EXPLICIT_POLL:
2517 /* Ignore */
2518 break;
2519 case L2CAP_EV_MONITOR_TO:
2520 if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) {
2521 l2cap_send_rr_or_rnr(chan, 1);
2522 __set_monitor_timer(chan);
2523 chan->retry_count++;
2524 } else {
2525 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
2526 }
2527 break;
2528 default:
2529 break;
2530 }
Mat Martineau608bcc62012-05-17 20:53:32 -07002531}
2532
Gustavo Padovand6603662012-05-21 13:58:22 -03002533static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
2534 struct sk_buff_head *skbs, u8 event)
Mat Martineau608bcc62012-05-17 20:53:32 -07002535{
Mat Martineau608bcc62012-05-17 20:53:32 -07002536 BT_DBG("chan %p, control %p, skbs %p, event %d, state %d",
2537 chan, control, skbs, event, chan->tx_state);
2538
2539 switch (chan->tx_state) {
2540 case L2CAP_TX_STATE_XMIT:
Gustavo Padovand6603662012-05-21 13:58:22 -03002541 l2cap_tx_state_xmit(chan, control, skbs, event);
Mat Martineau608bcc62012-05-17 20:53:32 -07002542 break;
2543 case L2CAP_TX_STATE_WAIT_F:
Gustavo Padovand6603662012-05-21 13:58:22 -03002544 l2cap_tx_state_wait_f(chan, control, skbs, event);
Mat Martineau608bcc62012-05-17 20:53:32 -07002545 break;
2546 default:
2547 /* Ignore event */
2548 break;
2549 }
Mat Martineau608bcc62012-05-17 20:53:32 -07002550}
2551
Mat Martineau4b51dae92012-05-17 20:53:37 -07002552static void l2cap_pass_to_tx(struct l2cap_chan *chan,
2553 struct l2cap_ctrl *control)
2554{
2555 BT_DBG("chan %p, control %p", chan, control);
Andrei Emeltchenko401bb1f2012-05-21 15:47:46 +03002556 l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT);
Mat Martineau4b51dae92012-05-17 20:53:37 -07002557}
2558
Mat Martineauf80842a2012-05-17 20:53:46 -07002559static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan,
2560 struct l2cap_ctrl *control)
2561{
2562 BT_DBG("chan %p, control %p", chan, control);
Andrei Emeltchenko401bb1f2012-05-21 15:47:46 +03002563 l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT);
Mat Martineauf80842a2012-05-17 20:53:46 -07002564}
2565
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566/* Copy frame to all raw sockets on that connection */
2567static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
2568{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002569 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002570 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571
2572 BT_DBG("conn %p", conn);
2573
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002574 mutex_lock(&conn->chan_lock);
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02002575
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002576 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002577 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03002578 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579 continue;
2580
2581 /* Don't send frame to the socket it came from */
2582 if (skb->sk == sk)
2583 continue;
Gustavo Padovan8bcde1f2012-05-28 19:18:14 -03002584 nskb = skb_clone(skb, GFP_KERNEL);
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002585 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 continue;
2587
Gustavo Padovan80b98022012-05-27 22:27:51 -03002588 if (chan->ops->recv(chan, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589 kfree_skb(nskb);
2590 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02002591
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002592 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593}
2594
2595/* ---- L2CAP signalling commands ---- */
Andrei Emeltchenkob4400672012-07-10 15:27:49 +03002596static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
2597 u8 ident, u16 dlen, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598{
2599 struct sk_buff *skb, **frag;
2600 struct l2cap_cmd_hdr *cmd;
2601 struct l2cap_hdr *lh;
2602 int len, count;
2603
Andrei Emeltchenkob4400672012-07-10 15:27:49 +03002604 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u",
2605 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606
2607 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
2608 count = min_t(unsigned int, conn->mtu, len);
2609
Gustavo Padovan8bcde1f2012-05-28 19:18:14 -03002610 skb = bt_skb_alloc(count, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611 if (!skb)
2612 return NULL;
2613
2614 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002615 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002616
2617 if (conn->hcon->type == LE_LINK)
Andrei Emeltchenkoac734982012-05-24 15:42:51 +03002618 lh->cid = __constant_cpu_to_le16(L2CAP_CID_LE_SIGNALING);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002619 else
Andrei Emeltchenkoac734982012-05-24 15:42:51 +03002620 lh->cid = __constant_cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621
2622 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
2623 cmd->code = code;
2624 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002625 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626
2627 if (dlen) {
2628 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
2629 memcpy(skb_put(skb, count), data, count);
2630 data += count;
2631 }
2632
2633 len -= skb->len;
2634
2635 /* Continuation fragments (no L2CAP header) */
2636 frag = &skb_shinfo(skb)->frag_list;
2637 while (len) {
2638 count = min_t(unsigned int, conn->mtu, len);
2639
Gustavo Padovan8bcde1f2012-05-28 19:18:14 -03002640 *frag = bt_skb_alloc(count, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641 if (!*frag)
2642 goto fail;
2643
2644 memcpy(skb_put(*frag, count), data, count);
2645
2646 len -= count;
2647 data += count;
2648
2649 frag = &(*frag)->next;
2650 }
2651
2652 return skb;
2653
2654fail:
2655 kfree_skb(skb);
2656 return NULL;
2657}
2658
Gustavo Padovan2d792812012-10-06 10:07:01 +01002659static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen,
2660 unsigned long *val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661{
2662 struct l2cap_conf_opt *opt = *ptr;
2663 int len;
2664
2665 len = L2CAP_CONF_OPT_SIZE + opt->len;
2666 *ptr += len;
2667
2668 *type = opt->type;
2669 *olen = opt->len;
2670
2671 switch (opt->len) {
2672 case 1:
2673 *val = *((u8 *) opt->val);
2674 break;
2675
2676 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04002677 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678 break;
2679
2680 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04002681 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682 break;
2683
2684 default:
2685 *val = (unsigned long) opt->val;
2686 break;
2687 }
2688
Andrei Emeltchenkob4400672012-07-10 15:27:49 +03002689 BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690 return len;
2691}
2692
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
2694{
2695 struct l2cap_conf_opt *opt = *ptr;
2696
Andrei Emeltchenkob4400672012-07-10 15:27:49 +03002697 BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698
2699 opt->type = type;
2700 opt->len = len;
2701
2702 switch (len) {
2703 case 1:
2704 *((u8 *) opt->val) = val;
2705 break;
2706
2707 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02002708 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 break;
2710
2711 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02002712 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713 break;
2714
2715 default:
2716 memcpy(opt->val, (void *) val, len);
2717 break;
2718 }
2719
2720 *ptr += L2CAP_CONF_OPT_SIZE + len;
2721}
2722
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002723static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
2724{
2725 struct l2cap_conf_efs efs;
2726
Szymon Janc1ec918c2011-11-16 09:32:21 +01002727 switch (chan->mode) {
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002728 case L2CAP_MODE_ERTM:
2729 efs.id = chan->local_id;
2730 efs.stype = chan->local_stype;
2731 efs.msdu = cpu_to_le16(chan->local_msdu);
2732 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
Andrei Emeltchenkoac734982012-05-24 15:42:51 +03002733 efs.acc_lat = __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
Andrei Emeltchenko8936fa62012-10-08 11:14:41 +03002734 efs.flush_to = __constant_cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO);
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002735 break;
2736
2737 case L2CAP_MODE_STREAMING:
2738 efs.id = 1;
2739 efs.stype = L2CAP_SERV_BESTEFFORT;
2740 efs.msdu = cpu_to_le16(chan->local_msdu);
2741 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
2742 efs.acc_lat = 0;
2743 efs.flush_to = 0;
2744 break;
2745
2746 default:
2747 return;
2748 }
2749
2750 l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
Andrei Emeltchenko8936fa62012-10-08 11:14:41 +03002751 (unsigned long) &efs);
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002752}
2753
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002754static void l2cap_ack_timeout(struct work_struct *work)
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002755{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002756 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
Mat Martineau03625202012-05-17 20:53:51 -07002757 ack_timer.work);
2758 u16 frames_to_ack;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002759
Gustavo F. Padovan2fb9b3d2011-12-22 16:56:05 -02002760 BT_DBG("chan %p", chan);
2761
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02002762 l2cap_chan_lock(chan);
2763
Mat Martineau03625202012-05-17 20:53:51 -07002764 frames_to_ack = __seq_offset(chan, chan->buffer_seq,
2765 chan->last_acked_seq);
2766
2767 if (frames_to_ack)
2768 l2cap_send_rr_or_rnr(chan, 0);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02002769
2770 l2cap_chan_unlock(chan);
Szymon Janc09bfb2e2012-01-11 10:59:49 +01002771 l2cap_chan_put(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002772}
2773
Andrei Emeltchenko466f8002012-05-29 13:59:01 +03002774int l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002775{
Mat Martineau3c588192012-04-11 10:48:42 -07002776 int err;
2777
Mat Martineau105bdf92012-04-27 16:50:48 -07002778 chan->next_tx_seq = 0;
2779 chan->expected_tx_seq = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002780 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002781 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002782 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002783 chan->frames_sent = 0;
Mat Martineau105bdf92012-04-27 16:50:48 -07002784 chan->last_acked_seq = 0;
2785 chan->sdu = NULL;
2786 chan->sdu_last_frag = NULL;
2787 chan->sdu_len = 0;
2788
Mat Martineaud34c34f2012-05-14 14:49:27 -07002789 skb_queue_head_init(&chan->tx_q);
2790
Mat Martineau105bdf92012-04-27 16:50:48 -07002791 if (chan->mode != L2CAP_MODE_ERTM)
2792 return 0;
2793
2794 chan->rx_state = L2CAP_RX_STATE_RECV;
2795 chan->tx_state = L2CAP_TX_STATE_XMIT;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002796
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002797 INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2798 INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2799 INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002800
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002801 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002802
Mat Martineau3c588192012-04-11 10:48:42 -07002803 err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
2804 if (err < 0)
2805 return err;
2806
Mat Martineau9dc9aff2012-05-17 16:20:14 -07002807 err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
2808 if (err < 0)
2809 l2cap_seq_list_free(&chan->srej_list);
2810
2811 return err;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002812}
2813
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002814static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2815{
2816 switch (mode) {
2817 case L2CAP_MODE_STREAMING:
2818 case L2CAP_MODE_ERTM:
2819 if (l2cap_mode_supported(mode, remote_feat_mask))
2820 return mode;
2821 /* fall through */
2822 default:
2823 return L2CAP_MODE_BASIC;
2824 }
2825}
2826
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002827static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
2828{
2829 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
2830}
2831
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002832static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2833{
2834 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2835}
2836
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002837static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
2838{
2839 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
Gustavo Padovan2d792812012-10-06 10:07:01 +01002840 __l2cap_ews_supported(chan)) {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002841 /* use extended control field */
2842 set_bit(FLAG_EXT_CTRL, &chan->flags);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002843 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2844 } else {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002845 chan->tx_win = min_t(u16, chan->tx_win,
Gustavo Padovan2d792812012-10-06 10:07:01 +01002846 L2CAP_DEFAULT_TX_WINDOW);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002847 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2848 }
Mat Martineauc20f8e32012-07-10 05:47:07 -07002849 chan->ack_win = chan->tx_win;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002850}
2851
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002852static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002855 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856 void *ptr = req->data;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002857 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002859 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002861 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002862 goto done;
2863
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002864 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002865 case L2CAP_MODE_STREAMING:
2866 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002867 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002868 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002869
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002870 if (__l2cap_efs_supported(chan))
2871 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2872
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002873 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002874 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002875 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002876 break;
2877 }
2878
2879done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002880 if (chan->imtu != L2CAP_DEFAULT_MTU)
2881 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002882
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002883 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002884 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002885 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
Gustavo Padovan2d792812012-10-06 10:07:01 +01002886 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002887 break;
2888
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002889 rfc.mode = L2CAP_MODE_BASIC;
2890 rfc.txwin_size = 0;
2891 rfc.max_transmit = 0;
2892 rfc.retrans_timeout = 0;
2893 rfc.monitor_timeout = 0;
2894 rfc.max_pdu_size = 0;
2895
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002896 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
Gustavo Padovan2d792812012-10-06 10:07:01 +01002897 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002898 break;
2899
2900 case L2CAP_MODE_ERTM:
2901 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002902 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002903 rfc.retrans_timeout = 0;
2904 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002905
2906 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
Gustavo Padovan2d792812012-10-06 10:07:01 +01002907 L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
2908 L2CAP_FCS_SIZE);
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002909 rfc.max_pdu_size = cpu_to_le16(size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002910
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002911 l2cap_txwin_setup(chan);
2912
2913 rfc.txwin_size = min_t(u16, chan->tx_win,
Gustavo Padovan2d792812012-10-06 10:07:01 +01002914 L2CAP_DEFAULT_TX_WINDOW);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002915
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002916 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
Gustavo Padovan2d792812012-10-06 10:07:01 +01002917 (unsigned long) &rfc);
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002918
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002919 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2920 l2cap_add_opt_efs(&ptr, chan);
2921
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002922 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002923 break;
2924
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002925 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo Padovan2d792812012-10-06 10:07:01 +01002926 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002927 chan->fcs = L2CAP_FCS_NONE;
2928 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002929 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002930
2931 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2932 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
Gustavo Padovan2d792812012-10-06 10:07:01 +01002933 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002934 break;
2935
2936 case L2CAP_MODE_STREAMING:
Mat Martineau273759e2012-05-17 20:53:53 -07002937 l2cap_txwin_setup(chan);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002938 rfc.mode = L2CAP_MODE_STREAMING;
2939 rfc.txwin_size = 0;
2940 rfc.max_transmit = 0;
2941 rfc.retrans_timeout = 0;
2942 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002943
2944 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
Gustavo Padovan2d792812012-10-06 10:07:01 +01002945 L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
2946 L2CAP_FCS_SIZE);
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002947 rfc.max_pdu_size = cpu_to_le16(size);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002948
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002949 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
Gustavo Padovan2d792812012-10-06 10:07:01 +01002950 (unsigned long) &rfc);
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002951
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002952 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2953 l2cap_add_opt_efs(&ptr, chan);
2954
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002955 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002956 break;
2957
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002958 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo Padovan2d792812012-10-06 10:07:01 +01002959 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002960 chan->fcs = L2CAP_FCS_NONE;
2961 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002962 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002963 break;
2964 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002966 req->dcid = cpu_to_le16(chan->dcid);
Andrei Emeltchenko59e54bd2012-05-23 15:44:06 +03002967 req->flags = __constant_cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968
2969 return ptr - data;
2970}
2971
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002972static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002974 struct l2cap_conf_rsp *rsp = data;
2975 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002976 void *req = chan->conf_req;
2977 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002978 int type, hint, olen;
2979 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002980 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002981 struct l2cap_conf_efs efs;
2982 u8 remote_efs = 0;
Marcel Holtmann861d6882007-10-20 13:37:06 +02002983 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002984 u16 result = L2CAP_CONF_SUCCESS;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002985 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002987 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002988
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002989 while (len >= L2CAP_CONF_OPT_SIZE) {
2990 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002992 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002993 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002994
2995 switch (type) {
2996 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002997 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002998 break;
2999
3000 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003001 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003002 break;
3003
3004 case L2CAP_CONF_QOS:
3005 break;
3006
Marcel Holtmann6464f352007-10-20 13:39:51 +02003007 case L2CAP_CONF_RFC:
3008 if (olen == sizeof(rfc))
3009 memcpy(&rfc, (void *) val, olen);
3010 break;
3011
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003012 case L2CAP_CONF_FCS:
3013 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003014 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03003015 break;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003016
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03003017 case L2CAP_CONF_EFS:
3018 remote_efs = 1;
3019 if (olen == sizeof(efs))
3020 memcpy(&efs, (void *) val, olen);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003021 break;
3022
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003023 case L2CAP_CONF_EWS:
3024 if (!enable_hs)
3025 return -ECONNREFUSED;
3026
3027 set_bit(FLAG_EXT_CTRL, &chan->flags);
3028 set_bit(CONF_EWS_RECV, &chan->conf_state);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003029 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003030 chan->remote_tx_win = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003031 break;
3032
3033 default:
3034 if (hint)
3035 break;
3036
3037 result = L2CAP_CONF_UNKNOWN;
3038 *((u8 *) ptr++) = type;
3039 break;
3040 }
3041 }
3042
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003043 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003044 goto done;
3045
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003046 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003047 case L2CAP_MODE_STREAMING:
3048 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003049 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003050 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo Padovan2d792812012-10-06 10:07:01 +01003051 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03003052 break;
3053 }
3054
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03003055 if (remote_efs) {
3056 if (__l2cap_efs_supported(chan))
3057 set_bit(FLAG_EFS_ENABLE, &chan->flags);
3058 else
3059 return -ECONNREFUSED;
3060 }
3061
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003062 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003063 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03003064
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003065 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003066 }
3067
3068done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003069 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003070 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003071 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003072
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003073 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003074 return -ECONNREFUSED;
3075
Gustavo Padovan2d792812012-10-06 10:07:01 +01003076 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3077 (unsigned long) &rfc);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003078 }
3079
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003080 if (result == L2CAP_CONF_SUCCESS) {
3081 /* Configure output options and let the other side know
3082 * which ones we don't like. */
3083
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003084 if (mtu < L2CAP_DEFAULT_MIN_MTU)
3085 result = L2CAP_CONF_UNACCEPT;
3086 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003087 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003088 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003089 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003090 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003091
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03003092 if (remote_efs) {
3093 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
Gustavo Padovan2d792812012-10-06 10:07:01 +01003094 efs.stype != L2CAP_SERV_NOTRAFIC &&
3095 efs.stype != chan->local_stype) {
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03003096
3097 result = L2CAP_CONF_UNACCEPT;
3098
3099 if (chan->num_conf_req >= 1)
3100 return -ECONNREFUSED;
3101
3102 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo Padovan2d792812012-10-06 10:07:01 +01003103 sizeof(efs),
3104 (unsigned long) &efs);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003105 } else {
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02003106 /* Send PENDING Conf Rsp */
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003107 result = L2CAP_CONF_PENDING;
3108 set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03003109 }
3110 }
3111
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003112 switch (rfc.mode) {
3113 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003114 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003115 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003116 break;
3117
3118 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003119 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
3120 chan->remote_tx_win = rfc.txwin_size;
3121 else
3122 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
3123
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03003124 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07003125
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03003126 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
Gustavo Padovan2d792812012-10-06 10:07:01 +01003127 chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
3128 L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03003129 rfc.max_pdu_size = cpu_to_le16(size);
3130 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003131
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03003132 rfc.retrans_timeout =
Andrei Emeltchenko4fd21a82012-03-12 12:13:10 +02003133 __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03003134 rfc.monitor_timeout =
Andrei Emeltchenko4fd21a82012-03-12 12:13:10 +02003135 __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003136
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003137 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03003138
3139 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
Gustavo Padovan2d792812012-10-06 10:07:01 +01003140 sizeof(rfc), (unsigned long) &rfc);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03003141
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03003142 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
3143 chan->remote_id = efs.id;
3144 chan->remote_stype = efs.stype;
3145 chan->remote_msdu = le16_to_cpu(efs.msdu);
3146 chan->remote_flush_to =
Gustavo Padovan2d792812012-10-06 10:07:01 +01003147 le32_to_cpu(efs.flush_to);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03003148 chan->remote_acc_lat =
Gustavo Padovan2d792812012-10-06 10:07:01 +01003149 le32_to_cpu(efs.acc_lat);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03003150 chan->remote_sdu_itime =
3151 le32_to_cpu(efs.sdu_itime);
3152 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo Padovan2d792812012-10-06 10:07:01 +01003153 sizeof(efs),
3154 (unsigned long) &efs);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03003155 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003156 break;
3157
3158 case L2CAP_MODE_STREAMING:
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03003159 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
Gustavo Padovan2d792812012-10-06 10:07:01 +01003160 chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
3161 L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03003162 rfc.max_pdu_size = cpu_to_le16(size);
3163 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003164
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003165 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03003166
Gustavo Padovan2d792812012-10-06 10:07:01 +01003167 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3168 (unsigned long) &rfc);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03003169
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003170 break;
3171
3172 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02003173 result = L2CAP_CONF_UNACCEPT;
3174
3175 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003176 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02003177 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003178
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003179 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003180 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003181 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003182 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003183 rsp->result = cpu_to_le16(result);
Andrei Emeltchenko59e54bd2012-05-23 15:44:06 +03003184 rsp->flags = __constant_cpu_to_le16(0);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003185
3186 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187}
3188
Gustavo Padovan2d792812012-10-06 10:07:01 +01003189static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
3190 void *data, u16 *result)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003191{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003192 struct l2cap_conf_req *req = data;
3193 void *ptr = req->data;
3194 int type, olen;
3195 unsigned long val;
Mat Martineau36e999a2011-12-08 17:23:21 -08003196 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02003197 struct l2cap_conf_efs efs;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003198
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003199 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003200
3201 while (len >= L2CAP_CONF_OPT_SIZE) {
3202 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
3203
3204 switch (type) {
3205 case L2CAP_CONF_MTU:
3206 if (val < L2CAP_DEFAULT_MIN_MTU) {
3207 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003208 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003209 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003210 chan->imtu = val;
3211 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003212 break;
3213
3214 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003215 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003216 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo Padovan2d792812012-10-06 10:07:01 +01003217 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003218 break;
3219
3220 case L2CAP_CONF_RFC:
3221 if (olen == sizeof(rfc))
3222 memcpy(&rfc, (void *)val, olen);
3223
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003224 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo Padovan2d792812012-10-06 10:07:01 +01003225 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003226 return -ECONNREFUSED;
3227
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003228 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003229
3230 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
Gustavo Padovan2d792812012-10-06 10:07:01 +01003231 sizeof(rfc), (unsigned long) &rfc);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003232 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003233
3234 case L2CAP_CONF_EWS:
Mat Martineauc20f8e32012-07-10 05:47:07 -07003235 chan->ack_win = min_t(u16, val, chan->ack_win);
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02003236 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
Mat Martineauc20f8e32012-07-10 05:47:07 -07003237 chan->tx_win);
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003238 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02003239
3240 case L2CAP_CONF_EFS:
3241 if (olen == sizeof(efs))
3242 memcpy(&efs, (void *)val, olen);
3243
3244 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
Gustavo Padovan2d792812012-10-06 10:07:01 +01003245 efs.stype != L2CAP_SERV_NOTRAFIC &&
3246 efs.stype != chan->local_stype)
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02003247 return -ECONNREFUSED;
3248
Gustavo Padovan2d792812012-10-06 10:07:01 +01003249 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs),
3250 (unsigned long) &efs);
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02003251 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003252 }
3253 }
3254
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003255 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03003256 return -ECONNREFUSED;
3257
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003258 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03003259
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003260 if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003261 switch (rfc.mode) {
3262 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003263 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
3264 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
3265 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Mat Martineauc20f8e32012-07-10 05:47:07 -07003266 if (!test_bit(FLAG_EXT_CTRL, &chan->flags))
3267 chan->ack_win = min_t(u16, chan->ack_win,
3268 rfc.txwin_size);
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02003269
3270 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
3271 chan->local_msdu = le16_to_cpu(efs.msdu);
3272 chan->local_sdu_itime =
Gustavo Padovan2d792812012-10-06 10:07:01 +01003273 le32_to_cpu(efs.sdu_itime);
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02003274 chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
3275 chan->local_flush_to =
Gustavo Padovan2d792812012-10-06 10:07:01 +01003276 le32_to_cpu(efs.flush_to);
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02003277 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003278 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02003279
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003280 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003281 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003282 }
3283 }
3284
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003285 req->dcid = cpu_to_le16(chan->dcid);
Andrei Emeltchenko59e54bd2012-05-23 15:44:06 +03003286 req->flags = __constant_cpu_to_le16(0);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003287
3288 return ptr - data;
3289}
3290
Gustavo Padovan2d792812012-10-06 10:07:01 +01003291static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data,
3292 u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003293{
3294 struct l2cap_conf_rsp *rsp = data;
3295 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003297 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003299 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003300 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003301 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003302
3303 return ptr - data;
3304}
3305
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003306void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03003307{
3308 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003309 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03003310 u8 buf[128];
3311
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003312 rsp.scid = cpu_to_le16(chan->dcid);
3313 rsp.dcid = cpu_to_le16(chan->scid);
Andrei Emeltchenkoac734982012-05-24 15:42:51 +03003314 rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
3315 rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo Padovan2d792812012-10-06 10:07:01 +01003316 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03003317
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003318 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03003319 return;
3320
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03003321 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo Padovan2d792812012-10-06 10:07:01 +01003322 l2cap_build_conf_req(chan, buf), buf);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03003323 chan->num_conf_req++;
3324}
3325
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003326static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003327{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003328 int type, olen;
3329 unsigned long val;
Mat Martineauc20f8e32012-07-10 05:47:07 -07003330 /* Use sane default values in case a misbehaving remote device
3331 * did not send an RFC or extended window size option.
3332 */
3333 u16 txwin_ext = chan->ack_win;
3334 struct l2cap_conf_rfc rfc = {
3335 .mode = chan->mode,
3336 .retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO),
3337 .monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO),
3338 .max_pdu_size = cpu_to_le16(chan->imtu),
3339 .txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW),
3340 };
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003341
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003342 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003343
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003344 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003345 return;
3346
3347 while (len >= L2CAP_CONF_OPT_SIZE) {
3348 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
3349
Mat Martineauc20f8e32012-07-10 05:47:07 -07003350 switch (type) {
3351 case L2CAP_CONF_RFC:
3352 if (olen == sizeof(rfc))
3353 memcpy(&rfc, (void *)val, olen);
Szymon Janc8f321f82012-06-08 11:33:33 +02003354 break;
Mat Martineauc20f8e32012-07-10 05:47:07 -07003355 case L2CAP_CONF_EWS:
3356 txwin_ext = val;
3357 break;
3358 }
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003359 }
3360
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003361 switch (rfc.mode) {
3362 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003363 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
3364 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Mat Martineauc20f8e32012-07-10 05:47:07 -07003365 chan->mps = le16_to_cpu(rfc.max_pdu_size);
3366 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3367 chan->ack_win = min_t(u16, chan->ack_win, txwin_ext);
3368 else
3369 chan->ack_win = min_t(u16, chan->ack_win,
3370 rfc.txwin_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003371 break;
3372 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003373 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03003374 }
3375}
3376
Gustavo Padovan2d792812012-10-06 10:07:01 +01003377static inline int l2cap_command_rej(struct l2cap_conn *conn,
3378 struct l2cap_cmd_hdr *cmd, u8 *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003379{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003380 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003381
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003382 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003383 return 0;
3384
3385 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
Gustavo Padovan2d792812012-10-06 10:07:01 +01003386 cmd->ident == conn->info_ident) {
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02003387 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01003388
3389 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003390 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003391
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003392 l2cap_conn_start(conn);
3393 }
3394
3395 return 0;
3396}
3397
Gustavo Padovan300229f2012-10-12 19:40:40 +08003398static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
3399 u8 *data, u8 rsp_code, u8 amp_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003400{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
3402 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003403 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04003404 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003405 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003406
3407 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003408 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409
Andrei Emeltchenko097db762012-03-09 14:16:17 +02003410 BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411
3412 /* Check if we have socket listening on psm */
Ido Yarivc2287682012-04-20 15:46:07 -03003413 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003414 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415 result = L2CAP_CR_BAD_PSM;
3416 goto sendresp;
3417 }
3418
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003419 parent = pchan->sk;
3420
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003421 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003422 lock_sock(parent);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003423
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003424 /* Check if the ACL is secure enough (if not SDP) */
Andrei Emeltchenko2983fd62012-05-24 15:42:50 +03003425 if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) &&
Gustavo Padovan2d792812012-10-06 10:07:01 +01003426 !hci_conn_check_link_mode(conn->hcon)) {
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02003427 conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003428 result = L2CAP_CR_SEC_BLOCK;
3429 goto response;
3430 }
3431
Linus Torvalds1da177e2005-04-16 15:20:36 -07003432 result = L2CAP_CR_NO_MEM;
3433
Gustavo Padovan2dfa1002012-05-27 22:27:58 -03003434 /* Check if we already have channel with that dcid */
3435 if (__l2cap_get_chan_by_dcid(conn, scid))
3436 goto response;
3437
Gustavo Padovan80b98022012-05-27 22:27:51 -03003438 chan = pchan->ops->new_connection(pchan);
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03003439 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003440 goto response;
3441
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03003442 sk = chan->sk;
3443
Linus Torvalds1da177e2005-04-16 15:20:36 -07003444 hci_conn_hold(conn->hcon);
3445
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446 bacpy(&bt_sk(sk)->src, conn->src);
3447 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003448 chan->psm = psm;
3449 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003450
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003451 __l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003452
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003453 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03003455 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003457 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458
Marcel Holtmann984947d2009-02-06 23:35:19 +01003459 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02003460 if (l2cap_chan_check_security(chan)) {
Gustavo Padovanc5daa682012-05-16 12:17:10 -03003461 if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02003462 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01003463 result = L2CAP_CR_PEND;
3464 status = L2CAP_CS_AUTHOR_PEND;
Gustavo Padovan2dc4e512012-10-12 19:35:24 +08003465 chan->ops->defer(chan);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01003466 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02003467 __l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01003468 result = L2CAP_CR_SUCCESS;
3469 status = L2CAP_CS_NO_INFO;
3470 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003471 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02003472 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003473 result = L2CAP_CR_PEND;
3474 status = L2CAP_CS_AUTHEN_PEND;
3475 }
3476 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02003477 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003478 result = L2CAP_CR_PEND;
3479 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003480 }
3481
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482response:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003483 release_sock(parent);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003484 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003485
3486sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003487 rsp.scid = cpu_to_le16(scid);
3488 rsp.dcid = cpu_to_le16(dcid);
3489 rsp.result = cpu_to_le16(result);
3490 rsp.status = cpu_to_le16(status);
Mat Martineau4c89b6a2012-10-11 17:48:22 +03003491 l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003492
3493 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
3494 struct l2cap_info_req info;
Andrei Emeltchenkoac734982012-05-24 15:42:51 +03003495 info.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003496
3497 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
3498 conn->info_ident = l2cap_get_ident(conn);
3499
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08003500 schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003501
Gustavo Padovan2d792812012-10-06 10:07:01 +01003502 l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
3503 sizeof(info), &info);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003504 }
3505
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003506 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo Padovan2d792812012-10-06 10:07:01 +01003507 result == L2CAP_CR_SUCCESS) {
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003508 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003509 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003510 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo Padovan2d792812012-10-06 10:07:01 +01003511 l2cap_build_conf_req(chan, buf), buf);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003512 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003513 }
Mat Martineau4c89b6a2012-10-11 17:48:22 +03003514}
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003515
Mat Martineau4c89b6a2012-10-11 17:48:22 +03003516static int l2cap_connect_req(struct l2cap_conn *conn,
3517 struct l2cap_cmd_hdr *cmd, u8 *data)
3518{
Gustavo Padovan300229f2012-10-12 19:40:40 +08003519 l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520 return 0;
3521}
3522
Gustavo Padovan2d792812012-10-06 10:07:01 +01003523static inline int l2cap_connect_rsp(struct l2cap_conn *conn,
3524 struct l2cap_cmd_hdr *cmd, u8 *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003525{
3526 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
3527 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003528 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003529 u8 req[128];
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003530 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003531
3532 scid = __le16_to_cpu(rsp->scid);
3533 dcid = __le16_to_cpu(rsp->dcid);
3534 result = __le16_to_cpu(rsp->result);
3535 status = __le16_to_cpu(rsp->status);
3536
Andrei Emeltchenko1b009c92012-02-21 12:54:54 +02003537 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
Gustavo Padovan2d792812012-10-06 10:07:01 +01003538 dcid, scid, result, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003540 mutex_lock(&conn->chan_lock);
3541
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542 if (scid) {
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003543 chan = __l2cap_get_chan_by_scid(conn, scid);
3544 if (!chan) {
3545 err = -EFAULT;
3546 goto unlock;
3547 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003548 } else {
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003549 chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
3550 if (!chan) {
3551 err = -EFAULT;
3552 goto unlock;
3553 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003554 }
3555
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003556 err = 0;
3557
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003558 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003559
Linus Torvalds1da177e2005-04-16 15:20:36 -07003560 switch (result) {
3561 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003562 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003563 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003564 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003565 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003566
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003567 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003568 break;
3569
Linus Torvalds1da177e2005-04-16 15:20:36 -07003570 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo Padovan2d792812012-10-06 10:07:01 +01003571 l2cap_build_conf_req(chan, req), req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003572 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003573 break;
3574
3575 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003576 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003577 break;
3578
3579 default:
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003580 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581 break;
3582 }
3583
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003584 l2cap_chan_unlock(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003585
3586unlock:
3587 mutex_unlock(&conn->chan_lock);
3588
3589 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003590}
3591
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003592static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07003593{
3594 /* FCS is enabled only in ERTM or streaming mode, if one or both
3595 * sides request it.
3596 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003597 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003598 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003599 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003600 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07003601}
3602
Andrei Emeltchenko29d8a592012-09-21 12:30:05 +03003603static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data,
3604 u8 ident, u16 flags)
3605{
3606 struct l2cap_conn *conn = chan->conn;
3607
3608 BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident,
3609 flags);
3610
3611 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
3612 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
3613
3614 l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP,
3615 l2cap_build_conf_rsp(chan, data,
3616 L2CAP_CONF_SUCCESS, flags), data);
3617}
3618
Gustavo Padovan2d792812012-10-06 10:07:01 +01003619static inline int l2cap_config_req(struct l2cap_conn *conn,
3620 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3621 u8 *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622{
3623 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
3624 u16 dcid, flags;
3625 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003626 struct l2cap_chan *chan;
Mat Martineau3c588192012-04-11 10:48:42 -07003627 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003628
3629 dcid = __le16_to_cpu(req->dcid);
3630 flags = __le16_to_cpu(req->flags);
3631
3632 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
3633
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003634 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003635 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636 return -ENOENT;
3637
David S. Miller033b1142011-07-21 13:38:42 -07003638 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003639 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003640
Andrei Emeltchenkoac734982012-05-24 15:42:51 +03003641 rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID);
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003642 rej.scid = cpu_to_le16(chan->scid);
3643 rej.dcid = cpu_to_le16(chan->dcid);
3644
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003645 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
Gustavo Padovan2d792812012-10-06 10:07:01 +01003646 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003647 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003648 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003649
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003650 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07003651 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04003652 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003653 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo Padovan2d792812012-10-06 10:07:01 +01003654 l2cap_build_conf_rsp(chan, rsp,
3655 L2CAP_CONF_REJECT, flags), rsp);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003656 goto unlock;
3657 }
3658
3659 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003660 memcpy(chan->conf_req + chan->conf_len, req->data, len);
3661 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003662
Andrei Emeltchenko59e54bd2012-05-23 15:44:06 +03003663 if (flags & L2CAP_CONF_FLAG_CONTINUATION) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003664 /* Incomplete config. Send empty response. */
3665 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo Padovan2d792812012-10-06 10:07:01 +01003666 l2cap_build_conf_rsp(chan, rsp,
3667 L2CAP_CONF_SUCCESS, flags), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003668 goto unlock;
3669 }
3670
3671 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003672 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003673 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003674 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003676 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003678 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003679 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003680
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003681 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003682 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003683
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003684 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02003685 goto unlock;
3686
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003687 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003688 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003689
Mat Martineau105bdf92012-04-27 16:50:48 -07003690 if (chan->mode == L2CAP_MODE_ERTM ||
3691 chan->mode == L2CAP_MODE_STREAMING)
Mat Martineau3c588192012-04-11 10:48:42 -07003692 err = l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003693
Mat Martineau3c588192012-04-11 10:48:42 -07003694 if (err < 0)
3695 l2cap_send_disconn_req(chan->conn, chan, -err);
3696 else
3697 l2cap_chan_ready(chan);
3698
Marcel Holtmann876d9482007-10-20 13:35:42 +02003699 goto unlock;
3700 }
3701
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003702 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003703 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo Padovan2d792812012-10-06 10:07:01 +01003705 l2cap_build_conf_req(chan, buf), buf);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003706 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707 }
3708
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003709 /* Got Conf Rsp PENDING from remote side and asume we sent
3710 Conf Rsp PENDING in the code above */
3711 if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
Andrei Emeltchenko29d8a592012-09-21 12:30:05 +03003712 test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003713
3714 /* check compatibility */
3715
Andrei Emeltchenko79de8862012-10-15 11:58:42 +03003716 /* Send rsp for BR/EDR channel */
3717 if (!chan->ctrl_id)
3718 l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags);
3719 else
3720 chan->ident = cmd->ident;
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003721 }
3722
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723unlock:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003724 l2cap_chan_unlock(chan);
Mat Martineau3c588192012-04-11 10:48:42 -07003725 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726}
3727
Gustavo Padovan2d792812012-10-06 10:07:01 +01003728static inline int l2cap_config_rsp(struct l2cap_conn *conn,
3729 struct l2cap_cmd_hdr *cmd, u8 *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730{
3731 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
3732 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003733 struct l2cap_chan *chan;
Andrei Emeltchenko61386cb2012-03-12 12:13:07 +02003734 int len = le16_to_cpu(cmd->len) - sizeof(*rsp);
Mat Martineau3c588192012-04-11 10:48:42 -07003735 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736
3737 scid = __le16_to_cpu(rsp->scid);
3738 flags = __le16_to_cpu(rsp->flags);
3739 result = __le16_to_cpu(rsp->result);
3740
Andrei Emeltchenko61386cb2012-03-12 12:13:07 +02003741 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
3742 result, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003744 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003745 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003746 return 0;
3747
3748 switch (result) {
3749 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003750 l2cap_conf_rfc_get(chan, rsp->data, len);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003751 clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003752 break;
3753
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003754 case L2CAP_CONF_PENDING:
3755 set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
3756
3757 if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
3758 char buf[64];
3759
3760 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
Gustavo Padovan2d792812012-10-06 10:07:01 +01003761 buf, &result);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003762 if (len < 0) {
3763 l2cap_send_disconn_req(conn, chan, ECONNRESET);
3764 goto done;
3765 }
3766
3767 /* check compatibility */
3768
Andrei Emeltchenko79de8862012-10-15 11:58:42 +03003769 if (!chan->ctrl_id)
3770 l2cap_send_efs_conf_rsp(chan, buf, cmd->ident,
3771 0);
3772 else
3773 chan->ident = cmd->ident;
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003774 }
3775 goto done;
3776
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003778 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003779 char req[64];
3780
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003781 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003782 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003783 goto done;
3784 }
3785
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003786 /* throw out any old stored conf requests */
3787 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003788 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
Gustavo Padovan2d792812012-10-06 10:07:01 +01003789 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003790 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003791 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003792 goto done;
3793 }
3794
3795 l2cap_send_cmd(conn, l2cap_get_ident(conn),
Gustavo Padovan2d792812012-10-06 10:07:01 +01003796 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003797 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003798 if (result != L2CAP_CONF_SUCCESS)
3799 goto done;
3800 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801 }
3802
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09003803 default:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003804 l2cap_chan_set_err(chan, ECONNRESET);
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +02003805
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08003806 __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003807 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808 goto done;
3809 }
3810
Andrei Emeltchenko59e54bd2012-05-23 15:44:06 +03003811 if (flags & L2CAP_CONF_FLAG_CONTINUATION)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812 goto done;
3813
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003814 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003816 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003817 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003818
Mat Martineau105bdf92012-04-27 16:50:48 -07003819 if (chan->mode == L2CAP_MODE_ERTM ||
3820 chan->mode == L2CAP_MODE_STREAMING)
Mat Martineau3c588192012-04-11 10:48:42 -07003821 err = l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003822
Mat Martineau3c588192012-04-11 10:48:42 -07003823 if (err < 0)
3824 l2cap_send_disconn_req(chan->conn, chan, -err);
3825 else
3826 l2cap_chan_ready(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003827 }
3828
3829done:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003830 l2cap_chan_unlock(chan);
Mat Martineau3c588192012-04-11 10:48:42 -07003831 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003832}
3833
Gustavo Padovan2d792812012-10-06 10:07:01 +01003834static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
3835 struct l2cap_cmd_hdr *cmd, u8 *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836{
3837 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3838 struct l2cap_disconn_rsp rsp;
3839 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003840 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 struct sock *sk;
3842
3843 scid = __le16_to_cpu(req->scid);
3844 dcid = __le16_to_cpu(req->dcid);
3845
3846 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3847
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003848 mutex_lock(&conn->chan_lock);
3849
3850 chan = __l2cap_get_chan_by_scid(conn, dcid);
3851 if (!chan) {
3852 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853 return 0;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003854 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003855
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003856 l2cap_chan_lock(chan);
3857
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003858 sk = chan->sk;
3859
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003860 rsp.dcid = cpu_to_le16(chan->scid);
3861 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3863
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003864 lock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865 sk->sk_shutdown = SHUTDOWN_MASK;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003866 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867
Mat Martineau61d6ef32012-04-27 16:50:50 -07003868 l2cap_chan_hold(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003869 l2cap_chan_del(chan, ECONNRESET);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003870
3871 l2cap_chan_unlock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872
Gustavo Padovan80b98022012-05-27 22:27:51 -03003873 chan->ops->close(chan);
Mat Martineau61d6ef32012-04-27 16:50:50 -07003874 l2cap_chan_put(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003875
3876 mutex_unlock(&conn->chan_lock);
3877
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878 return 0;
3879}
3880
Gustavo Padovan2d792812012-10-06 10:07:01 +01003881static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
3882 struct l2cap_cmd_hdr *cmd, u8 *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883{
3884 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3885 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003886 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887
3888 scid = __le16_to_cpu(rsp->scid);
3889 dcid = __le16_to_cpu(rsp->dcid);
3890
3891 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3892
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003893 mutex_lock(&conn->chan_lock);
3894
3895 chan = __l2cap_get_chan_by_scid(conn, scid);
3896 if (!chan) {
3897 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 return 0;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003899 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003900
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003901 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003902
Mat Martineau61d6ef32012-04-27 16:50:50 -07003903 l2cap_chan_hold(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003904 l2cap_chan_del(chan, 0);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003905
3906 l2cap_chan_unlock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907
Gustavo Padovan80b98022012-05-27 22:27:51 -03003908 chan->ops->close(chan);
Mat Martineau61d6ef32012-04-27 16:50:50 -07003909 l2cap_chan_put(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003910
3911 mutex_unlock(&conn->chan_lock);
3912
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913 return 0;
3914}
3915
Gustavo Padovan2d792812012-10-06 10:07:01 +01003916static inline int l2cap_information_req(struct l2cap_conn *conn,
3917 struct l2cap_cmd_hdr *cmd, u8 *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918{
3919 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920 u16 type;
3921
3922 type = __le16_to_cpu(req->type);
3923
3924 BT_DBG("type 0x%4.4x", type);
3925
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003926 if (type == L2CAP_IT_FEAT_MASK) {
3927 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003928 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003929 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
Andrei Emeltchenkoac734982012-05-24 15:42:51 +03003930 rsp->type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
3931 rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003932 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003933 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
Gustavo Padovan2d792812012-10-06 10:07:01 +01003934 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003935 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003936 feat_mask |= L2CAP_FEAT_EXT_FLOW
Gustavo Padovan2d792812012-10-06 10:07:01 +01003937 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003938
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003939 put_unaligned_le32(feat_mask, rsp->data);
Gustavo Padovan2d792812012-10-06 10:07:01 +01003940 l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
3941 buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003942 } else if (type == L2CAP_IT_FIXED_CHAN) {
3943 u8 buf[12];
3944 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
Mat Martineau50a147c2011-11-02 16:18:34 -07003945
3946 if (enable_hs)
3947 l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
3948 else
3949 l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
3950
Andrei Emeltchenkoac734982012-05-24 15:42:51 +03003951 rsp->type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3952 rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003953 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Gustavo Padovan2d792812012-10-06 10:07:01 +01003954 l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
3955 buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003956 } else {
3957 struct l2cap_info_rsp rsp;
3958 rsp.type = cpu_to_le16(type);
Andrei Emeltchenkoac734982012-05-24 15:42:51 +03003959 rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP);
Gustavo Padovan2d792812012-10-06 10:07:01 +01003960 l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp),
3961 &rsp);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003962 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963
3964 return 0;
3965}
3966
Gustavo Padovan2d792812012-10-06 10:07:01 +01003967static inline int l2cap_information_rsp(struct l2cap_conn *conn,
3968 struct l2cap_cmd_hdr *cmd, u8 *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969{
3970 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3971 u16 type, result;
3972
3973 type = __le16_to_cpu(rsp->type);
3974 result = __le16_to_cpu(rsp->result);
3975
3976 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3977
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003978 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3979 if (cmd->ident != conn->info_ident ||
Gustavo Padovan2d792812012-10-06 10:07:01 +01003980 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003981 return 0;
3982
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02003983 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003984
Ville Tervoadb08ed2010-08-04 09:43:33 +03003985 if (result != L2CAP_IR_SUCCESS) {
3986 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3987 conn->info_ident = 0;
3988
3989 l2cap_conn_start(conn);
3990
3991 return 0;
3992 }
3993
Andrei Emeltchenko978c93b2012-02-29 10:41:41 +02003994 switch (type) {
3995 case L2CAP_IT_FEAT_MASK:
Harvey Harrison83985312008-05-02 16:25:46 -07003996 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003997
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003998 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003999 struct l2cap_info_req req;
Andrei Emeltchenkoac734982012-05-24 15:42:51 +03004000 req.type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004001
4002 conn->info_ident = l2cap_get_ident(conn);
4003
4004 l2cap_send_cmd(conn, conn->info_ident,
Gustavo Padovan2d792812012-10-06 10:07:01 +01004005 L2CAP_INFO_REQ, sizeof(req), &req);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004006 } else {
4007 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
4008 conn->info_ident = 0;
4009
4010 l2cap_conn_start(conn);
4011 }
Andrei Emeltchenko978c93b2012-02-29 10:41:41 +02004012 break;
4013
4014 case L2CAP_IT_FIXED_CHAN:
4015 conn->fixed_chan_mask = rsp->data[0];
Marcel Holtmann984947d2009-02-06 23:35:19 +01004016 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004017 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01004018
4019 l2cap_conn_start(conn);
Andrei Emeltchenko978c93b2012-02-29 10:41:41 +02004020 break;
Marcel Holtmann984947d2009-02-06 23:35:19 +01004021 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02004022
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023 return 0;
4024}
4025
Mat Martineauf94ff6f2011-11-02 16:18:32 -07004026static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
Gustavo Padovan2d792812012-10-06 10:07:01 +01004027 struct l2cap_cmd_hdr *cmd,
4028 u16 cmd_len, void *data)
Mat Martineauf94ff6f2011-11-02 16:18:32 -07004029{
4030 struct l2cap_create_chan_req *req = data;
4031 struct l2cap_create_chan_rsp rsp;
4032 u16 psm, scid;
4033
4034 if (cmd_len != sizeof(*req))
4035 return -EPROTO;
4036
4037 if (!enable_hs)
4038 return -EINVAL;
4039
4040 psm = le16_to_cpu(req->psm);
4041 scid = le16_to_cpu(req->scid);
4042
Andrei Emeltchenkoad0ac6c2012-07-10 15:27:50 +03004043 BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id);
Mat Martineauf94ff6f2011-11-02 16:18:32 -07004044
4045 /* Placeholder: Always reject */
4046 rsp.dcid = 0;
4047 rsp.scid = cpu_to_le16(scid);
Andrei Emeltchenko8ce0c492012-03-12 12:13:09 +02004048 rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
4049 rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
Mat Martineauf94ff6f2011-11-02 16:18:32 -07004050
4051 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
4052 sizeof(rsp), &rsp);
4053
4054 return 0;
4055}
4056
4057static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
Gustavo Padovan2d792812012-10-06 10:07:01 +01004058 struct l2cap_cmd_hdr *cmd,
4059 void *data)
Mat Martineauf94ff6f2011-11-02 16:18:32 -07004060{
4061 BT_DBG("conn %p", conn);
4062
4063 return l2cap_connect_rsp(conn, cmd, data);
4064}
4065
Mat Martineau8d5a04a2011-11-02 16:18:35 -07004066static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
Andrei Emeltchenkoad0ac6c2012-07-10 15:27:50 +03004067 u16 icid, u16 result)
Mat Martineau8d5a04a2011-11-02 16:18:35 -07004068{
4069 struct l2cap_move_chan_rsp rsp;
4070
Andrei Emeltchenkoad0ac6c2012-07-10 15:27:50 +03004071 BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
Mat Martineau8d5a04a2011-11-02 16:18:35 -07004072
4073 rsp.icid = cpu_to_le16(icid);
4074 rsp.result = cpu_to_le16(result);
4075
4076 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
4077}
4078
4079static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
Andrei Emeltchenkoad0ac6c2012-07-10 15:27:50 +03004080 struct l2cap_chan *chan,
4081 u16 icid, u16 result)
Mat Martineau8d5a04a2011-11-02 16:18:35 -07004082{
4083 struct l2cap_move_chan_cfm cfm;
4084 u8 ident;
4085
Andrei Emeltchenkoad0ac6c2012-07-10 15:27:50 +03004086 BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
Mat Martineau8d5a04a2011-11-02 16:18:35 -07004087
4088 ident = l2cap_get_ident(conn);
4089 if (chan)
4090 chan->ident = ident;
4091
4092 cfm.icid = cpu_to_le16(icid);
4093 cfm.result = cpu_to_le16(result);
4094
4095 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
4096}
4097
4098static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
Andrei Emeltchenkoad0ac6c2012-07-10 15:27:50 +03004099 u16 icid)
Mat Martineau8d5a04a2011-11-02 16:18:35 -07004100{
4101 struct l2cap_move_chan_cfm_rsp rsp;
4102
Andrei Emeltchenkoad0ac6c2012-07-10 15:27:50 +03004103 BT_DBG("icid 0x%4.4x", icid);
Mat Martineau8d5a04a2011-11-02 16:18:35 -07004104
4105 rsp.icid = cpu_to_le16(icid);
4106 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
4107}
4108
4109static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
Andrei Emeltchenkoad0ac6c2012-07-10 15:27:50 +03004110 struct l2cap_cmd_hdr *cmd,
4111 u16 cmd_len, void *data)
Mat Martineau8d5a04a2011-11-02 16:18:35 -07004112{
4113 struct l2cap_move_chan_req *req = data;
4114 u16 icid = 0;
4115 u16 result = L2CAP_MR_NOT_ALLOWED;
4116
4117 if (cmd_len != sizeof(*req))
4118 return -EPROTO;
4119
4120 icid = le16_to_cpu(req->icid);
4121
Andrei Emeltchenkoad0ac6c2012-07-10 15:27:50 +03004122 BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id);
Mat Martineau8d5a04a2011-11-02 16:18:35 -07004123
4124 if (!enable_hs)
4125 return -EINVAL;
4126
4127 /* Placeholder: Always refuse */
4128 l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
4129
4130 return 0;
4131}
4132
4133static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
Andrei Emeltchenkoad0ac6c2012-07-10 15:27:50 +03004134 struct l2cap_cmd_hdr *cmd,
4135 u16 cmd_len, void *data)
Mat Martineau8d5a04a2011-11-02 16:18:35 -07004136{
4137 struct l2cap_move_chan_rsp *rsp = data;
4138 u16 icid, result;
4139
4140 if (cmd_len != sizeof(*rsp))
4141 return -EPROTO;
4142
4143 icid = le16_to_cpu(rsp->icid);
4144 result = le16_to_cpu(rsp->result);
4145
Andrei Emeltchenkoad0ac6c2012-07-10 15:27:50 +03004146 BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
Mat Martineau8d5a04a2011-11-02 16:18:35 -07004147
4148 /* Placeholder: Always unconfirmed */
4149 l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
4150
4151 return 0;
4152}
4153
4154static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
Andrei Emeltchenkoad0ac6c2012-07-10 15:27:50 +03004155 struct l2cap_cmd_hdr *cmd,
4156 u16 cmd_len, void *data)
Mat Martineau8d5a04a2011-11-02 16:18:35 -07004157{
4158 struct l2cap_move_chan_cfm *cfm = data;
4159 u16 icid, result;
4160
4161 if (cmd_len != sizeof(*cfm))
4162 return -EPROTO;
4163
4164 icid = le16_to_cpu(cfm->icid);
4165 result = le16_to_cpu(cfm->result);
4166
Andrei Emeltchenkoad0ac6c2012-07-10 15:27:50 +03004167 BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
Mat Martineau8d5a04a2011-11-02 16:18:35 -07004168
4169 l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
4170
4171 return 0;
4172}
4173
4174static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
Andrei Emeltchenkoad0ac6c2012-07-10 15:27:50 +03004175 struct l2cap_cmd_hdr *cmd,
4176 u16 cmd_len, void *data)
Mat Martineau8d5a04a2011-11-02 16:18:35 -07004177{
4178 struct l2cap_move_chan_cfm_rsp *rsp = data;
4179 u16 icid;
4180
4181 if (cmd_len != sizeof(*rsp))
4182 return -EPROTO;
4183
4184 icid = le16_to_cpu(rsp->icid);
4185
Andrei Emeltchenkoad0ac6c2012-07-10 15:27:50 +03004186 BT_DBG("icid 0x%4.4x", icid);
Mat Martineau8d5a04a2011-11-02 16:18:35 -07004187
4188 return 0;
4189}
4190
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03004191static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Gustavo Padovan2d792812012-10-06 10:07:01 +01004192 u16 to_multiplier)
Claudio Takahaside731152011-02-11 19:28:55 -02004193{
4194 u16 max_latency;
4195
4196 if (min > max || min < 6 || max > 3200)
4197 return -EINVAL;
4198
4199 if (to_multiplier < 10 || to_multiplier > 3200)
4200 return -EINVAL;
4201
4202 if (max >= to_multiplier * 8)
4203 return -EINVAL;
4204
4205 max_latency = (to_multiplier * 8 / max) - 1;
4206 if (latency > 499 || latency > max_latency)
4207 return -EINVAL;
4208
4209 return 0;
4210}
4211
4212static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
Gustavo Padovan2d792812012-10-06 10:07:01 +01004213 struct l2cap_cmd_hdr *cmd,
4214 u8 *data)
Claudio Takahaside731152011-02-11 19:28:55 -02004215{
4216 struct hci_conn *hcon = conn->hcon;
4217 struct l2cap_conn_param_update_req *req;
4218 struct l2cap_conn_param_update_rsp rsp;
4219 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02004220 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02004221
4222 if (!(hcon->link_mode & HCI_LM_MASTER))
4223 return -EINVAL;
4224
4225 cmd_len = __le16_to_cpu(cmd->len);
4226 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
4227 return -EPROTO;
4228
4229 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03004230 min = __le16_to_cpu(req->min);
4231 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02004232 latency = __le16_to_cpu(req->latency);
4233 to_multiplier = __le16_to_cpu(req->to_multiplier);
4234
4235 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
Gustavo Padovan2d792812012-10-06 10:07:01 +01004236 min, max, latency, to_multiplier);
Claudio Takahaside731152011-02-11 19:28:55 -02004237
4238 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02004239
4240 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
4241 if (err)
Andrei Emeltchenkoac734982012-05-24 15:42:51 +03004242 rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
Claudio Takahaside731152011-02-11 19:28:55 -02004243 else
Andrei Emeltchenkoac734982012-05-24 15:42:51 +03004244 rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
Claudio Takahaside731152011-02-11 19:28:55 -02004245
4246 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
Gustavo Padovan2d792812012-10-06 10:07:01 +01004247 sizeof(rsp), &rsp);
Claudio Takahaside731152011-02-11 19:28:55 -02004248
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02004249 if (!err)
4250 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
4251
Claudio Takahaside731152011-02-11 19:28:55 -02004252 return 0;
4253}
4254
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004255static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
Gustavo Padovan2d792812012-10-06 10:07:01 +01004256 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4257 u8 *data)
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004258{
4259 int err = 0;
4260
4261 switch (cmd->code) {
4262 case L2CAP_COMMAND_REJ:
4263 l2cap_command_rej(conn, cmd, data);
4264 break;
4265
4266 case L2CAP_CONN_REQ:
4267 err = l2cap_connect_req(conn, cmd, data);
4268 break;
4269
4270 case L2CAP_CONN_RSP:
Mat Martineauf5a25982012-10-11 17:48:21 +03004271 case L2CAP_CREATE_CHAN_RSP:
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004272 err = l2cap_connect_rsp(conn, cmd, data);
4273 break;
4274
4275 case L2CAP_CONF_REQ:
4276 err = l2cap_config_req(conn, cmd, cmd_len, data);
4277 break;
4278
4279 case L2CAP_CONF_RSP:
4280 err = l2cap_config_rsp(conn, cmd, data);
4281 break;
4282
4283 case L2CAP_DISCONN_REQ:
4284 err = l2cap_disconnect_req(conn, cmd, data);
4285 break;
4286
4287 case L2CAP_DISCONN_RSP:
4288 err = l2cap_disconnect_rsp(conn, cmd, data);
4289 break;
4290
4291 case L2CAP_ECHO_REQ:
4292 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
4293 break;
4294
4295 case L2CAP_ECHO_RSP:
4296 break;
4297
4298 case L2CAP_INFO_REQ:
4299 err = l2cap_information_req(conn, cmd, data);
4300 break;
4301
4302 case L2CAP_INFO_RSP:
4303 err = l2cap_information_rsp(conn, cmd, data);
4304 break;
4305
Mat Martineauf94ff6f2011-11-02 16:18:32 -07004306 case L2CAP_CREATE_CHAN_REQ:
4307 err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
4308 break;
4309
Mat Martineau8d5a04a2011-11-02 16:18:35 -07004310 case L2CAP_MOVE_CHAN_REQ:
4311 err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
4312 break;
4313
4314 case L2CAP_MOVE_CHAN_RSP:
4315 err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
4316 break;
4317
4318 case L2CAP_MOVE_CHAN_CFM:
4319 err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
4320 break;
4321
4322 case L2CAP_MOVE_CHAN_CFM_RSP:
4323 err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
4324 break;
4325
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004326 default:
4327 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
4328 err = -EINVAL;
4329 break;
4330 }
4331
4332 return err;
4333}
4334
4335static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
Gustavo Padovan2d792812012-10-06 10:07:01 +01004336 struct l2cap_cmd_hdr *cmd, u8 *data)
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004337{
4338 switch (cmd->code) {
4339 case L2CAP_COMMAND_REJ:
4340 return 0;
4341
4342 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02004343 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004344
4345 case L2CAP_CONN_PARAM_UPDATE_RSP:
4346 return 0;
4347
4348 default:
4349 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
4350 return -EINVAL;
4351 }
4352}
4353
4354static inline void l2cap_sig_channel(struct l2cap_conn *conn,
Gustavo Padovan2d792812012-10-06 10:07:01 +01004355 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004356{
4357 u8 *data = skb->data;
4358 int len = skb->len;
4359 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004360 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004361
4362 l2cap_raw_recv(conn, skb);
4363
4364 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07004365 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004366 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
4367 data += L2CAP_CMD_HDR_SIZE;
4368 len -= L2CAP_CMD_HDR_SIZE;
4369
Al Viro88219a02007-07-29 00:17:25 -07004370 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371
Gustavo Padovan2d792812012-10-06 10:07:01 +01004372 BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len,
4373 cmd.ident);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374
Al Viro88219a02007-07-29 00:17:25 -07004375 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376 BT_DBG("corrupted command");
4377 break;
4378 }
4379
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004380 if (conn->hcon->type == LE_LINK)
4381 err = l2cap_le_sig_cmd(conn, &cmd, data);
4382 else
4383 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384
4385 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03004386 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03004387
4388 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004389
4390 /* FIXME: Map err to a valid reason */
Andrei Emeltchenkoac734982012-05-24 15:42:51 +03004391 rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Gustavo Padovan2d792812012-10-06 10:07:01 +01004392 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ,
4393 sizeof(rej), &rej);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394 }
4395
Al Viro88219a02007-07-29 00:17:25 -07004396 data += cmd_len;
4397 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398 }
4399
4400 kfree_skb(skb);
4401}
4402
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004403static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004404{
4405 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03004406 int hdr_size;
4407
4408 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
4409 hdr_size = L2CAP_EXT_HDR_SIZE;
4410 else
4411 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004412
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004413 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004414 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004415 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
4416 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
4417
4418 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03004419 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004420 }
4421 return 0;
4422}
4423
Mat Martineau6ea00482012-05-17 20:53:52 -07004424static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03004425{
Mat Martineaue31f7632012-05-17 20:53:41 -07004426 struct l2cap_ctrl control;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03004427
Mat Martineaue31f7632012-05-17 20:53:41 -07004428 BT_DBG("chan %p", chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03004429
Mat Martineaue31f7632012-05-17 20:53:41 -07004430 memset(&control, 0, sizeof(control));
4431 control.sframe = 1;
4432 control.final = 1;
4433 control.reqseq = chan->buffer_seq;
4434 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03004435
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004436 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Mat Martineaue31f7632012-05-17 20:53:41 -07004437 control.super = L2CAP_SUPER_RNR;
4438 l2cap_send_sframe(chan, &control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03004439 }
4440
Mat Martineaue31f7632012-05-17 20:53:41 -07004441 if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
4442 chan->unacked_frames > 0)
4443 __set_retrans_timer(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03004444
Mat Martineaue31f7632012-05-17 20:53:41 -07004445 /* Send pending iframes */
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004446 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03004447
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004448 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Mat Martineaue31f7632012-05-17 20:53:41 -07004449 test_bit(CONN_SEND_FBIT, &chan->conn_state)) {
4450 /* F-bit wasn't sent in an s-frame or i-frame yet, so
4451 * send it now.
4452 */
4453 control.super = L2CAP_SUPER_RR;
4454 l2cap_send_sframe(chan, &control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03004455 }
4456}
4457
Gustavo Padovan2d792812012-10-06 10:07:01 +01004458static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag,
4459 struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004460{
Mat Martineau84084a32011-07-22 14:54:00 -07004461 /* skb->len reflects data in skb as well as all fragments
4462 * skb->data_len reflects only data in fragments
4463 */
4464 if (!skb_has_frag_list(skb))
4465 skb_shinfo(skb)->frag_list = new_frag;
4466
4467 new_frag->next = NULL;
4468
4469 (*last_frag)->next = new_frag;
4470 *last_frag = new_frag;
4471
4472 skb->len += new_frag->len;
4473 skb->data_len += new_frag->len;
4474 skb->truesize += new_frag->truesize;
4475}
4476
Mat Martineau4b51dae92012-05-17 20:53:37 -07004477static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
4478 struct l2cap_ctrl *control)
Mat Martineau84084a32011-07-22 14:54:00 -07004479{
4480 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004481
Mat Martineau4b51dae92012-05-17 20:53:37 -07004482 switch (control->sar) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004483 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07004484 if (chan->sdu)
4485 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004486
Gustavo Padovan80b98022012-05-27 22:27:51 -03004487 err = chan->ops->recv(chan, skb);
Mat Martineau84084a32011-07-22 14:54:00 -07004488 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004489
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004490 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07004491 if (chan->sdu)
4492 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004493
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03004494 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004495 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004496
Mat Martineau84084a32011-07-22 14:54:00 -07004497 if (chan->sdu_len > chan->imtu) {
4498 err = -EMSGSIZE;
4499 break;
4500 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004501
Mat Martineau84084a32011-07-22 14:54:00 -07004502 if (skb->len >= chan->sdu_len)
4503 break;
4504
4505 chan->sdu = skb;
4506 chan->sdu_last_frag = skb;
4507
4508 skb = NULL;
4509 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004510 break;
4511
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004512 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03004513 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07004514 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004515
Mat Martineau84084a32011-07-22 14:54:00 -07004516 append_skb_frag(chan->sdu, skb,
4517 &chan->sdu_last_frag);
4518 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004519
Mat Martineau84084a32011-07-22 14:54:00 -07004520 if (chan->sdu->len >= chan->sdu_len)
4521 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03004522
Mat Martineau84084a32011-07-22 14:54:00 -07004523 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004524 break;
4525
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004526 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03004527 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07004528 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004529
Mat Martineau84084a32011-07-22 14:54:00 -07004530 append_skb_frag(chan->sdu, skb,
4531 &chan->sdu_last_frag);
4532 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004533
Mat Martineau84084a32011-07-22 14:54:00 -07004534 if (chan->sdu->len != chan->sdu_len)
4535 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004536
Gustavo Padovan80b98022012-05-27 22:27:51 -03004537 err = chan->ops->recv(chan, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03004538
Mat Martineau84084a32011-07-22 14:54:00 -07004539 if (!err) {
4540 /* Reassembly complete */
4541 chan->sdu = NULL;
4542 chan->sdu_last_frag = NULL;
4543 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004544 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004545 break;
4546 }
4547
Mat Martineau84084a32011-07-22 14:54:00 -07004548 if (err) {
4549 kfree_skb(skb);
4550 kfree_skb(chan->sdu);
4551 chan->sdu = NULL;
4552 chan->sdu_last_frag = NULL;
4553 chan->sdu_len = 0;
4554 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004555
Mat Martineau84084a32011-07-22 14:54:00 -07004556 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004557}
4558
Mat Martineaue3281402011-07-07 09:39:02 -07004559void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03004560{
Mat Martineau61aa4f52012-05-17 20:53:40 -07004561 u8 event;
4562
4563 if (chan->mode != L2CAP_MODE_ERTM)
4564 return;
4565
4566 event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR;
Andrei Emeltchenko401bb1f2012-05-21 15:47:46 +03004567 l2cap_tx(chan, NULL, NULL, event);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004568}
4569
Mat Martineaud2a7ac52012-05-17 20:53:42 -07004570static int l2cap_rx_queued_iframes(struct l2cap_chan *chan)
4571{
Mat Martineau63838722012-05-17 20:53:45 -07004572 int err = 0;
4573 /* Pass sequential frames to l2cap_reassemble_sdu()
4574 * until a gap is encountered.
4575 */
4576
4577 BT_DBG("chan %p", chan);
4578
4579 while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4580 struct sk_buff *skb;
4581 BT_DBG("Searching for skb with txseq %d (queue len %d)",
4582 chan->buffer_seq, skb_queue_len(&chan->srej_q));
4583
4584 skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq);
4585
4586 if (!skb)
4587 break;
4588
4589 skb_unlink(skb, &chan->srej_q);
4590 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
4591 err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control);
4592 if (err)
4593 break;
4594 }
4595
4596 if (skb_queue_empty(&chan->srej_q)) {
4597 chan->rx_state = L2CAP_RX_STATE_RECV;
4598 l2cap_send_ack(chan);
4599 }
4600
4601 return err;
Mat Martineaud2a7ac52012-05-17 20:53:42 -07004602}
4603
4604static void l2cap_handle_srej(struct l2cap_chan *chan,
4605 struct l2cap_ctrl *control)
4606{
Mat Martineauf80842a2012-05-17 20:53:46 -07004607 struct sk_buff *skb;
4608
4609 BT_DBG("chan %p, control %p", chan, control);
4610
4611 if (control->reqseq == chan->next_tx_seq) {
4612 BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
4613 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4614 return;
4615 }
4616
4617 skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
4618
4619 if (skb == NULL) {
4620 BT_DBG("Seq %d not available for retransmission",
4621 control->reqseq);
4622 return;
4623 }
4624
4625 if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) {
4626 BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
4627 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4628 return;
4629 }
4630
4631 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4632
4633 if (control->poll) {
4634 l2cap_pass_to_tx(chan, control);
4635
4636 set_bit(CONN_SEND_FBIT, &chan->conn_state);
4637 l2cap_retransmit(chan, control);
4638 l2cap_ertm_send(chan);
4639
4640 if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
4641 set_bit(CONN_SREJ_ACT, &chan->conn_state);
4642 chan->srej_save_reqseq = control->reqseq;
4643 }
4644 } else {
4645 l2cap_pass_to_tx_fbit(chan, control);
4646
4647 if (control->final) {
4648 if (chan->srej_save_reqseq != control->reqseq ||
4649 !test_and_clear_bit(CONN_SREJ_ACT,
4650 &chan->conn_state))
4651 l2cap_retransmit(chan, control);
4652 } else {
4653 l2cap_retransmit(chan, control);
4654 if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
4655 set_bit(CONN_SREJ_ACT, &chan->conn_state);
4656 chan->srej_save_reqseq = control->reqseq;
4657 }
4658 }
4659 }
Mat Martineaud2a7ac52012-05-17 20:53:42 -07004660}
4661
4662static void l2cap_handle_rej(struct l2cap_chan *chan,
4663 struct l2cap_ctrl *control)
4664{
Mat Martineaufcd289d2012-05-17 20:53:47 -07004665 struct sk_buff *skb;
4666
4667 BT_DBG("chan %p, control %p", chan, control);
4668
4669 if (control->reqseq == chan->next_tx_seq) {
4670 BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
4671 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4672 return;
4673 }
4674
4675 skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
4676
4677 if (chan->max_tx && skb &&
4678 bt_cb(skb)->control.retries >= chan->max_tx) {
4679 BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
4680 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4681 return;
4682 }
4683
4684 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4685
4686 l2cap_pass_to_tx(chan, control);
4687
4688 if (control->final) {
4689 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
4690 l2cap_retransmit_all(chan, control);
4691 } else {
4692 l2cap_retransmit_all(chan, control);
4693 l2cap_ertm_send(chan);
4694 if (chan->tx_state == L2CAP_TX_STATE_WAIT_F)
4695 set_bit(CONN_REJ_ACT, &chan->conn_state);
4696 }
Mat Martineaud2a7ac52012-05-17 20:53:42 -07004697}
4698
Mat Martineau4b51dae92012-05-17 20:53:37 -07004699static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
4700{
4701 BT_DBG("chan %p, txseq %d", chan, txseq);
4702
4703 BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq,
4704 chan->expected_tx_seq);
4705
4706 if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
4707 if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
Gustavo Padovan2d792812012-10-06 10:07:01 +01004708 chan->tx_win) {
Mat Martineau4b51dae92012-05-17 20:53:37 -07004709 /* See notes below regarding "double poll" and
4710 * invalid packets.
4711 */
4712 if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
4713 BT_DBG("Invalid/Ignore - after SREJ");
4714 return L2CAP_TXSEQ_INVALID_IGNORE;
4715 } else {
4716 BT_DBG("Invalid - in window after SREJ sent");
4717 return L2CAP_TXSEQ_INVALID;
4718 }
4719 }
4720
4721 if (chan->srej_list.head == txseq) {
4722 BT_DBG("Expected SREJ");
4723 return L2CAP_TXSEQ_EXPECTED_SREJ;
4724 }
4725
4726 if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) {
4727 BT_DBG("Duplicate SREJ - txseq already stored");
4728 return L2CAP_TXSEQ_DUPLICATE_SREJ;
4729 }
4730
4731 if (l2cap_seq_list_contains(&chan->srej_list, txseq)) {
4732 BT_DBG("Unexpected SREJ - not requested");
4733 return L2CAP_TXSEQ_UNEXPECTED_SREJ;
4734 }
4735 }
4736
4737 if (chan->expected_tx_seq == txseq) {
4738 if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
4739 chan->tx_win) {
4740 BT_DBG("Invalid - txseq outside tx window");
4741 return L2CAP_TXSEQ_INVALID;
4742 } else {
4743 BT_DBG("Expected");
4744 return L2CAP_TXSEQ_EXPECTED;
4745 }
4746 }
4747
4748 if (__seq_offset(chan, txseq, chan->last_acked_seq) <
Gustavo Padovan2d792812012-10-06 10:07:01 +01004749 __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) {
Mat Martineau4b51dae92012-05-17 20:53:37 -07004750 BT_DBG("Duplicate - expected_tx_seq later than txseq");
4751 return L2CAP_TXSEQ_DUPLICATE;
4752 }
4753
4754 if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) {
4755 /* A source of invalid packets is a "double poll" condition,
4756 * where delays cause us to send multiple poll packets. If
4757 * the remote stack receives and processes both polls,
4758 * sequence numbers can wrap around in such a way that a
4759 * resent frame has a sequence number that looks like new data
4760 * with a sequence gap. This would trigger an erroneous SREJ
4761 * request.
4762 *
4763 * Fortunately, this is impossible with a tx window that's
4764 * less than half of the maximum sequence number, which allows
4765 * invalid frames to be safely ignored.
4766 *
4767 * With tx window sizes greater than half of the tx window
4768 * maximum, the frame is invalid and cannot be ignored. This
4769 * causes a disconnect.
4770 */
4771
4772 if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
4773 BT_DBG("Invalid/Ignore - txseq outside tx window");
4774 return L2CAP_TXSEQ_INVALID_IGNORE;
4775 } else {
4776 BT_DBG("Invalid - txseq outside tx window");
4777 return L2CAP_TXSEQ_INVALID;
4778 }
4779 } else {
4780 BT_DBG("Unexpected - txseq indicates missing frames");
4781 return L2CAP_TXSEQ_UNEXPECTED;
4782 }
4783}
4784
Mat Martineaud2a7ac52012-05-17 20:53:42 -07004785static int l2cap_rx_state_recv(struct l2cap_chan *chan,
4786 struct l2cap_ctrl *control,
4787 struct sk_buff *skb, u8 event)
4788{
4789 int err = 0;
4790 bool skb_in_use = 0;
4791
4792 BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
4793 event);
4794
4795 switch (event) {
4796 case L2CAP_EV_RECV_IFRAME:
4797 switch (l2cap_classify_txseq(chan, control->txseq)) {
4798 case L2CAP_TXSEQ_EXPECTED:
4799 l2cap_pass_to_tx(chan, control);
4800
4801 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4802 BT_DBG("Busy, discarding expected seq %d",
4803 control->txseq);
4804 break;
4805 }
4806
4807 chan->expected_tx_seq = __next_seq(chan,
4808 control->txseq);
4809
4810 chan->buffer_seq = chan->expected_tx_seq;
4811 skb_in_use = 1;
4812
4813 err = l2cap_reassemble_sdu(chan, skb, control);
4814 if (err)
4815 break;
4816
4817 if (control->final) {
4818 if (!test_and_clear_bit(CONN_REJ_ACT,
4819 &chan->conn_state)) {
4820 control->final = 0;
4821 l2cap_retransmit_all(chan, control);
4822 l2cap_ertm_send(chan);
4823 }
4824 }
4825
4826 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
4827 l2cap_send_ack(chan);
4828 break;
4829 case L2CAP_TXSEQ_UNEXPECTED:
4830 l2cap_pass_to_tx(chan, control);
4831
4832 /* Can't issue SREJ frames in the local busy state.
4833 * Drop this frame, it will be seen as missing
4834 * when local busy is exited.
4835 */
4836 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4837 BT_DBG("Busy, discarding unexpected seq %d",
4838 control->txseq);
4839 break;
4840 }
4841
4842 /* There was a gap in the sequence, so an SREJ
4843 * must be sent for each missing frame. The
4844 * current frame is stored for later use.
4845 */
4846 skb_queue_tail(&chan->srej_q, skb);
4847 skb_in_use = 1;
4848 BT_DBG("Queued %p (queue len %d)", skb,
4849 skb_queue_len(&chan->srej_q));
4850
4851 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
4852 l2cap_seq_list_clear(&chan->srej_list);
4853 l2cap_send_srej(chan, control->txseq);
4854
4855 chan->rx_state = L2CAP_RX_STATE_SREJ_SENT;
4856 break;
4857 case L2CAP_TXSEQ_DUPLICATE:
4858 l2cap_pass_to_tx(chan, control);
4859 break;
4860 case L2CAP_TXSEQ_INVALID_IGNORE:
4861 break;
4862 case L2CAP_TXSEQ_INVALID:
4863 default:
4864 l2cap_send_disconn_req(chan->conn, chan,
4865 ECONNRESET);
4866 break;
4867 }
4868 break;
4869 case L2CAP_EV_RECV_RR:
4870 l2cap_pass_to_tx(chan, control);
4871 if (control->final) {
4872 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4873
4874 if (!test_and_clear_bit(CONN_REJ_ACT,
4875 &chan->conn_state)) {
4876 control->final = 0;
4877 l2cap_retransmit_all(chan, control);
4878 }
4879
4880 l2cap_ertm_send(chan);
4881 } else if (control->poll) {
4882 l2cap_send_i_or_rr_or_rnr(chan);
4883 } else {
4884 if (test_and_clear_bit(CONN_REMOTE_BUSY,
4885 &chan->conn_state) &&
4886 chan->unacked_frames)
4887 __set_retrans_timer(chan);
4888
4889 l2cap_ertm_send(chan);
4890 }
4891 break;
4892 case L2CAP_EV_RECV_RNR:
4893 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4894 l2cap_pass_to_tx(chan, control);
4895 if (control && control->poll) {
4896 set_bit(CONN_SEND_FBIT, &chan->conn_state);
4897 l2cap_send_rr_or_rnr(chan, 0);
4898 }
4899 __clear_retrans_timer(chan);
4900 l2cap_seq_list_clear(&chan->retrans_list);
4901 break;
4902 case L2CAP_EV_RECV_REJ:
4903 l2cap_handle_rej(chan, control);
4904 break;
4905 case L2CAP_EV_RECV_SREJ:
4906 l2cap_handle_srej(chan, control);
4907 break;
4908 default:
4909 break;
4910 }
4911
4912 if (skb && !skb_in_use) {
4913 BT_DBG("Freeing %p", skb);
4914 kfree_skb(skb);
4915 }
4916
4917 return err;
4918}
4919
4920static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
4921 struct l2cap_ctrl *control,
4922 struct sk_buff *skb, u8 event)
4923{
4924 int err = 0;
4925 u16 txseq = control->txseq;
4926 bool skb_in_use = 0;
4927
4928 BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
4929 event);
4930
4931 switch (event) {
4932 case L2CAP_EV_RECV_IFRAME:
4933 switch (l2cap_classify_txseq(chan, txseq)) {
4934 case L2CAP_TXSEQ_EXPECTED:
4935 /* Keep frame for reassembly later */
4936 l2cap_pass_to_tx(chan, control);
4937 skb_queue_tail(&chan->srej_q, skb);
4938 skb_in_use = 1;
4939 BT_DBG("Queued %p (queue len %d)", skb,
4940 skb_queue_len(&chan->srej_q));
4941
4942 chan->expected_tx_seq = __next_seq(chan, txseq);
4943 break;
4944 case L2CAP_TXSEQ_EXPECTED_SREJ:
4945 l2cap_seq_list_pop(&chan->srej_list);
4946
4947 l2cap_pass_to_tx(chan, control);
4948 skb_queue_tail(&chan->srej_q, skb);
4949 skb_in_use = 1;
4950 BT_DBG("Queued %p (queue len %d)", skb,
4951 skb_queue_len(&chan->srej_q));
4952
4953 err = l2cap_rx_queued_iframes(chan);
4954 if (err)
4955 break;
4956
4957 break;
4958 case L2CAP_TXSEQ_UNEXPECTED:
4959 /* Got a frame that can't be reassembled yet.
4960 * Save it for later, and send SREJs to cover
4961 * the missing frames.
4962 */
4963 skb_queue_tail(&chan->srej_q, skb);
4964 skb_in_use = 1;
4965 BT_DBG("Queued %p (queue len %d)", skb,
4966 skb_queue_len(&chan->srej_q));
4967
4968 l2cap_pass_to_tx(chan, control);
4969 l2cap_send_srej(chan, control->txseq);
4970 break;
4971 case L2CAP_TXSEQ_UNEXPECTED_SREJ:
4972 /* This frame was requested with an SREJ, but
4973 * some expected retransmitted frames are
4974 * missing. Request retransmission of missing
4975 * SREJ'd frames.
4976 */
4977 skb_queue_tail(&chan->srej_q, skb);
4978 skb_in_use = 1;
4979 BT_DBG("Queued %p (queue len %d)", skb,
4980 skb_queue_len(&chan->srej_q));
4981
4982 l2cap_pass_to_tx(chan, control);
4983 l2cap_send_srej_list(chan, control->txseq);
4984 break;
4985 case L2CAP_TXSEQ_DUPLICATE_SREJ:
4986 /* We've already queued this frame. Drop this copy. */
4987 l2cap_pass_to_tx(chan, control);
4988 break;
4989 case L2CAP_TXSEQ_DUPLICATE:
4990 /* Expecting a later sequence number, so this frame
4991 * was already received. Ignore it completely.
4992 */
4993 break;
4994 case L2CAP_TXSEQ_INVALID_IGNORE:
4995 break;
4996 case L2CAP_TXSEQ_INVALID:
4997 default:
4998 l2cap_send_disconn_req(chan->conn, chan,
4999 ECONNRESET);
5000 break;
5001 }
5002 break;
5003 case L2CAP_EV_RECV_RR:
5004 l2cap_pass_to_tx(chan, control);
5005 if (control->final) {
5006 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
5007
5008 if (!test_and_clear_bit(CONN_REJ_ACT,
5009 &chan->conn_state)) {
5010 control->final = 0;
5011 l2cap_retransmit_all(chan, control);
5012 }
5013
5014 l2cap_ertm_send(chan);
5015 } else if (control->poll) {
5016 if (test_and_clear_bit(CONN_REMOTE_BUSY,
5017 &chan->conn_state) &&
5018 chan->unacked_frames) {
5019 __set_retrans_timer(chan);
5020 }
5021
5022 set_bit(CONN_SEND_FBIT, &chan->conn_state);
5023 l2cap_send_srej_tail(chan);
5024 } else {
5025 if (test_and_clear_bit(CONN_REMOTE_BUSY,
5026 &chan->conn_state) &&
5027 chan->unacked_frames)
5028 __set_retrans_timer(chan);
5029
5030 l2cap_send_ack(chan);
5031 }
5032 break;
5033 case L2CAP_EV_RECV_RNR:
5034 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
5035 l2cap_pass_to_tx(chan, control);
5036 if (control->poll) {
5037 l2cap_send_srej_tail(chan);
5038 } else {
5039 struct l2cap_ctrl rr_control;
5040 memset(&rr_control, 0, sizeof(rr_control));
5041 rr_control.sframe = 1;
5042 rr_control.super = L2CAP_SUPER_RR;
5043 rr_control.reqseq = chan->buffer_seq;
5044 l2cap_send_sframe(chan, &rr_control);
5045 }
5046
5047 break;
5048 case L2CAP_EV_RECV_REJ:
5049 l2cap_handle_rej(chan, control);
5050 break;
5051 case L2CAP_EV_RECV_SREJ:
5052 l2cap_handle_srej(chan, control);
5053 break;
5054 }
5055
5056 if (skb && !skb_in_use) {
5057 BT_DBG("Freeing %p", skb);
5058 kfree_skb(skb);
5059 }
5060
5061 return err;
5062}
5063
5064static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
5065{
5066 /* Make sure reqseq is for a packet that has been sent but not acked */
5067 u16 unacked;
5068
5069 unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq);
5070 return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked;
5071}
5072
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07005073static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
5074 struct sk_buff *skb, u8 event)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005075{
Mat Martineaud2a7ac52012-05-17 20:53:42 -07005076 int err = 0;
5077
5078 BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan,
5079 control, skb, event, chan->rx_state);
5080
5081 if (__valid_reqseq(chan, control->reqseq)) {
5082 switch (chan->rx_state) {
5083 case L2CAP_RX_STATE_RECV:
5084 err = l2cap_rx_state_recv(chan, control, skb, event);
5085 break;
5086 case L2CAP_RX_STATE_SREJ_SENT:
5087 err = l2cap_rx_state_srej_sent(chan, control, skb,
5088 event);
5089 break;
5090 default:
5091 /* shut it down */
5092 break;
5093 }
5094 } else {
5095 BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d",
5096 control->reqseq, chan->next_tx_seq,
5097 chan->expected_ack_seq);
5098 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
5099 }
5100
5101 return err;
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07005102}
5103
5104static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
5105 struct sk_buff *skb)
5106{
Mat Martineau4b51dae92012-05-17 20:53:37 -07005107 int err = 0;
5108
5109 BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
5110 chan->rx_state);
5111
5112 if (l2cap_classify_txseq(chan, control->txseq) ==
5113 L2CAP_TXSEQ_EXPECTED) {
5114 l2cap_pass_to_tx(chan, control);
5115
5116 BT_DBG("buffer_seq %d->%d", chan->buffer_seq,
5117 __next_seq(chan, chan->buffer_seq));
5118
5119 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
5120
5121 l2cap_reassemble_sdu(chan, skb, control);
5122 } else {
5123 if (chan->sdu) {
5124 kfree_skb(chan->sdu);
5125 chan->sdu = NULL;
5126 }
5127 chan->sdu_last_frag = NULL;
5128 chan->sdu_len = 0;
5129
5130 if (skb) {
5131 BT_DBG("Freeing %p", skb);
5132 kfree_skb(skb);
5133 }
5134 }
5135
5136 chan->last_acked_seq = control->txseq;
5137 chan->expected_tx_seq = __next_seq(chan, control->txseq);
5138
5139 return err;
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07005140}
5141
5142static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
5143{
5144 struct l2cap_ctrl *control = &bt_cb(skb)->control;
5145 u16 len;
5146 u8 event;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005147
Mat Martineaub76bbd62012-04-11 10:48:43 -07005148 __unpack_control(chan, skb);
5149
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005150 len = skb->len;
5151
5152 /*
5153 * We can just drop the corrupted I-frame here.
5154 * Receiver will miss it and start proper recovery
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07005155 * procedures and ask for retransmission.
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005156 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03005157 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005158 goto drop;
5159
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07005160 if (!control->sframe && control->sar == L2CAP_SAR_START)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03005161 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005162
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03005163 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03005164 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005165
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03005166 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03005167 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005168 goto drop;
5169 }
5170
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07005171 if (!control->sframe) {
5172 int err;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005173
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07005174 BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
5175 control->sar, control->reqseq, control->final,
5176 control->txseq);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03005177
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07005178 /* Validate F-bit - F=0 always valid, F=1 only
5179 * valid in TX WAIT_F
5180 */
5181 if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005182 goto drop;
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07005183
5184 if (chan->mode != L2CAP_MODE_STREAMING) {
5185 event = L2CAP_EV_RECV_IFRAME;
5186 err = l2cap_rx(chan, control, skb, event);
5187 } else {
5188 err = l2cap_stream_rx(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005189 }
5190
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07005191 if (err)
5192 l2cap_send_disconn_req(chan->conn, chan,
5193 ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005194 } else {
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07005195 const u8 rx_func_to_event[4] = {
5196 L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
5197 L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
5198 };
5199
5200 /* Only I-frames are expected in streaming mode */
5201 if (chan->mode == L2CAP_MODE_STREAMING)
5202 goto drop;
5203
5204 BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
5205 control->reqseq, control->final, control->poll,
5206 control->super);
5207
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005208 if (len != 0) {
5209 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03005210 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005211 goto drop;
5212 }
5213
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07005214 /* Validate F and P bits */
5215 if (control->final && (control->poll ||
5216 chan->tx_state != L2CAP_TX_STATE_WAIT_F))
5217 goto drop;
5218
5219 event = rx_func_to_event[control->super];
5220 if (l2cap_rx(chan, control, skb, event))
5221 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03005222 }
5223
5224 return 0;
5225
5226drop:
5227 kfree_skb(skb);
5228 return 0;
5229}
5230
Andrei Emeltchenko13ca56e2012-05-31 11:18:55 +03005231static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
5232 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005233{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03005234 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005235
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03005236 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03005237 if (!chan) {
Andrei Emeltchenko97e8e892012-05-29 13:59:17 +03005238 if (cid == L2CAP_CID_A2MP) {
5239 chan = a2mp_channel_create(conn, skb);
5240 if (!chan) {
5241 kfree_skb(skb);
Andrei Emeltchenko13ca56e2012-05-31 11:18:55 +03005242 return;
Andrei Emeltchenko97e8e892012-05-29 13:59:17 +03005243 }
5244
5245 l2cap_chan_lock(chan);
5246 } else {
5247 BT_DBG("unknown cid 0x%4.4x", cid);
5248 /* Drop packet and return */
5249 kfree_skb(skb);
Andrei Emeltchenko13ca56e2012-05-31 11:18:55 +03005250 return;
Andrei Emeltchenko97e8e892012-05-29 13:59:17 +03005251 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005252 }
5253
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03005254 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005255
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03005256 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005257 goto drop;
5258
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03005259 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03005260 case L2CAP_MODE_BASIC:
5261 /* If socket recv buffers overflows we drop data here
5262 * which is *bad* because L2CAP has to be reliable.
5263 * But we don't have any other choice. L2CAP doesn't
5264 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005265
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03005266 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03005267 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005268
Gustavo Padovan80b98022012-05-27 22:27:51 -03005269 if (!chan->ops->recv(chan, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03005270 goto done;
5271 break;
5272
5273 case L2CAP_MODE_ERTM:
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03005274 case L2CAP_MODE_STREAMING:
Mat Martineaucec8ab6e2012-05-17 20:53:36 -07005275 l2cap_data_rcv(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03005276 goto done;
5277
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03005278 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03005279 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03005280 break;
5281 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005282
5283drop:
5284 kfree_skb(skb);
5285
5286done:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02005287 l2cap_chan_unlock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005288}
5289
Andrei Emeltchenko84104b22012-05-31 11:18:56 +03005290static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
5291 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005292{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005293 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005294
Ido Yarivc2287682012-04-20 15:46:07 -03005295 chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005296 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005297 goto drop;
5298
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02005299 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005300
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03005301 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005302 goto drop;
5303
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03005304 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005305 goto drop;
5306
Gustavo Padovan80b98022012-05-27 22:27:51 -03005307 if (!chan->ops->recv(chan, skb))
Andrei Emeltchenko84104b22012-05-31 11:18:56 +03005308 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005309
5310drop:
5311 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005312}
5313
Andrei Emeltchenko6810fca2012-05-31 11:18:57 +03005314static void l2cap_att_channel(struct l2cap_conn *conn, u16 cid,
5315 struct sk_buff *skb)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03005316{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005317 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03005318
Ido Yarivc2287682012-04-20 15:46:07 -03005319 chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005320 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03005321 goto drop;
5322
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02005323 BT_DBG("chan %p, len %d", chan, skb->len);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03005324
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03005325 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03005326 goto drop;
5327
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03005328 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03005329 goto drop;
5330
Gustavo Padovan80b98022012-05-27 22:27:51 -03005331 if (!chan->ops->recv(chan, skb))
Andrei Emeltchenko6810fca2012-05-31 11:18:57 +03005332 return;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03005333
5334drop:
5335 kfree_skb(skb);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03005336}
5337
Linus Torvalds1da177e2005-04-16 15:20:36 -07005338static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
5339{
5340 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07005341 u16 cid, len;
5342 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005343
5344 skb_pull(skb, L2CAP_HDR_SIZE);
5345 cid = __le16_to_cpu(lh->cid);
5346 len = __le16_to_cpu(lh->len);
5347
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03005348 if (len != skb->len) {
5349 kfree_skb(skb);
5350 return;
5351 }
5352
Linus Torvalds1da177e2005-04-16 15:20:36 -07005353 BT_DBG("len %d, cid 0x%4.4x", len, cid);
5354
5355 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02005356 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03005357 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07005358 l2cap_sig_channel(conn, skb);
5359 break;
5360
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03005361 case L2CAP_CID_CONN_LESS:
Andrei Emeltchenko097db762012-03-09 14:16:17 +02005362 psm = get_unaligned((__le16 *) skb->data);
Andrei Emeltchenko0181a702012-05-29 10:04:05 +03005363 skb_pull(skb, L2CAP_PSMLEN_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005364 l2cap_conless_channel(conn, psm, skb);
5365 break;
5366
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03005367 case L2CAP_CID_LE_DATA:
5368 l2cap_att_channel(conn, cid, skb);
5369 break;
5370
Anderson Brigliab501d6a2011-06-07 18:46:31 -03005371 case L2CAP_CID_SMP:
5372 if (smp_sig_channel(conn, skb))
5373 l2cap_conn_del(conn->hcon, EACCES);
5374 break;
5375
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376 default:
5377 l2cap_data_channel(conn, cid, skb);
5378 break;
5379 }
5380}
5381
5382/* ---- L2CAP interface with lower layer (HCI) ---- */
5383
Ulisses Furquim686ebf22011-12-21 10:11:33 -02005384int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005385{
5386 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005387 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005388
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03005389 BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005390
5391 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005392 read_lock(&chan_list_lock);
5393 list_for_each_entry(c, &chan_list, global_l) {
5394 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03005395
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03005396 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005397 continue;
5398
5399 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01005400 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03005401 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01005402 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005403 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01005404 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
5405 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03005406 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01005407 lm2 |= HCI_LM_MASTER;
5408 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005409 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005410 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005411
5412 return exact ? lm1 : lm2;
5413}
5414
Andrei Emeltchenko9e664632012-07-24 16:06:15 +03005415void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005416{
Marcel Holtmann01394182006-07-03 10:02:46 +02005417 struct l2cap_conn *conn;
5418
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +03005419 BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005420
Linus Torvalds1da177e2005-04-16 15:20:36 -07005421 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005422 conn = l2cap_conn_add(hcon, status);
5423 if (conn)
5424 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02005425 } else
Joe Perchese1750722011-06-29 18:18:29 -07005426 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005427
Linus Torvalds1da177e2005-04-16 15:20:36 -07005428}
5429
Ulisses Furquim686ebf22011-12-21 10:11:33 -02005430int l2cap_disconn_ind(struct hci_conn *hcon)
Marcel Holtmann2950f212009-02-12 14:02:50 +01005431{
5432 struct l2cap_conn *conn = hcon->l2cap_data;
5433
5434 BT_DBG("hcon %p", hcon);
5435
Ulisses Furquim686ebf22011-12-21 10:11:33 -02005436 if (!conn)
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02005437 return HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01005438 return conn->disc_reason;
5439}
5440
Andrei Emeltchenko9e664632012-07-24 16:06:15 +03005441void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005442{
5443 BT_DBG("hcon %p reason %d", hcon, reason);
5444
Joe Perchese1750722011-06-29 18:18:29 -07005445 l2cap_conn_del(hcon, bt_to_errno(reason));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005446}
5447
Gustavo F. Padovan43434782011-04-12 18:31:57 -03005448static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01005449{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03005450 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01005451 return;
5452
Marcel Holtmannf62e4322009-01-15 21:58:44 +01005453 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03005454 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08005455 __set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03005456 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03005457 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01005458 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03005459 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03005460 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01005461 }
5462}
5463
Ulisses Furquim686ebf22011-12-21 10:11:33 -02005464int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005465{
Marcel Holtmann40be4922008-07-14 20:13:50 +02005466 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03005467 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005468
Marcel Holtmann01394182006-07-03 10:02:46 +02005469 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005470 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02005471
Andrei Emeltchenko89d8b402012-07-10 15:27:51 +03005472 BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005473
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03005474 if (hcon->type == LE_LINK) {
Hemant Gupta35d4adcc2012-04-18 14:46:26 +05305475 if (!status && encrypt)
5476 smp_distribute_keys(conn, 0);
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02005477 cancel_delayed_work(&conn->security_timer);
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03005478 }
5479
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02005480 mutex_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005481
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02005482 list_for_each_entry(chan, &conn->chan_l, list) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02005483 l2cap_chan_lock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005484
Andrei Emeltchenko89d8b402012-07-10 15:27:51 +03005485 BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
5486 state_to_string(chan->state));
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03005487
Andrei Emeltchenko78eb2f92012-07-19 17:03:47 +03005488 if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
5489 l2cap_chan_unlock(chan);
5490 continue;
5491 }
5492
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03005493 if (chan->scid == L2CAP_CID_LE_DATA) {
5494 if (!status && encrypt) {
5495 chan->sec_level = hcon->sec_level;
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02005496 l2cap_chan_ready(chan);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03005497 }
5498
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02005499 l2cap_chan_unlock(chan);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03005500 continue;
5501 }
5502
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03005503 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02005504 l2cap_chan_unlock(chan);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01005505 continue;
5506 }
5507
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03005508 if (!status && (chan->state == BT_CONNECTED ||
Gustavo Padovan2d792812012-10-06 10:07:01 +01005509 chan->state == BT_CONFIG)) {
Gustavo Padovana7d77232012-05-13 03:20:07 -03005510 struct sock *sk = chan->sk;
5511
Gustavo Padovanc5daa682012-05-16 12:17:10 -03005512 clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
Gustavo Padovana7d77232012-05-13 03:20:07 -03005513 sk->sk_state_change(sk);
5514
Gustavo F. Padovan43434782011-04-12 18:31:57 -03005515 l2cap_check_encryption(chan, encrypt);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02005516 l2cap_chan_unlock(chan);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02005517 continue;
5518 }
5519
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03005520 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02005521 if (!status) {
Andrei Emeltchenko93c3e8f2012-09-27 17:26:16 +03005522 l2cap_start_connection(chan);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02005523 } else {
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08005524 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02005525 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03005526 } else if (chan->state == BT_CONNECT2) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02005527 struct sock *sk = chan->sk;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02005528 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03005529 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02005530
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02005531 lock_sock(sk);
5532
Marcel Holtmannb1235d72008-07-14 20:13:54 +02005533 if (!status) {
Gustavo Padovanc5daa682012-05-16 12:17:10 -03005534 if (test_bit(BT_SK_DEFER_SETUP,
5535 &bt_sk(sk)->flags)) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03005536 res = L2CAP_CR_PEND;
5537 stat = L2CAP_CS_AUTHOR_PEND;
Gustavo Padovan2dc4e512012-10-12 19:35:24 +08005538 chan->ops->defer(chan);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03005539 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02005540 __l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03005541 res = L2CAP_CR_SUCCESS;
5542 stat = L2CAP_CS_NO_INFO;
5543 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02005544 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02005545 __l2cap_state_change(chan, BT_DISCONN);
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08005546 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03005547 res = L2CAP_CR_SEC_BLOCK;
5548 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02005549 }
5550
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02005551 release_sock(sk);
5552
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03005553 rsp.scid = cpu_to_le16(chan->dcid);
5554 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03005555 rsp.result = cpu_to_le16(res);
5556 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03005557 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
Gustavo Padovan2d792812012-10-06 10:07:01 +01005558 sizeof(rsp), &rsp);
Mat Martineau2d369352012-05-23 14:59:30 -07005559
5560 if (!test_bit(CONF_REQ_SENT, &chan->conf_state) &&
5561 res == L2CAP_CR_SUCCESS) {
5562 char buf[128];
5563 set_bit(CONF_REQ_SENT, &chan->conf_state);
5564 l2cap_send_cmd(conn, l2cap_get_ident(conn),
5565 L2CAP_CONF_REQ,
5566 l2cap_build_conf_req(chan, buf),
5567 buf);
5568 chan->num_conf_req++;
5569 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005570 }
5571
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02005572 l2cap_chan_unlock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005573 }
5574
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02005575 mutex_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02005576
Linus Torvalds1da177e2005-04-16 15:20:36 -07005577 return 0;
5578}
5579
Ulisses Furquim686ebf22011-12-21 10:11:33 -02005580int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005581{
5582 struct l2cap_conn *conn = hcon->l2cap_data;
Andrei Emeltchenkod73a0982012-10-15 11:58:40 +03005583 struct l2cap_hdr *hdr;
5584 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005585
Andrei Emeltchenko1d13a252012-10-15 11:58:41 +03005586 /* For AMP controller do not create l2cap conn */
5587 if (!conn && hcon->hdev->dev_type != HCI_BREDR)
5588 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005589
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02005590 if (!conn)
5591 conn = l2cap_conn_add(hcon, 0);
5592
5593 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005594 goto drop;
5595
5596 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
5597
Andrei Emeltchenkod73a0982012-10-15 11:58:40 +03005598 switch (flags) {
5599 case ACL_START:
5600 case ACL_START_NO_FLUSH:
5601 case ACL_COMPLETE:
Linus Torvalds1da177e2005-04-16 15:20:36 -07005602 if (conn->rx_len) {
5603 BT_ERR("Unexpected start frame (len %d)", skb->len);
5604 kfree_skb(conn->rx_skb);
5605 conn->rx_skb = NULL;
5606 conn->rx_len = 0;
5607 l2cap_conn_unreliable(conn, ECOMM);
5608 }
5609
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03005610 /* Start fragment always begin with Basic L2CAP header */
5611 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005612 BT_ERR("Frame is too short (len %d)", skb->len);
5613 l2cap_conn_unreliable(conn, ECOMM);
5614 goto drop;
5615 }
5616
5617 hdr = (struct l2cap_hdr *) skb->data;
5618 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
5619
5620 if (len == skb->len) {
5621 /* Complete frame received */
5622 l2cap_recv_frame(conn, skb);
5623 return 0;
5624 }
5625
5626 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
5627
5628 if (skb->len > len) {
5629 BT_ERR("Frame is too long (len %d, expected len %d)",
Gustavo Padovan2d792812012-10-06 10:07:01 +01005630 skb->len, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005631 l2cap_conn_unreliable(conn, ECOMM);
5632 goto drop;
5633 }
5634
5635 /* Allocate skb for the complete frame (with header) */
Gustavo Padovan8bcde1f2012-05-28 19:18:14 -03005636 conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL);
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03005637 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005638 goto drop;
5639
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03005640 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Gustavo Padovan2d792812012-10-06 10:07:01 +01005641 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005642 conn->rx_len = len - skb->len;
Andrei Emeltchenkod73a0982012-10-15 11:58:40 +03005643 break;
5644
5645 case ACL_CONT:
Linus Torvalds1da177e2005-04-16 15:20:36 -07005646 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
5647
5648 if (!conn->rx_len) {
5649 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
5650 l2cap_conn_unreliable(conn, ECOMM);
5651 goto drop;
5652 }
5653
5654 if (skb->len > conn->rx_len) {
5655 BT_ERR("Fragment is too long (len %d, expected %d)",
Gustavo Padovan2d792812012-10-06 10:07:01 +01005656 skb->len, conn->rx_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005657 kfree_skb(conn->rx_skb);
5658 conn->rx_skb = NULL;
5659 conn->rx_len = 0;
5660 l2cap_conn_unreliable(conn, ECOMM);
5661 goto drop;
5662 }
5663
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03005664 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Gustavo Padovan2d792812012-10-06 10:07:01 +01005665 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005666 conn->rx_len -= skb->len;
5667
5668 if (!conn->rx_len) {
5669 /* Complete frame received */
5670 l2cap_recv_frame(conn, conn->rx_skb);
5671 conn->rx_skb = NULL;
5672 }
Andrei Emeltchenkod73a0982012-10-15 11:58:40 +03005673 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005674 }
5675
5676drop:
5677 kfree_skb(skb);
5678 return 0;
5679}
5680
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005681static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005682{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005683 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005684
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02005685 read_lock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005686
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005687 list_for_each_entry(c, &chan_list, global_l) {
5688 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005689
Andrei Emeltchenkofcb73332012-09-25 12:49:44 +03005690 seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
5691 &bt_sk(sk)->src, &bt_sk(sk)->dst,
5692 c->state, __le16_to_cpu(c->psm),
5693 c->scid, c->dcid, c->imtu, c->omtu,
5694 c->sec_level, c->mode);
Andrei Emeltchenko61e1b4b2012-01-19 11:19:50 +02005695 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005696
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02005697 read_unlock(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08005698
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005699 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005700}
5701
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005702static int l2cap_debugfs_open(struct inode *inode, struct file *file)
5703{
5704 return single_open(file, l2cap_debugfs_show, inode->i_private);
5705}
5706
5707static const struct file_operations l2cap_debugfs_fops = {
5708 .open = l2cap_debugfs_open,
5709 .read = seq_read,
5710 .llseek = seq_lseek,
5711 .release = single_release,
5712};
5713
5714static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005715
Gustavo F. Padovan64274512011-02-07 20:08:52 -02005716int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005717{
5718 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08005719
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02005720 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005721 if (err < 0)
5722 return err;
5723
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005724 if (bt_debugfs) {
Gustavo Padovan2d792812012-10-06 10:07:01 +01005725 l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
5726 NULL, &l2cap_debugfs_fops);
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005727 if (!l2cap_debugfs)
5728 BT_ERR("Failed to create L2CAP debug file");
5729 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005730
Linus Torvalds1da177e2005-04-16 15:20:36 -07005731 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005732}
5733
Gustavo F. Padovan64274512011-02-07 20:08:52 -02005734void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005735{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005736 debugfs_remove(l2cap_debugfs);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02005737 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005738}
5739
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03005740module_param(disable_ertm, bool, 0644);
5741MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");