blob: 1192c943bf8e88c6c9ef15691564a8396f0a4de7 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Gustavo F. Padovan590051d2011-12-18 13:39:33 -02006 Copyright (C) 2011 ProFUSION Embedded Systems
Linus Torvalds1da177e2005-04-16 15:20:36 -07007
8 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License version 2 as
12 published by the Free Software Foundation;
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
17 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090018 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090023 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
24 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070025 SOFTWARE IS DISCLAIMED.
26*/
27
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020028/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070029
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/module.h>
31
32#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080033#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/errno.h>
35#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/sched.h>
37#include <linux/slab.h>
38#include <linux/poll.h>
39#include <linux/fcntl.h>
40#include <linux/init.h>
41#include <linux/interrupt.h>
42#include <linux/socket.h>
43#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080045#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010046#include <linux/debugfs.h>
47#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030048#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030049#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#include <net/sock.h>
51
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
Anderson Brigliab501d6a2011-06-07 18:46:31 -030057#include <net/bluetooth/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
Rusty Russelleb939922011-12-19 14:08:01 +000059bool disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020060
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070061static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Mat Martineau50a147c2011-11-02 16:18:34 -070062static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
Johannes Bergb5ad8b72011-06-01 08:54:45 +020064static LIST_HEAD(chan_list);
65static DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
Linus Torvalds1da177e2005-04-16 15:20:36 -070067static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
68 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030069static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
70 void *data);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -030071static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030072static void l2cap_send_disconn_req(struct l2cap_conn *conn,
73 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Marcel Holtmann01394182006-07-03 10:02:46 +020075/* ---- L2CAP channels ---- */
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -030076
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030077static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020078{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020079 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030080
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020081 list_for_each_entry(c, &conn->chan_l, list) {
82 if (c->dcid == cid)
83 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020084 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020085 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +020086}
87
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030088static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020089{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020090 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030091
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020092 list_for_each_entry(c, &conn->chan_l, list) {
93 if (c->scid == cid)
94 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020095 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +020096 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +020097}
98
99/* Find channel with given SCID.
100 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300101static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200102{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300103 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300104
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200105 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300106 c = __l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200107 mutex_unlock(&conn->chan_lock);
108
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300109 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200110}
111
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300112static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200113{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200114 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300115
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200116 list_for_each_entry(c, &conn->chan_l, list) {
117 if (c->ident == ident)
118 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200119 }
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200120 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200121}
122
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300123static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300124{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300125 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300126
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300127 list_for_each_entry(c, &chan_list, global_l) {
128 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Szymon Janc250938c2011-11-16 09:32:22 +0100129 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300130 }
Szymon Janc250938c2011-11-16 09:32:22 +0100131 return NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300132}
133
134int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
135{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300136 int err;
137
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200138 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300139
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300140 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300141 err = -EADDRINUSE;
142 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300143 }
144
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300145 if (psm) {
146 chan->psm = psm;
147 chan->sport = psm;
148 err = 0;
149 } else {
150 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300151
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300152 err = -EINVAL;
153 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300154 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300155 chan->psm = cpu_to_le16(p);
156 chan->sport = cpu_to_le16(p);
157 err = 0;
158 break;
159 }
160 }
161
162done:
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200163 write_unlock(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300164 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300165}
166
167int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
168{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200169 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300170
171 chan->scid = scid;
172
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200173 write_unlock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300174
175 return 0;
176}
177
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300178static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200179{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300180 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200181
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300182 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300183 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200184 return cid;
185 }
186
187 return 0;
188}
189
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200190static void __l2cap_state_change(struct l2cap_chan *chan, int state)
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300191{
Andrei Emeltchenko42d2d872012-02-17 11:40:57 +0200192 BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
Gustavo F. Padovanbadaaa02011-11-23 20:11:46 -0200193 state_to_string(state));
194
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300195 chan->state = state;
196 chan->ops->state_change(chan->data, state);
197}
198
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200199static void l2cap_state_change(struct l2cap_chan *chan, int state)
200{
201 struct sock *sk = chan->sk;
202
203 lock_sock(sk);
204 __l2cap_state_change(chan, state);
205 release_sock(sk);
206}
207
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +0200208static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err)
209{
210 struct sock *sk = chan->sk;
211
212 sk->sk_err = err;
213}
214
215static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
216{
217 struct sock *sk = chan->sk;
218
219 lock_sock(sk);
220 __l2cap_chan_set_err(chan, err);
221 release_sock(sk);
222}
223
Mat Martineau3c588192012-04-11 10:48:42 -0700224/* ---- L2CAP sequence number lists ---- */
225
226/* For ERTM, ordered lists of sequence numbers must be tracked for
227 * SREJ requests that are received and for frames that are to be
228 * retransmitted. These seq_list functions implement a singly-linked
229 * list in an array, where membership in the list can also be checked
230 * in constant time. Items can also be added to the tail of the list
231 * and removed from the head in constant time, without further memory
232 * allocs or frees.
233 */
234
235static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
236{
237 size_t alloc_size, i;
238
239 /* Allocated size is a power of 2 to map sequence numbers
240 * (which may be up to 14 bits) in to a smaller array that is
241 * sized for the negotiated ERTM transmit windows.
242 */
243 alloc_size = roundup_pow_of_two(size);
244
245 seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL);
246 if (!seq_list->list)
247 return -ENOMEM;
248
249 seq_list->mask = alloc_size - 1;
250 seq_list->head = L2CAP_SEQ_LIST_CLEAR;
251 seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
252 for (i = 0; i < alloc_size; i++)
253 seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
254
255 return 0;
256}
257
258static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
259{
260 kfree(seq_list->list);
261}
262
263static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
264 u16 seq)
265{
266 /* Constant-time check for list membership */
267 return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
268}
269
270static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq)
271{
272 u16 mask = seq_list->mask;
273
274 if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) {
275 /* In case someone tries to pop the head of an empty list */
276 return L2CAP_SEQ_LIST_CLEAR;
277 } else if (seq_list->head == seq) {
278 /* Head can be removed in constant time */
279 seq_list->head = seq_list->list[seq & mask];
280 seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
281
282 if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
283 seq_list->head = L2CAP_SEQ_LIST_CLEAR;
284 seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
285 }
286 } else {
287 /* Walk the list to find the sequence number */
288 u16 prev = seq_list->head;
289 while (seq_list->list[prev & mask] != seq) {
290 prev = seq_list->list[prev & mask];
291 if (prev == L2CAP_SEQ_LIST_TAIL)
292 return L2CAP_SEQ_LIST_CLEAR;
293 }
294
295 /* Unlink the number from the list and clear it */
296 seq_list->list[prev & mask] = seq_list->list[seq & mask];
297 seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
298 if (seq_list->tail == seq)
299 seq_list->tail = prev;
300 }
301 return seq;
302}
303
304static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
305{
306 /* Remove the head in constant time */
307 return l2cap_seq_list_remove(seq_list, seq_list->head);
308}
309
310static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
311{
312 if (seq_list->head != L2CAP_SEQ_LIST_CLEAR) {
313 u16 i;
314 for (i = 0; i <= seq_list->mask; i++)
315 seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
316
317 seq_list->head = L2CAP_SEQ_LIST_CLEAR;
318 seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
319 }
320}
321
322static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
323{
324 u16 mask = seq_list->mask;
325
326 /* All appends happen in constant time */
327
328 if (seq_list->list[seq & mask] == L2CAP_SEQ_LIST_CLEAR) {
329 if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
330 seq_list->head = seq;
331 else
332 seq_list->list[seq_list->tail & mask] = seq;
333
334 seq_list->tail = seq;
335 seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
336 }
337}
338
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300339static void l2cap_chan_timeout(struct work_struct *work)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300340{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300341 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
342 chan_timer.work);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200343 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300344 int reason;
345
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200346 BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300347
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200348 mutex_lock(&conn->chan_lock);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200349 l2cap_chan_lock(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300350
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300351 if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300352 reason = ECONNREFUSED;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300353 else if (chan->state == BT_CONNECT &&
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300354 chan->sec_level != BT_SECURITY_SDP)
355 reason = ECONNREFUSED;
356 else
357 reason = ETIMEDOUT;
358
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300359 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300360
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200361 l2cap_chan_unlock(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300362
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300363 chan->ops->close(chan->data);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200364 mutex_unlock(&conn->chan_lock);
365
Ulisses Furquim371fd832011-12-21 20:02:36 -0200366 l2cap_chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300367}
368
Gustavo Padovaneef1d9b2012-03-25 13:59:16 -0300369struct l2cap_chan *l2cap_chan_create(void)
Marcel Holtmann01394182006-07-03 10:02:46 +0200370{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300371 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200372
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300373 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
374 if (!chan)
375 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200376
Andrei Emeltchenkoc03b3552012-02-21 12:54:56 +0200377 mutex_init(&chan->lock);
378
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200379 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300380 list_add(&chan->global_l, &chan_list);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200381 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300382
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300383 INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300384
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300385 chan->state = BT_OPEN;
386
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300387 atomic_set(&chan->refcnt, 1);
388
Gustavo Padovaneef1d9b2012-03-25 13:59:16 -0300389 BT_DBG("chan %p", chan);
Szymon Jancabc545b2011-11-03 16:05:44 +0100390
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300391 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200392}
393
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300394void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300395{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200396 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300397 list_del(&chan->global_l);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200398 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300399
Ulisses Furquim371fd832011-12-21 20:02:36 -0200400 l2cap_chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300401}
402
Andrei Emeltchenkobd4b1652012-03-28 16:31:25 +0300403void l2cap_chan_set_defaults(struct l2cap_chan *chan)
404{
405 chan->fcs = L2CAP_FCS_CRC16;
406 chan->max_tx = L2CAP_DEFAULT_MAX_TX;
407 chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
408 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
409 chan->sec_level = BT_SECURITY_LOW;
410
411 set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
412}
413
Andrei Emeltchenko14a28492012-03-23 16:31:49 +0200414static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200415{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300416 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Andrei Emeltchenko097db762012-03-09 14:16:17 +0200417 __le16_to_cpu(chan->psm), chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200418
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +0200419 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +0100420
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300421 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200422
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200423 switch (chan->chan_type) {
424 case L2CAP_CHAN_CONN_ORIENTED:
Ville Tervob62f3282011-02-10 22:38:50 -0300425 if (conn->hcon->type == LE_LINK) {
426 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300427 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300428 chan->scid = L2CAP_CID_LE_DATA;
429 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300430 } else {
431 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300432 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300433 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300434 }
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200435 break;
436
437 case L2CAP_CHAN_CONN_LESS:
Marcel Holtmann01394182006-07-03 10:02:46 +0200438 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300439 chan->scid = L2CAP_CID_CONN_LESS;
440 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300441 chan->omtu = L2CAP_DEFAULT_MTU;
Andrei Emeltchenko54911202012-02-06 15:04:00 +0200442 break;
443
444 default:
Marcel Holtmann01394182006-07-03 10:02:46 +0200445 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300446 chan->scid = L2CAP_CID_SIGNALING;
447 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300448 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200449 }
450
Andrei Emeltchenko8f7975b2011-10-13 16:18:54 +0300451 chan->local_id = L2CAP_BESTEFFORT_ID;
452 chan->local_stype = L2CAP_SERV_BESTEFFORT;
453 chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
454 chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
455 chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
456 chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
457
Ulisses Furquim371fd832011-12-21 20:02:36 -0200458 l2cap_chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300459
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200460 list_add(&chan->list, &conn->chan_l);
Andrei Emeltchenko643162a2012-02-22 17:11:55 +0200461}
462
Andrei Emeltchenko14a28492012-03-23 16:31:49 +0200463static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Andrei Emeltchenko643162a2012-02-22 17:11:55 +0200464{
465 mutex_lock(&conn->chan_lock);
466 __l2cap_chan_add(conn, chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200467 mutex_unlock(&conn->chan_lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200468}
469
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300470static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200471{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300472 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300473 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200474 struct sock *parent = bt_sk(sk)->parent;
475
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300476 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200477
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300478 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200479
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900480 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300481 /* Delete from channel list */
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200482 list_del(&chan->list);
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200483
Ulisses Furquim371fd832011-12-21 20:02:36 -0200484 l2cap_chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300485
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300486 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200487 hci_conn_put(conn->hcon);
488 }
489
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200490 lock_sock(sk);
491
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200492 __l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200493 sock_set_flag(sk, SOCK_ZAPPED);
494
495 if (err)
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +0200496 __l2cap_chan_set_err(chan, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200497
498 if (parent) {
499 bt_accept_unlink(sk);
500 parent->sk_data_ready(parent, 0);
501 } else
502 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300503
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200504 release_sock(sk);
505
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300506 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
507 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300508 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300509
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300510 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300511
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300512 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300513 struct srej_list *l, *tmp;
514
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300515 __clear_retrans_timer(chan);
516 __clear_monitor_timer(chan);
517 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300518
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300519 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300520
Mat Martineau3c588192012-04-11 10:48:42 -0700521 l2cap_seq_list_free(&chan->srej_list);
522 l2cap_seq_list_free(&chan->retrans_list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300523 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300524 list_del(&l->list);
525 kfree(l);
526 }
527 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200528}
529
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300530static void l2cap_chan_cleanup_listen(struct sock *parent)
531{
532 struct sock *sk;
533
534 BT_DBG("parent %p", parent);
535
536 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300537 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300538 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200539
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200540 l2cap_chan_lock(chan);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300541 __clear_chan_timer(chan);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300542 l2cap_chan_close(chan, ECONNRESET);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200543 l2cap_chan_unlock(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +0200544
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300545 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300546 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300547}
548
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300549void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300550{
551 struct l2cap_conn *conn = chan->conn;
552 struct sock *sk = chan->sk;
553
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200554 BT_DBG("chan %p state %s sk %p", chan,
555 state_to_string(chan->state), sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300556
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300557 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300558 case BT_LISTEN:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200559 lock_sock(sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300560 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300561
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200562 __l2cap_state_change(chan, BT_CLOSED);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300563 sock_set_flag(sk, SOCK_ZAPPED);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200564 release_sock(sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300565 break;
566
567 case BT_CONNECTED:
568 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300569 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300570 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300571 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300572 l2cap_send_disconn_req(conn, chan, reason);
573 } else
574 l2cap_chan_del(chan, reason);
575 break;
576
577 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300578 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300579 conn->hcon->type == ACL_LINK) {
580 struct l2cap_conn_rsp rsp;
581 __u16 result;
582
583 if (bt_sk(sk)->defer_setup)
584 result = L2CAP_CR_SEC_BLOCK;
585 else
586 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300587 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300588
589 rsp.scid = cpu_to_le16(chan->dcid);
590 rsp.dcid = cpu_to_le16(chan->scid);
591 rsp.result = cpu_to_le16(result);
592 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
593 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
594 sizeof(rsp), &rsp);
595 }
596
597 l2cap_chan_del(chan, reason);
598 break;
599
600 case BT_CONNECT:
601 case BT_DISCONN:
602 l2cap_chan_del(chan, reason);
603 break;
604
605 default:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200606 lock_sock(sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300607 sock_set_flag(sk, SOCK_ZAPPED);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200608 release_sock(sk);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300609 break;
610 }
611}
612
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300613static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530614{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300615 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300616 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530617 case BT_SECURITY_HIGH:
618 return HCI_AT_DEDICATED_BONDING_MITM;
619 case BT_SECURITY_MEDIUM:
620 return HCI_AT_DEDICATED_BONDING;
621 default:
622 return HCI_AT_NO_BONDING;
623 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300624 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300625 if (chan->sec_level == BT_SECURITY_LOW)
626 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530627
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300628 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530629 return HCI_AT_NO_BONDING_MITM;
630 else
631 return HCI_AT_NO_BONDING;
632 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300633 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530634 case BT_SECURITY_HIGH:
635 return HCI_AT_GENERAL_BONDING_MITM;
636 case BT_SECURITY_MEDIUM:
637 return HCI_AT_GENERAL_BONDING;
638 default:
639 return HCI_AT_NO_BONDING;
640 }
641 }
642}
643
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200644/* Service level security */
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200645int l2cap_chan_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200646{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300647 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100648 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200649
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300650 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100651
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300652 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200653}
654
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200655static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200656{
657 u8 id;
658
659 /* Get next available identificator.
660 * 1 - 128 are used by kernel.
661 * 129 - 199 are reserved.
662 * 200 - 254 are used by utilities like l2ping, etc.
663 */
664
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200665 spin_lock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200666
667 if (++conn->tx_ident > 128)
668 conn->tx_ident = 1;
669
670 id = conn->tx_ident;
671
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200672 spin_unlock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200673
674 return id;
675}
676
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300677static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200678{
679 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200680 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200681
682 BT_DBG("code 0x%2.2x", code);
683
684 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300685 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200686
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200687 if (lmp_no_flush_capable(conn->hcon->hdev))
688 flags = ACL_START_NO_FLUSH;
689 else
690 flags = ACL_START;
691
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700692 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +0200693 skb->priority = HCI_PRIO_MAX;
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700694
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200695 hci_send_acl(conn->hchan, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200696}
697
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200698static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
699{
700 struct hci_conn *hcon = chan->conn->hcon;
701 u16 flags;
702
703 BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
704 skb->priority);
705
706 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
707 lmp_no_flush_capable(hcon->hdev))
708 flags = ACL_START_NO_FLUSH;
709 else
710 flags = ACL_START;
711
712 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
713 hci_send_acl(chan->conn->hchan, skb, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714}
715
Mat Martineaub5c6aae2012-04-25 16:36:15 -0700716static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
717{
718 control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
719 control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
720
721 if (enh & L2CAP_CTRL_FRAME_TYPE) {
722 /* S-Frame */
723 control->sframe = 1;
724 control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
725 control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
726
727 control->sar = 0;
728 control->txseq = 0;
729 } else {
730 /* I-Frame */
731 control->sframe = 0;
732 control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
733 control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
734
735 control->poll = 0;
736 control->super = 0;
737 }
738}
739
740static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
741{
742 control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
743 control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
744
745 if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
746 /* S-Frame */
747 control->sframe = 1;
748 control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
749 control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
750
751 control->sar = 0;
752 control->txseq = 0;
753 } else {
754 /* I-Frame */
755 control->sframe = 0;
756 control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
757 control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
758
759 control->poll = 0;
760 control->super = 0;
761 }
762}
763
764static inline void __unpack_control(struct l2cap_chan *chan,
765 struct sk_buff *skb)
766{
767 if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
768 __unpack_extended_control(get_unaligned_le32(skb->data),
769 &bt_cb(skb)->control);
770 } else {
771 __unpack_enhanced_control(get_unaligned_le16(skb->data),
772 &bt_cb(skb)->control);
773 }
774}
775
776static u32 __pack_extended_control(struct l2cap_ctrl *control)
777{
778 u32 packed;
779
780 packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
781 packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
782
783 if (control->sframe) {
784 packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
785 packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
786 packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
787 } else {
788 packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
789 packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
790 }
791
792 return packed;
793}
794
795static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
796{
797 u16 packed;
798
799 packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
800 packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
801
802 if (control->sframe) {
803 packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
804 packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
805 packed |= L2CAP_CTRL_FRAME_TYPE;
806 } else {
807 packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
808 packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
809 }
810
811 return packed;
812}
813
814static inline void __pack_control(struct l2cap_chan *chan,
815 struct l2cap_ctrl *control,
816 struct sk_buff *skb)
817{
818 if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
819 put_unaligned_le32(__pack_extended_control(control),
820 skb->data + L2CAP_HDR_SIZE);
821 } else {
822 put_unaligned_le16(__pack_enhanced_control(control),
823 skb->data + L2CAP_HDR_SIZE);
824 }
825}
826
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300827static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300828{
829 struct sk_buff *skb;
830 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300831 struct l2cap_conn *conn = chan->conn;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300832 int count, hlen;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300833
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300834 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300835 return;
836
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300837 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
838 hlen = L2CAP_EXT_HDR_SIZE;
839 else
840 hlen = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300841
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300842 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300843 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300844
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300845 BT_DBG("chan %p, control 0x%8.8x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300846
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300847 count = min_t(unsigned int, conn->mtu, hlen);
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +0300848
849 control |= __set_sframe(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300850
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300851 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +0300852 control |= __set_ctrl_final(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300853
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300854 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +0300855 control |= __set_ctrl_poll(chan);
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300856
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300857 skb = bt_skb_alloc(count, GFP_ATOMIC);
858 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300859 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300860
861 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300862 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300863 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300864
865 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300866
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300867 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300868 u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
869 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300870 }
871
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200872 skb->priority = HCI_PRIO_MAX;
873 l2cap_do_send(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300874}
875
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300876static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300877{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300878 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300879 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300880 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300881 } else
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300882 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300883
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300884 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300885
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300886 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300887}
888
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300889static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300890{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300891 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300892}
893
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +0200894static void l2cap_send_conn_req(struct l2cap_chan *chan)
895{
896 struct l2cap_conn *conn = chan->conn;
897 struct l2cap_conn_req req;
898
899 req.scid = cpu_to_le16(chan->scid);
900 req.psm = chan->psm;
901
902 chan->ident = l2cap_get_ident(conn);
903
904 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
905
906 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
907}
908
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300909static void l2cap_chan_ready(struct l2cap_chan *chan)
910{
911 struct sock *sk = chan->sk;
912 struct sock *parent;
913
914 lock_sock(sk);
915
916 parent = bt_sk(sk)->parent;
917
918 BT_DBG("sk %p, parent %p", sk, parent);
919
920 chan->conf_state = 0;
921 __clear_chan_timer(chan);
922
923 __l2cap_state_change(chan, BT_CONNECTED);
924 sk->sk_state_change(sk);
925
926 if (parent)
927 parent->sk_data_ready(parent, 0);
928
929 release_sock(sk);
930}
931
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300932static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200933{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300934 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200935
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300936 if (conn->hcon->type == LE_LINK) {
937 l2cap_chan_ready(chan);
938 return;
939 }
940
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200941 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100942 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
943 return;
944
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200945 if (l2cap_chan_check_security(chan) &&
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +0200946 __l2cap_no_conn_pending(chan))
947 l2cap_send_conn_req(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200948 } else {
949 struct l2cap_info_req req;
950 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
951
952 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
953 conn->info_ident = l2cap_get_ident(conn);
954
Marcel Holtmannba13ccd2012-03-01 14:25:33 -0800955 schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200956
957 l2cap_send_cmd(conn, conn->info_ident,
958 L2CAP_INFO_REQ, sizeof(req), &req);
959 }
960}
961
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300962static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
963{
964 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300965 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300966 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
967
968 switch (mode) {
969 case L2CAP_MODE_ERTM:
970 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
971 case L2CAP_MODE_STREAMING:
972 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
973 default:
974 return 0x00;
975 }
976}
977
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300978static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300979{
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200980 struct sock *sk = chan->sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300981 struct l2cap_disconn_req req;
982
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300983 if (!conn)
984 return;
985
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300986 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300987 __clear_retrans_timer(chan);
988 __clear_monitor_timer(chan);
989 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300990 }
991
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300992 req.dcid = cpu_to_le16(chan->dcid);
993 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300994 l2cap_send_cmd(conn, l2cap_get_ident(conn),
995 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300996
Andrei Emeltchenko6be36552012-02-22 17:11:56 +0200997 lock_sock(sk);
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +0200998 __l2cap_state_change(chan, BT_DISCONN);
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +0200999 __l2cap_chan_set_err(chan, err);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001000 release_sock(sk);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -03001001}
1002
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001004static void l2cap_conn_start(struct l2cap_conn *conn)
1005{
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001006 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001007
1008 BT_DBG("conn %p", conn);
1009
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001010 mutex_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001011
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001012 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001013 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001014
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001015 l2cap_chan_lock(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001016
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001017 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001018 l2cap_chan_unlock(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001019 continue;
1020 }
1021
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001022 if (chan->state == BT_CONNECT) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001023 if (!l2cap_chan_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001024 !__l2cap_no_conn_pending(chan)) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001025 l2cap_chan_unlock(chan);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -03001026 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02001027 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -03001028
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001029 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1030 && test_bit(CONF_STATE2_DEVICE,
1031 &chan->conf_state)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001032 l2cap_chan_close(chan, ECONNRESET);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001033 l2cap_chan_unlock(chan);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -03001034 continue;
1035 }
1036
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +02001037 l2cap_send_conn_req(chan);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -03001038
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001039 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001040 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001041 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001042 rsp.scid = cpu_to_le16(chan->dcid);
1043 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001044
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001045 if (l2cap_chan_check_security(chan)) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001046 lock_sock(sk);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001047 if (bt_sk(sk)->defer_setup) {
1048 struct sock *parent = bt_sk(sk)->parent;
1049 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1050 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00001051 if (parent)
1052 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001053
1054 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001055 __l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001056 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1057 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1058 }
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001059 release_sock(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001060 } else {
1061 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1062 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
1063 }
1064
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001065 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1066 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001067
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001068 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001069 rsp.result != L2CAP_CR_SUCCESS) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001070 l2cap_chan_unlock(chan);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001071 continue;
1072 }
1073
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001074 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001075 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001076 l2cap_build_conf_req(chan, buf), buf);
1077 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001078 }
1079
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001080 l2cap_chan_unlock(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001081 }
1082
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001083 mutex_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001084}
1085
Ido Yarivc2287682012-04-20 15:46:07 -03001086/* Find socket with cid and source/destination bdaddr.
Ville Tervob62f3282011-02-10 22:38:50 -03001087 * Returns closest match, locked.
1088 */
Andrei Emeltchenkod9b88702012-03-12 12:13:08 +02001089static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
Ido Yarivc2287682012-04-20 15:46:07 -03001090 bdaddr_t *src,
1091 bdaddr_t *dst)
Ville Tervob62f3282011-02-10 22:38:50 -03001092{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001093 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -03001094
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001095 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -03001096
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001097 list_for_each_entry(c, &chan_list, global_l) {
1098 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001099
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001100 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -03001101 continue;
1102
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001103 if (c->scid == cid) {
Ido Yarivc2287682012-04-20 15:46:07 -03001104 int src_match, dst_match;
1105 int src_any, dst_any;
1106
Ville Tervob62f3282011-02-10 22:38:50 -03001107 /* Exact match. */
Ido Yarivc2287682012-04-20 15:46:07 -03001108 src_match = !bacmp(&bt_sk(sk)->src, src);
1109 dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1110 if (src_match && dst_match) {
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001111 read_unlock(&chan_list_lock);
1112 return c;
1113 }
Ville Tervob62f3282011-02-10 22:38:50 -03001114
1115 /* Closest match */
Ido Yarivc2287682012-04-20 15:46:07 -03001116 src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1117 dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1118 if ((src_match && dst_any) || (src_any && dst_match) ||
1119 (src_any && dst_any))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001120 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -03001121 }
1122 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -03001123
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001124 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -03001125
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001126 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -03001127}
1128
1129static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1130{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -03001131 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001132 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -03001133
1134 BT_DBG("");
1135
1136 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001137 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ido Yarivc2287682012-04-20 15:46:07 -03001138 conn->src, conn->dst);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001139 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -03001140 return;
1141
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001142 parent = pchan->sk;
1143
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001144 lock_sock(parent);
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -03001145
Ville Tervob62f3282011-02-10 22:38:50 -03001146 /* Check for backlog size */
1147 if (sk_acceptq_is_full(parent)) {
1148 BT_DBG("backlog full %d", parent->sk_ack_backlog);
1149 goto clean;
1150 }
1151
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03001152 chan = pchan->ops->new_connection(pchan->data);
1153 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -03001154 goto clean;
1155
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03001156 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001157
Ville Tervob62f3282011-02-10 22:38:50 -03001158 hci_conn_hold(conn->hcon);
1159
Ville Tervob62f3282011-02-10 22:38:50 -03001160 bacpy(&bt_sk(sk)->src, conn->src);
1161 bacpy(&bt_sk(sk)->dst, conn->dst);
1162
Gustavo F. Padovand1010242011-03-25 00:39:48 -03001163 bt_accept_enqueue(parent, sk);
1164
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001165 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001166
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001167 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -03001168
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001169 __l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -03001170 parent->sk_data_ready(parent, 0);
1171
Ville Tervob62f3282011-02-10 22:38:50 -03001172clean:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001173 release_sock(parent);
Ville Tervob62f3282011-02-10 22:38:50 -03001174}
1175
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001176static void l2cap_conn_ready(struct l2cap_conn *conn)
1177{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001178 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001179
1180 BT_DBG("conn %p", conn);
1181
Ville Tervob62f3282011-02-10 22:38:50 -03001182 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
1183 l2cap_le_conn_ready(conn);
1184
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03001185 if (conn->hcon->out && conn->hcon->type == LE_LINK)
1186 smp_conn_security(conn, conn->hcon->pending_sec_level);
1187
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001188 mutex_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001189
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001190 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001191
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001192 l2cap_chan_lock(chan);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001193
Vinicius Costa Gomes63128452011-06-17 22:46:26 -03001194 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -03001195 if (smp_conn_security(conn, chan->sec_level))
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02001196 l2cap_chan_ready(chan);
Ville Tervoacd7d372011-02-10 22:38:49 -03001197
Vinicius Costa Gomes63128452011-06-17 22:46:26 -03001198 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001199 struct sock *sk = chan->sk;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001200 __clear_chan_timer(chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001201 lock_sock(sk);
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02001202 __l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001203 sk->sk_state_change(sk);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001204 release_sock(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -03001205
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001206 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001207 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001208
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001209 l2cap_chan_unlock(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001210 }
1211
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001212 mutex_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001213}
1214
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001215/* Notify sockets that we cannot guaranty reliability anymore */
1216static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
1217{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001218 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001219
1220 BT_DBG("conn %p", conn);
1221
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001222 mutex_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001223
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001224 list_for_each_entry(chan, &conn->chan_l, list) {
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +03001225 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +02001226 __l2cap_chan_set_err(chan, err);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001227 }
1228
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001229 mutex_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001230}
1231
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -02001232static void l2cap_info_timeout(struct work_struct *work)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001233{
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -02001234 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02001235 info_timer.work);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001236
Marcel Holtmann984947d2009-02-06 23:35:19 +01001237 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01001238 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01001239
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001240 l2cap_conn_start(conn);
1241}
1242
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001243static void l2cap_conn_del(struct hci_conn *hcon, int err)
1244{
1245 struct l2cap_conn *conn = hcon->l2cap_data;
1246 struct l2cap_chan *chan, *l;
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001247
1248 if (!conn)
1249 return;
1250
1251 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
1252
1253 kfree_skb(conn->rx_skb);
1254
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001255 mutex_lock(&conn->chan_lock);
1256
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001257 /* Kill channels */
1258 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001259 l2cap_chan_lock(chan);
1260
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001261 l2cap_chan_del(chan, err);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001262
1263 l2cap_chan_unlock(chan);
1264
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001265 chan->ops->close(chan->data);
1266 }
1267
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001268 mutex_unlock(&conn->chan_lock);
1269
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001270 hci_chan_del(conn->hchan);
1271
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001272 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
Ulisses Furquim127074b2012-01-30 18:26:29 -02001273 cancel_delayed_work_sync(&conn->info_timer);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001274
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001275 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
Ulisses Furquim127074b2012-01-30 18:26:29 -02001276 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001277 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001278 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001279
1280 hcon->l2cap_data = NULL;
1281 kfree(conn);
1282}
1283
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001284static void security_timeout(struct work_struct *work)
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001285{
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001286 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1287 security_timer.work);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001288
1289 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1290}
1291
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1293{
Marcel Holtmann01394182006-07-03 10:02:46 +02001294 struct l2cap_conn *conn = hcon->l2cap_data;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001295 struct hci_chan *hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296
Marcel Holtmann01394182006-07-03 10:02:46 +02001297 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 return conn;
1299
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001300 hchan = hci_chan_create(hcon);
1301 if (!hchan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001304 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1305 if (!conn) {
1306 hci_chan_del(hchan);
1307 return NULL;
1308 }
1309
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 hcon->l2cap_data = conn;
1311 conn->hcon = hcon;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001312 conn->hchan = hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001314 BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
Marcel Holtmann01394182006-07-03 10:02:46 +02001315
Ville Tervoacd7d372011-02-10 22:38:49 -03001316 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1317 conn->mtu = hcon->hdev->le_mtu;
1318 else
1319 conn->mtu = hcon->hdev->acl_mtu;
1320
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 conn->src = &hcon->hdev->bdaddr;
1322 conn->dst = &hcon->dst;
1323
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001324 conn->feat_mask = 0;
1325
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 spin_lock_init(&conn->lock);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02001327 mutex_init(&conn->chan_lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001328
1329 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001331 if (hcon->type == LE_LINK)
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001332 INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001333 else
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02001334 INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
Dave Young45054dc2009-10-18 20:28:30 +00001335
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001336 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01001337
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 return conn;
1339}
1340
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342
Ido Yarivc2287682012-04-20 15:46:07 -03001343/* Find socket with psm and source / destination bdaddr.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 * Returns closest match.
1345 */
Ido Yarivc2287682012-04-20 15:46:07 -03001346static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1347 bdaddr_t *src,
1348 bdaddr_t *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001350 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001352 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001353
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001354 list_for_each_entry(c, &chan_list, global_l) {
1355 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001356
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001357 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 continue;
1359
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001360 if (c->psm == psm) {
Ido Yarivc2287682012-04-20 15:46:07 -03001361 int src_match, dst_match;
1362 int src_any, dst_any;
1363
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 /* Exact match. */
Ido Yarivc2287682012-04-20 15:46:07 -03001365 src_match = !bacmp(&bt_sk(sk)->src, src);
1366 dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1367 if (src_match && dst_match) {
Johannes Berga7567b22011-06-01 08:29:54 +02001368 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001369 return c;
1370 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
1372 /* Closest match */
Ido Yarivc2287682012-04-20 15:46:07 -03001373 src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1374 dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1375 if ((src_match && dst_any) || (src_any && dst_match) ||
1376 (src_any && dst_any))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001377 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 }
1379 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001381 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001382
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001383 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384}
1385
Andre Guedes8e9f9892012-04-24 21:02:55 -03001386int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
1387 bdaddr_t *dst, u8 dst_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001389 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 bdaddr_t *src = &bt_sk(sk)->src;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 struct l2cap_conn *conn;
1392 struct hci_conn *hcon;
1393 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001394 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001395 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396
Andre Guedes8e9f9892012-04-24 21:02:55 -03001397 BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst),
1398 dst_type, __le16_to_cpu(chan->psm));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001400 hdev = hci_get_route(dst, src);
1401 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 return -EHOSTUNREACH;
1403
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001404 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001406 l2cap_chan_lock(chan);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001407
1408 /* PSM must be odd and lsb of upper byte must be 0 */
1409 if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
1410 chan->chan_type != L2CAP_CHAN_RAW) {
1411 err = -EINVAL;
1412 goto done;
1413 }
1414
1415 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
1416 err = -EINVAL;
1417 goto done;
1418 }
1419
1420 switch (chan->mode) {
1421 case L2CAP_MODE_BASIC:
1422 break;
1423 case L2CAP_MODE_ERTM:
1424 case L2CAP_MODE_STREAMING:
1425 if (!disable_ertm)
1426 break;
1427 /* fall through */
1428 default:
1429 err = -ENOTSUPP;
1430 goto done;
1431 }
1432
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001433 lock_sock(sk);
1434
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001435 switch (sk->sk_state) {
1436 case BT_CONNECT:
1437 case BT_CONNECT2:
1438 case BT_CONFIG:
1439 /* Already connecting */
1440 err = 0;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001441 release_sock(sk);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001442 goto done;
1443
1444 case BT_CONNECTED:
1445 /* Already connected */
1446 err = -EISCONN;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001447 release_sock(sk);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001448 goto done;
1449
1450 case BT_OPEN:
1451 case BT_BOUND:
1452 /* Can connect */
1453 break;
1454
1455 default:
1456 err = -EBADFD;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001457 release_sock(sk);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001458 goto done;
1459 }
1460
1461 /* Set destination address and psm */
Gustavo F. Padovan9219b2a2012-01-02 20:08:04 -02001462 bacpy(&bt_sk(sk)->dst, dst);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001463
1464 release_sock(sk);
1465
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001466 chan->psm = psm;
1467 chan->dcid = cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001469 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001470
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001471 if (chan->dcid == L2CAP_CID_LE_DATA)
Andre Guedes8e9f9892012-04-24 21:02:55 -03001472 hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
Andre Guedesb12f62c2012-04-24 21:02:54 -03001473 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001474 else
Andre Guedes8e9f9892012-04-24 21:02:55 -03001475 hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
Andre Guedesb12f62c2012-04-24 21:02:54 -03001476 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001477
Ville Tervo30e76272011-02-22 16:10:53 -03001478 if (IS_ERR(hcon)) {
1479 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001481 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482
1483 conn = l2cap_conn_add(hcon, 0);
1484 if (!conn) {
1485 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001486 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 goto done;
1488 }
1489
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -03001490 if (hcon->type == LE_LINK) {
1491 err = 0;
1492
1493 if (!list_empty(&conn->chan_l)) {
1494 err = -EBUSY;
1495 hci_conn_put(hcon);
1496 }
1497
1498 if (err)
1499 goto done;
1500 }
1501
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 /* Update source addr of the socket */
1503 bacpy(src, conn->src);
1504
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001505 l2cap_chan_unlock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001506 l2cap_chan_add(conn, chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001507 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001508
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001509 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001510 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511
1512 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001513 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001514 __clear_chan_timer(chan);
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001515 if (l2cap_chan_check_security(chan))
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001516 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001517 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001518 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 }
1520
Ville Tervo30e76272011-02-22 16:10:53 -03001521 err = 0;
1522
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523done:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001524 l2cap_chan_unlock(chan);
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001525 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 hci_dev_put(hdev);
1527 return err;
1528}
1529
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001530int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001531{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001532 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001533 DECLARE_WAITQUEUE(wait, current);
1534 int err = 0;
1535 int timeo = HZ/5;
1536
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001537 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001538 set_current_state(TASK_INTERRUPTIBLE);
1539 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001540 if (!timeo)
1541 timeo = HZ/5;
1542
1543 if (signal_pending(current)) {
1544 err = sock_intr_errno(timeo);
1545 break;
1546 }
1547
1548 release_sock(sk);
1549 timeo = schedule_timeout(timeo);
1550 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001551 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001552
1553 err = sock_error(sk);
1554 if (err)
1555 break;
1556 }
1557 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001558 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001559 return err;
1560}
1561
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001562static void l2cap_monitor_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001563{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001564 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1565 monitor_timer.work);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001566
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001567 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001568
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001569 l2cap_chan_lock(chan);
1570
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001571 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001572 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001573 l2cap_chan_unlock(chan);
Andrei Emeltchenko8d7e1c72012-03-23 09:42:15 +02001574 l2cap_chan_put(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001575 return;
1576 }
1577
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001578 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001579 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001580
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001581 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001582 l2cap_chan_unlock(chan);
Andrei Emeltchenko8d7e1c72012-03-23 09:42:15 +02001583 l2cap_chan_put(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001584}
1585
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001586static void l2cap_retrans_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001587{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001588 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1589 retrans_timer.work);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001590
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001591 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001592
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001593 l2cap_chan_lock(chan);
1594
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001595 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001596 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001597
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001598 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001599
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001600 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02001601
1602 l2cap_chan_unlock(chan);
Andrei Emeltchenko8d7e1c72012-03-23 09:42:15 +02001603 l2cap_chan_put(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001604}
1605
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001606static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001607{
1608 struct sk_buff *skb;
1609
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001610 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001611 chan->unacked_frames) {
Mat Martineau3ce35142012-04-25 16:36:14 -07001612 if (bt_cb(skb)->control.txseq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001613 break;
1614
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001615 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001616 kfree_skb(skb);
1617
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001618 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001619 }
1620
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001621 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001622 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001623}
1624
Szymon Janc67c9e842011-07-28 16:24:33 +02001625static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001626{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001627 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001628 u32 control;
1629 u16 fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001630
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001631 while ((skb = skb_dequeue(&chan->tx_q))) {
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001632 control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001633 control |= __set_txseq(chan, chan->next_tx_seq);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001634 __put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001635
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001636 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001637 fcs = crc16(0, (u8 *)skb->data,
1638 skb->len - L2CAP_FCS_SIZE);
1639 put_unaligned_le16(fcs,
1640 skb->data + skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001641 }
1642
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001643 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001644
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001645 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001646 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001647}
1648
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001649static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001650{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001651 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001652 u16 fcs;
1653 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001654
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001655 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001656 if (!skb)
1657 return;
1658
Mat Martineau3ce35142012-04-25 16:36:14 -07001659 while (bt_cb(skb)->control.txseq != tx_seq) {
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001660 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001661 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001662
Szymon Jancd1726b62011-11-16 09:32:20 +01001663 skb = skb_queue_next(&chan->tx_q, skb);
1664 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001665
Mat Martineau3ce35142012-04-25 16:36:14 -07001666 if (bt_cb(skb)->control.retries == chan->remote_max_tx &&
1667 chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001668 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001669 return;
1670 }
1671
1672 tx_skb = skb_clone(skb, GFP_ATOMIC);
Mat Martineau3ce35142012-04-25 16:36:14 -07001673 bt_cb(skb)->control.retries++;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001674
1675 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001676 control &= __get_sar_mask(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001677
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001678 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001679 control |= __set_ctrl_final(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001680
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001681 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001682 control |= __set_txseq(chan, tx_seq);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001683
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001684 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001685
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001686 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001687 fcs = crc16(0, (u8 *)tx_skb->data,
1688 tx_skb->len - L2CAP_FCS_SIZE);
1689 put_unaligned_le16(fcs,
1690 tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001691 }
1692
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001693 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001694}
1695
Szymon Janc67c9e842011-07-28 16:24:33 +02001696static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001697{
1698 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001699 u16 fcs;
1700 u32 control;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001701 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001702
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001703 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001704 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001705
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001706 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001707
Mat Martineau3ce35142012-04-25 16:36:14 -07001708 if (bt_cb(skb)->control.retries == chan->remote_max_tx &&
1709 chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001710 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001711 break;
1712 }
1713
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001714 tx_skb = skb_clone(skb, GFP_ATOMIC);
1715
Mat Martineau3ce35142012-04-25 16:36:14 -07001716 bt_cb(skb)->control.retries++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001717
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001718 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001719 control &= __get_sar_mask(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001720
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001721 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001722 control |= __set_ctrl_final(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001723
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001724 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001725 control |= __set_txseq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001726
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001727 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001728
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001729 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001730 fcs = crc16(0, (u8 *)skb->data,
1731 tx_skb->len - L2CAP_FCS_SIZE);
1732 put_unaligned_le16(fcs, skb->data +
1733 tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001734 }
1735
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001736 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001737
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001738 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001739
Mat Martineau3ce35142012-04-25 16:36:14 -07001740 bt_cb(skb)->control.txseq = chan->next_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001741
1742 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001743
Mat Martineau3ce35142012-04-25 16:36:14 -07001744 if (bt_cb(skb)->control.retries == 1) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001745 chan->unacked_frames++;
Szymon Janc930fa4a2012-02-07 15:43:02 +01001746
1747 if (!nsent++)
1748 __clear_ack_timer(chan);
Szymon Janc8ed7a0a2012-02-07 15:43:01 +01001749 }
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301750
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001751 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001752
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001753 if (skb_queue_is_last(&chan->tx_q, skb))
1754 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001755 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001756 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001757 }
1758
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001759 return nsent;
1760}
1761
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001762static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001763{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001764 int ret;
1765
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001766 if (!skb_queue_empty(&chan->tx_q))
1767 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001768
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001769 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001770 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001771 return ret;
1772}
1773
Szymon Jancb17e73b2012-01-11 10:59:47 +01001774static void __l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001775{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001776 u32 control = 0;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001777
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001778 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001779
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001780 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001781 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001782 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001783 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001784 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001785 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001786
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001787 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001788 return;
1789
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001790 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001791 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001792}
1793
Szymon Jancb17e73b2012-01-11 10:59:47 +01001794static void l2cap_send_ack(struct l2cap_chan *chan)
1795{
1796 __clear_ack_timer(chan);
1797 __l2cap_send_ack(chan);
1798}
1799
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001800static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001801{
1802 struct srej_list *tail;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001803 u32 control;
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001804
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001805 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001806 control |= __set_ctrl_final(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001807
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001808 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001809 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001810
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001811 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001812}
1813
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001814static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
1815 struct msghdr *msg, int len,
1816 int count, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817{
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001818 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001819 struct sk_buff **frag;
Gustavo Padovan90338942012-04-06 20:15:47 -03001820 int sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001822 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001823 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824
1825 sent += count;
1826 len -= count;
1827
1828 /* Continuation fragments (no L2CAP header) */
1829 frag = &skb_shinfo(skb)->frag_list;
1830 while (len) {
1831 count = min_t(unsigned int, conn->mtu, len);
1832
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001833 *frag = chan->ops->alloc_skb(chan, count,
Gustavo Padovan90338942012-04-06 20:15:47 -03001834 msg->msg_flags & MSG_DONTWAIT);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001835
Gustavo Padovan90338942012-04-06 20:15:47 -03001836 if (IS_ERR(*frag))
1837 return PTR_ERR(*frag);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001838 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1839 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001841 (*frag)->priority = skb->priority;
1842
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 sent += count;
1844 len -= count;
1845
1846 frag = &(*frag)->next;
1847 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848
1849 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001850}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001852static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
1853 struct msghdr *msg, size_t len,
1854 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001855{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001856 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001857 struct sk_buff *skb;
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001858 int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001859 struct l2cap_hdr *lh;
1860
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001861 BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001862
1863 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001864
1865 skb = chan->ops->alloc_skb(chan, count + hlen,
Gustavo Padovan90338942012-04-06 20:15:47 -03001866 msg->msg_flags & MSG_DONTWAIT);
1867 if (IS_ERR(skb))
1868 return skb;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001869
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001870 skb->priority = priority;
1871
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001872 /* Create L2CAP header */
1873 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001874 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001875 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko097db762012-03-09 14:16:17 +02001876 put_unaligned(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001877
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001878 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001879 if (unlikely(err < 0)) {
1880 kfree_skb(skb);
1881 return ERR_PTR(err);
1882 }
1883 return skb;
1884}
1885
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001886static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
1887 struct msghdr *msg, size_t len,
1888 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001889{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001890 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001891 struct sk_buff *skb;
1892 int err, count, hlen = L2CAP_HDR_SIZE;
1893 struct l2cap_hdr *lh;
1894
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001895 BT_DBG("chan %p len %d", chan, (int)len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001896
1897 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001898
1899 skb = chan->ops->alloc_skb(chan, count + hlen,
Gustavo Padovan90338942012-04-06 20:15:47 -03001900 msg->msg_flags & MSG_DONTWAIT);
1901 if (IS_ERR(skb))
1902 return skb;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001903
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001904 skb->priority = priority;
1905
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001906 /* Create L2CAP header */
1907 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001908 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001909 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1910
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001911 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001912 if (unlikely(err < 0)) {
1913 kfree_skb(skb);
1914 return ERR_PTR(err);
1915 }
1916 return skb;
1917}
1918
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001919static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1920 struct msghdr *msg, size_t len,
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001921 u32 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001922{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001923 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001924 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001925 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001926 struct l2cap_hdr *lh;
1927
Andrei Emeltchenko6d5922b2012-02-06 15:04:01 +02001928 BT_DBG("chan %p len %d", chan, (int)len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001929
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001930 if (!conn)
1931 return ERR_PTR(-ENOTCONN);
1932
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001933 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1934 hlen = L2CAP_EXT_HDR_SIZE;
1935 else
1936 hlen = L2CAP_ENH_HDR_SIZE;
1937
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001938 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001939 hlen += L2CAP_SDULEN_SIZE;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001940
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001941 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001942 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001943
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001944 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001945
1946 skb = chan->ops->alloc_skb(chan, count + hlen,
Gustavo Padovan90338942012-04-06 20:15:47 -03001947 msg->msg_flags & MSG_DONTWAIT);
1948 if (IS_ERR(skb))
1949 return skb;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001950
1951 /* Create L2CAP header */
1952 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001953 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001954 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001955
1956 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
1957
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001958 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001959 put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001960
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001961 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001962 if (unlikely(err < 0)) {
1963 kfree_skb(skb);
1964 return ERR_PTR(err);
1965 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001966
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001967 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001968 put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001969
Mat Martineau3ce35142012-04-25 16:36:14 -07001970 bt_cb(skb)->control.retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001971 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972}
1973
Szymon Janc67c9e842011-07-28 16:24:33 +02001974static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001975{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001976 struct sk_buff *skb;
1977 struct sk_buff_head sar_queue;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001978 u32 control;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001979 size_t size = 0;
1980
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001981 skb_queue_head_init(&sar_queue);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001982 control = __set_ctrl_sar(chan, L2CAP_SAR_START);
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001983 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001984 if (IS_ERR(skb))
1985 return PTR_ERR(skb);
1986
1987 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001988 len -= chan->remote_mps;
1989 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001990
1991 while (len > 0) {
1992 size_t buflen;
1993
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001994 if (len > chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001995 control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001996 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001997 } else {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001998 control = __set_ctrl_sar(chan, L2CAP_SAR_END);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001999 buflen = len;
2000 }
2001
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002002 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002003 if (IS_ERR(skb)) {
2004 skb_queue_purge(&sar_queue);
2005 return PTR_ERR(skb);
2006 }
2007
2008 __skb_queue_tail(&sar_queue, skb);
2009 len -= buflen;
2010 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002011 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002012 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
2013 if (chan->tx_send_head == NULL)
2014 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002015
2016 return size;
2017}
2018
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02002019int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
2020 u32 priority)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002021{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002022 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03002023 u32 control;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002024 int err;
2025
2026 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03002027 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02002028 skb = l2cap_create_connless_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002029 if (IS_ERR(skb))
2030 return PTR_ERR(skb);
2031
2032 l2cap_do_send(chan, skb);
2033 return len;
2034 }
2035
2036 switch (chan->mode) {
2037 case L2CAP_MODE_BASIC:
2038 /* Check outgoing MTU */
2039 if (len > chan->omtu)
2040 return -EMSGSIZE;
2041
2042 /* Create a basic PDU */
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02002043 skb = l2cap_create_basic_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002044 if (IS_ERR(skb))
2045 return PTR_ERR(skb);
2046
2047 l2cap_do_send(chan, skb);
2048 err = len;
2049 break;
2050
2051 case L2CAP_MODE_ERTM:
2052 case L2CAP_MODE_STREAMING:
2053 /* Entire SDU fits into one PDU */
2054 if (len <= chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03002055 control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002056 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
2057 0);
2058 if (IS_ERR(skb))
2059 return PTR_ERR(skb);
2060
2061 __skb_queue_tail(&chan->tx_q, skb);
2062
2063 if (chan->tx_send_head == NULL)
2064 chan->tx_send_head = skb;
2065
2066 } else {
2067 /* Segment SDU into multiples PDUs */
2068 err = l2cap_sar_segment_sdu(chan, msg, len);
2069 if (err < 0)
2070 return err;
2071 }
2072
2073 if (chan->mode == L2CAP_MODE_STREAMING) {
2074 l2cap_streaming_send(chan);
2075 err = len;
2076 break;
2077 }
2078
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03002079 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
2080 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03002081 err = len;
2082 break;
2083 }
2084
2085 err = l2cap_ertm_send(chan);
2086 if (err >= 0)
2087 err = len;
2088
2089 break;
2090
2091 default:
2092 BT_DBG("bad state %1.1x", chan->mode);
2093 err = -EBADFD;
2094 }
2095
2096 return err;
2097}
2098
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099/* Copy frame to all raw sockets on that connection */
2100static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
2101{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002103 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104
2105 BT_DBG("conn %p", conn);
2106
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002107 mutex_lock(&conn->chan_lock);
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02002108
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002109 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002110 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03002111 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112 continue;
2113
2114 /* Don't send frame to the socket it came from */
2115 if (skb->sk == sk)
2116 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002117 nskb = skb_clone(skb, GFP_ATOMIC);
2118 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 continue;
2120
Gustavo F. Padovan23070492011-05-16 17:57:22 -03002121 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 kfree_skb(nskb);
2123 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02002124
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002125 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126}
2127
2128/* ---- L2CAP signalling commands ---- */
2129static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
2130 u8 code, u8 ident, u16 dlen, void *data)
2131{
2132 struct sk_buff *skb, **frag;
2133 struct l2cap_cmd_hdr *cmd;
2134 struct l2cap_hdr *lh;
2135 int len, count;
2136
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002137 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
2138 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139
2140 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
2141 count = min_t(unsigned int, conn->mtu, len);
2142
2143 skb = bt_skb_alloc(count, GFP_ATOMIC);
2144 if (!skb)
2145 return NULL;
2146
2147 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002148 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002149
2150 if (conn->hcon->type == LE_LINK)
2151 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
2152 else
2153 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154
2155 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
2156 cmd->code = code;
2157 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002158 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159
2160 if (dlen) {
2161 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
2162 memcpy(skb_put(skb, count), data, count);
2163 data += count;
2164 }
2165
2166 len -= skb->len;
2167
2168 /* Continuation fragments (no L2CAP header) */
2169 frag = &skb_shinfo(skb)->frag_list;
2170 while (len) {
2171 count = min_t(unsigned int, conn->mtu, len);
2172
2173 *frag = bt_skb_alloc(count, GFP_ATOMIC);
2174 if (!*frag)
2175 goto fail;
2176
2177 memcpy(skb_put(*frag, count), data, count);
2178
2179 len -= count;
2180 data += count;
2181
2182 frag = &(*frag)->next;
2183 }
2184
2185 return skb;
2186
2187fail:
2188 kfree_skb(skb);
2189 return NULL;
2190}
2191
2192static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
2193{
2194 struct l2cap_conf_opt *opt = *ptr;
2195 int len;
2196
2197 len = L2CAP_CONF_OPT_SIZE + opt->len;
2198 *ptr += len;
2199
2200 *type = opt->type;
2201 *olen = opt->len;
2202
2203 switch (opt->len) {
2204 case 1:
2205 *val = *((u8 *) opt->val);
2206 break;
2207
2208 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04002209 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 break;
2211
2212 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04002213 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 break;
2215
2216 default:
2217 *val = (unsigned long) opt->val;
2218 break;
2219 }
2220
2221 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
2222 return len;
2223}
2224
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
2226{
2227 struct l2cap_conf_opt *opt = *ptr;
2228
2229 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
2230
2231 opt->type = type;
2232 opt->len = len;
2233
2234 switch (len) {
2235 case 1:
2236 *((u8 *) opt->val) = val;
2237 break;
2238
2239 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02002240 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241 break;
2242
2243 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02002244 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245 break;
2246
2247 default:
2248 memcpy(opt->val, (void *) val, len);
2249 break;
2250 }
2251
2252 *ptr += L2CAP_CONF_OPT_SIZE + len;
2253}
2254
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002255static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
2256{
2257 struct l2cap_conf_efs efs;
2258
Szymon Janc1ec918c2011-11-16 09:32:21 +01002259 switch (chan->mode) {
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002260 case L2CAP_MODE_ERTM:
2261 efs.id = chan->local_id;
2262 efs.stype = chan->local_stype;
2263 efs.msdu = cpu_to_le16(chan->local_msdu);
2264 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
2265 efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
2266 efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
2267 break;
2268
2269 case L2CAP_MODE_STREAMING:
2270 efs.id = 1;
2271 efs.stype = L2CAP_SERV_BESTEFFORT;
2272 efs.msdu = cpu_to_le16(chan->local_msdu);
2273 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
2274 efs.acc_lat = 0;
2275 efs.flush_to = 0;
2276 break;
2277
2278 default:
2279 return;
2280 }
2281
2282 l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
2283 (unsigned long) &efs);
2284}
2285
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002286static void l2cap_ack_timeout(struct work_struct *work)
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002287{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002288 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2289 ack_timer.work);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002290
Gustavo F. Padovan2fb9b3d2011-12-22 16:56:05 -02002291 BT_DBG("chan %p", chan);
2292
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02002293 l2cap_chan_lock(chan);
2294
Szymon Jancb17e73b2012-01-11 10:59:47 +01002295 __l2cap_send_ack(chan);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02002296
2297 l2cap_chan_unlock(chan);
Szymon Janc09bfb2e2012-01-11 10:59:49 +01002298
2299 l2cap_chan_put(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002300}
2301
Mat Martineau3c588192012-04-11 10:48:42 -07002302static inline int l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002303{
Mat Martineau3c588192012-04-11 10:48:42 -07002304 int err;
2305
Mat Martineau105bdf92012-04-27 16:50:48 -07002306 chan->next_tx_seq = 0;
2307 chan->expected_tx_seq = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002308 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002309 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002310 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002311 chan->num_acked = 0;
2312 chan->frames_sent = 0;
Mat Martineau105bdf92012-04-27 16:50:48 -07002313 chan->last_acked_seq = 0;
2314 chan->sdu = NULL;
2315 chan->sdu_last_frag = NULL;
2316 chan->sdu_len = 0;
2317
2318 if (chan->mode != L2CAP_MODE_ERTM)
2319 return 0;
2320
2321 chan->rx_state = L2CAP_RX_STATE_RECV;
2322 chan->tx_state = L2CAP_TX_STATE_XMIT;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002323
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002324 INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2325 INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2326 INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002327
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002328 skb_queue_head_init(&chan->srej_q);
Mat Martineau105bdf92012-04-27 16:50:48 -07002329 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002330
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03002331 INIT_LIST_HEAD(&chan->srej_l);
Mat Martineau3c588192012-04-11 10:48:42 -07002332 err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
2333 if (err < 0)
2334 return err;
2335
2336 return l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002337}
2338
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002339static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2340{
2341 switch (mode) {
2342 case L2CAP_MODE_STREAMING:
2343 case L2CAP_MODE_ERTM:
2344 if (l2cap_mode_supported(mode, remote_feat_mask))
2345 return mode;
2346 /* fall through */
2347 default:
2348 return L2CAP_MODE_BASIC;
2349 }
2350}
2351
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002352static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
2353{
2354 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
2355}
2356
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002357static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2358{
2359 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2360}
2361
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002362static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
2363{
2364 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002365 __l2cap_ews_supported(chan)) {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002366 /* use extended control field */
2367 set_bit(FLAG_EXT_CTRL, &chan->flags);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002368 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2369 } else {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002370 chan->tx_win = min_t(u16, chan->tx_win,
2371 L2CAP_DEFAULT_TX_WINDOW);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002372 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2373 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002374}
2375
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002376static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002379 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380 void *ptr = req->data;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002381 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002383 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002385 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002386 goto done;
2387
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002388 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002389 case L2CAP_MODE_STREAMING:
2390 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002391 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002392 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002393
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002394 if (__l2cap_efs_supported(chan))
2395 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2396
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002397 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002398 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002399 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002400 break;
2401 }
2402
2403done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002404 if (chan->imtu != L2CAP_DEFAULT_MTU)
2405 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002406
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002407 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002408 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002409 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2410 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002411 break;
2412
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002413 rfc.mode = L2CAP_MODE_BASIC;
2414 rfc.txwin_size = 0;
2415 rfc.max_transmit = 0;
2416 rfc.retrans_timeout = 0;
2417 rfc.monitor_timeout = 0;
2418 rfc.max_pdu_size = 0;
2419
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002420 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2421 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002422 break;
2423
2424 case L2CAP_MODE_ERTM:
2425 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002426 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002427 rfc.retrans_timeout = 0;
2428 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002429
2430 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2431 L2CAP_EXT_HDR_SIZE -
2432 L2CAP_SDULEN_SIZE -
2433 L2CAP_FCS_SIZE);
2434 rfc.max_pdu_size = cpu_to_le16(size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002435
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002436 l2cap_txwin_setup(chan);
2437
2438 rfc.txwin_size = min_t(u16, chan->tx_win,
2439 L2CAP_DEFAULT_TX_WINDOW);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002440
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002441 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2442 (unsigned long) &rfc);
2443
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002444 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2445 l2cap_add_opt_efs(&ptr, chan);
2446
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002447 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002448 break;
2449
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002450 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002451 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002452 chan->fcs = L2CAP_FCS_NONE;
2453 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002454 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002455
2456 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2457 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2458 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002459 break;
2460
2461 case L2CAP_MODE_STREAMING:
2462 rfc.mode = L2CAP_MODE_STREAMING;
2463 rfc.txwin_size = 0;
2464 rfc.max_transmit = 0;
2465 rfc.retrans_timeout = 0;
2466 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002467
2468 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2469 L2CAP_EXT_HDR_SIZE -
2470 L2CAP_SDULEN_SIZE -
2471 L2CAP_FCS_SIZE);
2472 rfc.max_pdu_size = cpu_to_le16(size);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002473
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002474 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2475 (unsigned long) &rfc);
2476
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002477 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2478 l2cap_add_opt_efs(&ptr, chan);
2479
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002480 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002481 break;
2482
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002483 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002484 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002485 chan->fcs = L2CAP_FCS_NONE;
2486 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002487 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002488 break;
2489 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002491 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002492 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493
2494 return ptr - data;
2495}
2496
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002497static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002499 struct l2cap_conf_rsp *rsp = data;
2500 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002501 void *req = chan->conf_req;
2502 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002503 int type, hint, olen;
2504 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002505 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002506 struct l2cap_conf_efs efs;
2507 u8 remote_efs = 0;
Marcel Holtmann861d6882007-10-20 13:37:06 +02002508 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002509 u16 result = L2CAP_CONF_SUCCESS;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002510 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002512 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002513
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002514 while (len >= L2CAP_CONF_OPT_SIZE) {
2515 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002517 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002518 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002519
2520 switch (type) {
2521 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002522 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002523 break;
2524
2525 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002526 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002527 break;
2528
2529 case L2CAP_CONF_QOS:
2530 break;
2531
Marcel Holtmann6464f352007-10-20 13:39:51 +02002532 case L2CAP_CONF_RFC:
2533 if (olen == sizeof(rfc))
2534 memcpy(&rfc, (void *) val, olen);
2535 break;
2536
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002537 case L2CAP_CONF_FCS:
2538 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002539 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002540 break;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002541
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002542 case L2CAP_CONF_EFS:
2543 remote_efs = 1;
2544 if (olen == sizeof(efs))
2545 memcpy(&efs, (void *) val, olen);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002546 break;
2547
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002548 case L2CAP_CONF_EWS:
2549 if (!enable_hs)
2550 return -ECONNREFUSED;
2551
2552 set_bit(FLAG_EXT_CTRL, &chan->flags);
2553 set_bit(CONF_EWS_RECV, &chan->conf_state);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002554 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002555 chan->remote_tx_win = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002556 break;
2557
2558 default:
2559 if (hint)
2560 break;
2561
2562 result = L2CAP_CONF_UNKNOWN;
2563 *((u8 *) ptr++) = type;
2564 break;
2565 }
2566 }
2567
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002568 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002569 goto done;
2570
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002571 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002572 case L2CAP_MODE_STREAMING:
2573 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002574 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002575 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002576 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002577 break;
2578 }
2579
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002580 if (remote_efs) {
2581 if (__l2cap_efs_supported(chan))
2582 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2583 else
2584 return -ECONNREFUSED;
2585 }
2586
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002587 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002588 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002589
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002590 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002591 }
2592
2593done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002594 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002595 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002596 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002597
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002598 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002599 return -ECONNREFUSED;
2600
2601 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2602 sizeof(rfc), (unsigned long) &rfc);
2603 }
2604
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002605 if (result == L2CAP_CONF_SUCCESS) {
2606 /* Configure output options and let the other side know
2607 * which ones we don't like. */
2608
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002609 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2610 result = L2CAP_CONF_UNACCEPT;
2611 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002612 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002613 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002614 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002615 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002616
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002617 if (remote_efs) {
2618 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2619 efs.stype != L2CAP_SERV_NOTRAFIC &&
2620 efs.stype != chan->local_stype) {
2621
2622 result = L2CAP_CONF_UNACCEPT;
2623
2624 if (chan->num_conf_req >= 1)
2625 return -ECONNREFUSED;
2626
2627 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002628 sizeof(efs),
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002629 (unsigned long) &efs);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002630 } else {
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002631 /* Send PENDING Conf Rsp */
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002632 result = L2CAP_CONF_PENDING;
2633 set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002634 }
2635 }
2636
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002637 switch (rfc.mode) {
2638 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002639 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002640 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002641 break;
2642
2643 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002644 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2645 chan->remote_tx_win = rfc.txwin_size;
2646 else
2647 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2648
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002649 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002650
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002651 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2652 chan->conn->mtu -
2653 L2CAP_EXT_HDR_SIZE -
2654 L2CAP_SDULEN_SIZE -
2655 L2CAP_FCS_SIZE);
2656 rfc.max_pdu_size = cpu_to_le16(size);
2657 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002658
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002659 rfc.retrans_timeout =
Andrei Emeltchenko4fd21a82012-03-12 12:13:10 +02002660 __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002661 rfc.monitor_timeout =
Andrei Emeltchenko4fd21a82012-03-12 12:13:10 +02002662 __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002663
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002664 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002665
2666 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2667 sizeof(rfc), (unsigned long) &rfc);
2668
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002669 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2670 chan->remote_id = efs.id;
2671 chan->remote_stype = efs.stype;
2672 chan->remote_msdu = le16_to_cpu(efs.msdu);
2673 chan->remote_flush_to =
2674 le32_to_cpu(efs.flush_to);
2675 chan->remote_acc_lat =
2676 le32_to_cpu(efs.acc_lat);
2677 chan->remote_sdu_itime =
2678 le32_to_cpu(efs.sdu_itime);
2679 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2680 sizeof(efs), (unsigned long) &efs);
2681 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002682 break;
2683
2684 case L2CAP_MODE_STREAMING:
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002685 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2686 chan->conn->mtu -
2687 L2CAP_EXT_HDR_SIZE -
2688 L2CAP_SDULEN_SIZE -
2689 L2CAP_FCS_SIZE);
2690 rfc.max_pdu_size = cpu_to_le16(size);
2691 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002692
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002693 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002694
2695 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2696 sizeof(rfc), (unsigned long) &rfc);
2697
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002698 break;
2699
2700 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002701 result = L2CAP_CONF_UNACCEPT;
2702
2703 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002704 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002705 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002706
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002707 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002708 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002709 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002710 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002711 rsp->result = cpu_to_le16(result);
2712 rsp->flags = cpu_to_le16(0x0000);
2713
2714 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715}
2716
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002717static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002718{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002719 struct l2cap_conf_req *req = data;
2720 void *ptr = req->data;
2721 int type, olen;
2722 unsigned long val;
Mat Martineau36e999a2011-12-08 17:23:21 -08002723 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002724 struct l2cap_conf_efs efs;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002725
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002726 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002727
2728 while (len >= L2CAP_CONF_OPT_SIZE) {
2729 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2730
2731 switch (type) {
2732 case L2CAP_CONF_MTU:
2733 if (val < L2CAP_DEFAULT_MIN_MTU) {
2734 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002735 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002736 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002737 chan->imtu = val;
2738 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002739 break;
2740
2741 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002742 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002743 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002744 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002745 break;
2746
2747 case L2CAP_CONF_RFC:
2748 if (olen == sizeof(rfc))
2749 memcpy(&rfc, (void *)val, olen);
2750
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002751 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002752 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002753 return -ECONNREFUSED;
2754
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002755 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002756
2757 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2758 sizeof(rfc), (unsigned long) &rfc);
2759 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002760
2761 case L2CAP_CONF_EWS:
2762 chan->tx_win = min_t(u16, val,
2763 L2CAP_DEFAULT_EXT_WINDOW);
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002764 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2765 chan->tx_win);
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002766 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002767
2768 case L2CAP_CONF_EFS:
2769 if (olen == sizeof(efs))
2770 memcpy(&efs, (void *)val, olen);
2771
2772 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2773 efs.stype != L2CAP_SERV_NOTRAFIC &&
2774 efs.stype != chan->local_stype)
2775 return -ECONNREFUSED;
2776
2777 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2778 sizeof(efs), (unsigned long) &efs);
2779 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002780 }
2781 }
2782
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002783 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002784 return -ECONNREFUSED;
2785
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002786 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002787
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002788 if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002789 switch (rfc.mode) {
2790 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002791 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2792 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2793 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002794
2795 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2796 chan->local_msdu = le16_to_cpu(efs.msdu);
2797 chan->local_sdu_itime =
2798 le32_to_cpu(efs.sdu_itime);
2799 chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
2800 chan->local_flush_to =
2801 le32_to_cpu(efs.flush_to);
2802 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002803 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002804
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002805 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002806 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002807 }
2808 }
2809
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002810 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002811 req->flags = cpu_to_le16(0x0000);
2812
2813 return ptr - data;
2814}
2815
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002816static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817{
2818 struct l2cap_conf_rsp *rsp = data;
2819 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002821 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002823 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002824 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002825 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826
2827 return ptr - data;
2828}
2829
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002830void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002831{
2832 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002833 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002834 u8 buf[128];
2835
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002836 rsp.scid = cpu_to_le16(chan->dcid);
2837 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002838 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2839 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2840 l2cap_send_cmd(conn, chan->ident,
2841 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2842
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002843 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002844 return;
2845
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002846 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2847 l2cap_build_conf_req(chan, buf), buf);
2848 chan->num_conf_req++;
2849}
2850
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002851static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002852{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002853 int type, olen;
2854 unsigned long val;
2855 struct l2cap_conf_rfc rfc;
2856
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002857 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002858
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002859 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002860 return;
2861
2862 while (len >= L2CAP_CONF_OPT_SIZE) {
2863 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2864
2865 switch (type) {
2866 case L2CAP_CONF_RFC:
2867 if (olen == sizeof(rfc))
2868 memcpy(&rfc, (void *)val, olen);
2869 goto done;
2870 }
2871 }
2872
Mat Martineau36e999a2011-12-08 17:23:21 -08002873 /* Use sane default values in case a misbehaving remote device
2874 * did not send an RFC option.
2875 */
2876 rfc.mode = chan->mode;
2877 rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
2878 rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
2879 rfc.max_pdu_size = cpu_to_le16(chan->imtu);
2880
2881 BT_ERR("Expected RFC option was not found, using defaults");
2882
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002883done:
2884 switch (rfc.mode) {
2885 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002886 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2887 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2888 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002889 break;
2890 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002891 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002892 }
2893}
2894
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002895static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2896{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002897 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002898
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002899 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002900 return 0;
2901
2902 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2903 cmd->ident == conn->info_ident) {
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02002904 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002905
2906 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002907 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002908
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002909 l2cap_conn_start(conn);
2910 }
2911
2912 return 0;
2913}
2914
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2916{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2918 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002919 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002920 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002921 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002922
2923 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002924 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925
Andrei Emeltchenko097db762012-03-09 14:16:17 +02002926 BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002927
2928 /* Check if we have socket listening on psm */
Ido Yarivc2287682012-04-20 15:46:07 -03002929 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002930 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002931 result = L2CAP_CR_BAD_PSM;
2932 goto sendresp;
2933 }
2934
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002935 parent = pchan->sk;
2936
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02002937 mutex_lock(&conn->chan_lock);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002938 lock_sock(parent);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002939
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002940 /* Check if the ACL is secure enough (if not SDP) */
2941 if (psm != cpu_to_le16(0x0001) &&
2942 !hci_conn_check_link_mode(conn->hcon)) {
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002943 conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002944 result = L2CAP_CR_SEC_BLOCK;
2945 goto response;
2946 }
2947
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948 result = L2CAP_CR_NO_MEM;
2949
2950 /* Check for backlog size */
2951 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002952 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 goto response;
2954 }
2955
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002956 chan = pchan->ops->new_connection(pchan->data);
2957 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002958 goto response;
2959
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002960 sk = chan->sk;
2961
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002963 if (__l2cap_get_chan_by_dcid(conn, scid)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002965 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002966 goto response;
2967 }
2968
2969 hci_conn_hold(conn->hcon);
2970
Linus Torvalds1da177e2005-04-16 15:20:36 -07002971 bacpy(&bt_sk(sk)->src, conn->src);
2972 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002973 chan->psm = psm;
2974 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002976 bt_accept_enqueue(parent, sk);
2977
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02002978 __l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002979
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002980 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002982 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002984 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985
Marcel Holtmann984947d2009-02-06 23:35:19 +01002986 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02002987 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002988 if (bt_sk(sk)->defer_setup) {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02002989 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002990 result = L2CAP_CR_PEND;
2991 status = L2CAP_CS_AUTHOR_PEND;
2992 parent->sk_data_ready(parent, 0);
2993 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02002994 __l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002995 result = L2CAP_CR_SUCCESS;
2996 status = L2CAP_CS_NO_INFO;
2997 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002998 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02002999 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003000 result = L2CAP_CR_PEND;
3001 status = L2CAP_CS_AUTHEN_PEND;
3002 }
3003 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02003004 __l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003005 result = L2CAP_CR_PEND;
3006 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 }
3008
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009response:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003010 release_sock(parent);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003011 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012
3013sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003014 rsp.scid = cpu_to_le16(scid);
3015 rsp.dcid = cpu_to_le16(dcid);
3016 rsp.result = cpu_to_le16(result);
3017 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003019
3020 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
3021 struct l2cap_info_req info;
3022 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3023
3024 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
3025 conn->info_ident = l2cap_get_ident(conn);
3026
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08003027 schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003028
3029 l2cap_send_cmd(conn, conn->info_ident,
3030 L2CAP_INFO_REQ, sizeof(info), &info);
3031 }
3032
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003033 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003034 result == L2CAP_CR_SUCCESS) {
3035 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003036 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003037 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003038 l2cap_build_conf_req(chan, buf), buf);
3039 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003040 }
3041
Linus Torvalds1da177e2005-04-16 15:20:36 -07003042 return 0;
3043}
3044
3045static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3046{
3047 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
3048 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003049 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050 u8 req[128];
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003051 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052
3053 scid = __le16_to_cpu(rsp->scid);
3054 dcid = __le16_to_cpu(rsp->dcid);
3055 result = __le16_to_cpu(rsp->result);
3056 status = __le16_to_cpu(rsp->status);
3057
Andrei Emeltchenko1b009c92012-02-21 12:54:54 +02003058 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
3059 dcid, scid, result, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003060
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003061 mutex_lock(&conn->chan_lock);
3062
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063 if (scid) {
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003064 chan = __l2cap_get_chan_by_scid(conn, scid);
3065 if (!chan) {
3066 err = -EFAULT;
3067 goto unlock;
3068 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069 } else {
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003070 chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
3071 if (!chan) {
3072 err = -EFAULT;
3073 goto unlock;
3074 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075 }
3076
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003077 err = 0;
3078
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003079 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003080
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081 switch (result) {
3082 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003083 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003084 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003085 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003086 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003087
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003088 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03003089 break;
3090
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003092 l2cap_build_conf_req(chan, req), req);
3093 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003094 break;
3095
3096 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003097 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098 break;
3099
3100 default:
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003101 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102 break;
3103 }
3104
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003105 l2cap_chan_unlock(chan);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003106
3107unlock:
3108 mutex_unlock(&conn->chan_lock);
3109
3110 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111}
3112
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003113static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07003114{
3115 /* FCS is enabled only in ERTM or streaming mode, if one or both
3116 * sides request it.
3117 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003118 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003119 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003120 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003121 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07003122}
3123
Al Viro88219a02007-07-29 00:17:25 -07003124static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125{
3126 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
3127 u16 dcid, flags;
3128 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003129 struct l2cap_chan *chan;
Mat Martineau3c588192012-04-11 10:48:42 -07003130 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131
3132 dcid = __le16_to_cpu(req->dcid);
3133 flags = __le16_to_cpu(req->flags);
3134
3135 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
3136
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003137 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003138 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139 return -ENOENT;
3140
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003141 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003142
David S. Miller033b1142011-07-21 13:38:42 -07003143 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003144 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003145
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003146 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
3147 rej.scid = cpu_to_le16(chan->scid);
3148 rej.dcid = cpu_to_le16(chan->dcid);
3149
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003150 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
3151 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003152 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03003153 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01003154
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003155 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07003156 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04003157 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003158 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003159 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003160 L2CAP_CONF_REJECT, flags), rsp);
3161 goto unlock;
3162 }
3163
3164 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003165 memcpy(chan->conf_req + chan->conf_len, req->data, len);
3166 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167
3168 if (flags & 0x0001) {
3169 /* Incomplete config. Send empty response. */
3170 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003171 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003172 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173 goto unlock;
3174 }
3175
3176 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003177 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003178 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003179 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003181 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003183 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003184 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003185
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003186 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003187 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02003188
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003189 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02003190 goto unlock;
3191
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003192 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003193 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003194
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003195 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003196
Mat Martineau105bdf92012-04-27 16:50:48 -07003197 if (chan->mode == L2CAP_MODE_ERTM ||
3198 chan->mode == L2CAP_MODE_STREAMING)
Mat Martineau3c588192012-04-11 10:48:42 -07003199 err = l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003200
Mat Martineau3c588192012-04-11 10:48:42 -07003201 if (err < 0)
3202 l2cap_send_disconn_req(chan->conn, chan, -err);
3203 else
3204 l2cap_chan_ready(chan);
3205
Marcel Holtmann876d9482007-10-20 13:35:42 +02003206 goto unlock;
3207 }
3208
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003209 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02003210 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003212 l2cap_build_conf_req(chan, buf), buf);
3213 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003214 }
3215
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003216 /* Got Conf Rsp PENDING from remote side and asume we sent
3217 Conf Rsp PENDING in the code above */
3218 if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
3219 test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
3220
3221 /* check compatibility */
3222
3223 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
3224 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
3225
3226 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02003227 l2cap_build_conf_rsp(chan, rsp,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003228 L2CAP_CONF_SUCCESS, 0x0000), rsp);
3229 }
3230
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231unlock:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003232 l2cap_chan_unlock(chan);
Mat Martineau3c588192012-04-11 10:48:42 -07003233 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003234}
3235
3236static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3237{
3238 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
3239 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003240 struct l2cap_chan *chan;
Andrei Emeltchenko61386cb2012-03-12 12:13:07 +02003241 int len = le16_to_cpu(cmd->len) - sizeof(*rsp);
Mat Martineau3c588192012-04-11 10:48:42 -07003242 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243
3244 scid = __le16_to_cpu(rsp->scid);
3245 flags = __le16_to_cpu(rsp->flags);
3246 result = __le16_to_cpu(rsp->result);
3247
Andrei Emeltchenko61386cb2012-03-12 12:13:07 +02003248 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
3249 result, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003250
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003251 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003252 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003253 return 0;
3254
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003255 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003256
Linus Torvalds1da177e2005-04-16 15:20:36 -07003257 switch (result) {
3258 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003259 l2cap_conf_rfc_get(chan, rsp->data, len);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003260 clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261 break;
3262
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003263 case L2CAP_CONF_PENDING:
3264 set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
3265
3266 if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
3267 char buf[64];
3268
3269 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
3270 buf, &result);
3271 if (len < 0) {
3272 l2cap_send_disconn_req(conn, chan, ECONNRESET);
3273 goto done;
3274 }
3275
3276 /* check compatibility */
3277
3278 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
3279 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
3280
3281 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02003282 l2cap_build_conf_rsp(chan, buf,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03003283 L2CAP_CONF_SUCCESS, 0x0000), buf);
3284 }
3285 goto done;
3286
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003288 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003289 char req[64];
3290
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003291 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003292 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02003293 goto done;
3294 }
3295
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003296 /* throw out any old stored conf requests */
3297 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003298 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
3299 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003300 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003301 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003302 goto done;
3303 }
3304
3305 l2cap_send_cmd(conn, l2cap_get_ident(conn),
3306 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03003307 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03003308 if (result != L2CAP_CONF_SUCCESS)
3309 goto done;
3310 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003311 }
3312
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09003313 default:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003314 l2cap_chan_set_err(chan, ECONNRESET);
Andrei Emeltchenko2e0052e2012-02-21 12:54:58 +02003315
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08003316 __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003317 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003318 goto done;
3319 }
3320
3321 if (flags & 0x01)
3322 goto done;
3323
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003324 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003325
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03003326 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003327 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003328
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003329 l2cap_state_change(chan, BT_CONNECTED);
Mat Martineau105bdf92012-04-27 16:50:48 -07003330 if (chan->mode == L2CAP_MODE_ERTM ||
3331 chan->mode == L2CAP_MODE_STREAMING)
Mat Martineau3c588192012-04-11 10:48:42 -07003332 err = l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003333
Mat Martineau3c588192012-04-11 10:48:42 -07003334 if (err < 0)
3335 l2cap_send_disconn_req(chan->conn, chan, -err);
3336 else
3337 l2cap_chan_ready(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338 }
3339
3340done:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003341 l2cap_chan_unlock(chan);
Mat Martineau3c588192012-04-11 10:48:42 -07003342 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003343}
3344
3345static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3346{
3347 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3348 struct l2cap_disconn_rsp rsp;
3349 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003350 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003351 struct sock *sk;
3352
3353 scid = __le16_to_cpu(req->scid);
3354 dcid = __le16_to_cpu(req->dcid);
3355
3356 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3357
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003358 mutex_lock(&conn->chan_lock);
3359
3360 chan = __l2cap_get_chan_by_scid(conn, dcid);
3361 if (!chan) {
3362 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363 return 0;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003364 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003366 l2cap_chan_lock(chan);
3367
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003368 sk = chan->sk;
3369
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003370 rsp.dcid = cpu_to_le16(chan->scid);
3371 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3373
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003374 lock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375 sk->sk_shutdown = SHUTDOWN_MASK;
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003376 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003377
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003378 l2cap_chan_del(chan, ECONNRESET);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003379
3380 l2cap_chan_unlock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003382 chan->ops->close(chan->data);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003383
3384 mutex_unlock(&conn->chan_lock);
3385
Linus Torvalds1da177e2005-04-16 15:20:36 -07003386 return 0;
3387}
3388
3389static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3390{
3391 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3392 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003393 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003394
3395 scid = __le16_to_cpu(rsp->scid);
3396 dcid = __le16_to_cpu(rsp->dcid);
3397
3398 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3399
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003400 mutex_lock(&conn->chan_lock);
3401
3402 chan = __l2cap_get_chan_by_scid(conn, scid);
3403 if (!chan) {
3404 mutex_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405 return 0;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003406 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003408 l2cap_chan_lock(chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003409
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003410 l2cap_chan_del(chan, 0);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02003411
3412 l2cap_chan_unlock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003413
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003414 chan->ops->close(chan->data);
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02003415
3416 mutex_unlock(&conn->chan_lock);
3417
Linus Torvalds1da177e2005-04-16 15:20:36 -07003418 return 0;
3419}
3420
3421static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3422{
3423 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003424 u16 type;
3425
3426 type = __le16_to_cpu(req->type);
3427
3428 BT_DBG("type 0x%4.4x", type);
3429
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003430 if (type == L2CAP_IT_FEAT_MASK) {
3431 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003432 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003433 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3434 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3435 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003436 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003437 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3438 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003439 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003440 feat_mask |= L2CAP_FEAT_EXT_FLOW
3441 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003442
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003443 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003444 l2cap_send_cmd(conn, cmd->ident,
3445 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003446 } else if (type == L2CAP_IT_FIXED_CHAN) {
3447 u8 buf[12];
3448 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
Mat Martineau50a147c2011-11-02 16:18:34 -07003449
3450 if (enable_hs)
3451 l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
3452 else
3453 l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
3454
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003455 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3456 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003457 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003458 l2cap_send_cmd(conn, cmd->ident,
3459 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003460 } else {
3461 struct l2cap_info_rsp rsp;
3462 rsp.type = cpu_to_le16(type);
3463 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3464 l2cap_send_cmd(conn, cmd->ident,
3465 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3466 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467
3468 return 0;
3469}
3470
3471static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3472{
3473 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3474 u16 type, result;
3475
3476 type = __le16_to_cpu(rsp->type);
3477 result = __le16_to_cpu(rsp->result);
3478
3479 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3480
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003481 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3482 if (cmd->ident != conn->info_ident ||
3483 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3484 return 0;
3485
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02003486 cancel_delayed_work(&conn->info_timer);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003487
Ville Tervoadb08ed2010-08-04 09:43:33 +03003488 if (result != L2CAP_IR_SUCCESS) {
3489 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3490 conn->info_ident = 0;
3491
3492 l2cap_conn_start(conn);
3493
3494 return 0;
3495 }
3496
Andrei Emeltchenko978c93b2012-02-29 10:41:41 +02003497 switch (type) {
3498 case L2CAP_IT_FEAT_MASK:
Harvey Harrison83985312008-05-02 16:25:46 -07003499 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003500
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003501 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003502 struct l2cap_info_req req;
3503 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3504
3505 conn->info_ident = l2cap_get_ident(conn);
3506
3507 l2cap_send_cmd(conn, conn->info_ident,
3508 L2CAP_INFO_REQ, sizeof(req), &req);
3509 } else {
3510 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3511 conn->info_ident = 0;
3512
3513 l2cap_conn_start(conn);
3514 }
Andrei Emeltchenko978c93b2012-02-29 10:41:41 +02003515 break;
3516
3517 case L2CAP_IT_FIXED_CHAN:
3518 conn->fixed_chan_mask = rsp->data[0];
Marcel Holtmann984947d2009-02-06 23:35:19 +01003519 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003520 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003521
3522 l2cap_conn_start(conn);
Andrei Emeltchenko978c93b2012-02-29 10:41:41 +02003523 break;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003524 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003525
Linus Torvalds1da177e2005-04-16 15:20:36 -07003526 return 0;
3527}
3528
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003529static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3530 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3531 void *data)
3532{
3533 struct l2cap_create_chan_req *req = data;
3534 struct l2cap_create_chan_rsp rsp;
3535 u16 psm, scid;
3536
3537 if (cmd_len != sizeof(*req))
3538 return -EPROTO;
3539
3540 if (!enable_hs)
3541 return -EINVAL;
3542
3543 psm = le16_to_cpu(req->psm);
3544 scid = le16_to_cpu(req->scid);
3545
3546 BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3547
3548 /* Placeholder: Always reject */
3549 rsp.dcid = 0;
3550 rsp.scid = cpu_to_le16(scid);
Andrei Emeltchenko8ce0c492012-03-12 12:13:09 +02003551 rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
3552 rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003553
3554 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3555 sizeof(rsp), &rsp);
3556
3557 return 0;
3558}
3559
3560static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3561 struct l2cap_cmd_hdr *cmd, void *data)
3562{
3563 BT_DBG("conn %p", conn);
3564
3565 return l2cap_connect_rsp(conn, cmd, data);
3566}
3567
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003568static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
3569 u16 icid, u16 result)
3570{
3571 struct l2cap_move_chan_rsp rsp;
3572
3573 BT_DBG("icid %d, result %d", icid, result);
3574
3575 rsp.icid = cpu_to_le16(icid);
3576 rsp.result = cpu_to_le16(result);
3577
3578 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
3579}
3580
3581static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
3582 struct l2cap_chan *chan, u16 icid, u16 result)
3583{
3584 struct l2cap_move_chan_cfm cfm;
3585 u8 ident;
3586
3587 BT_DBG("icid %d, result %d", icid, result);
3588
3589 ident = l2cap_get_ident(conn);
3590 if (chan)
3591 chan->ident = ident;
3592
3593 cfm.icid = cpu_to_le16(icid);
3594 cfm.result = cpu_to_le16(result);
3595
3596 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
3597}
3598
3599static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
3600 u16 icid)
3601{
3602 struct l2cap_move_chan_cfm_rsp rsp;
3603
3604 BT_DBG("icid %d", icid);
3605
3606 rsp.icid = cpu_to_le16(icid);
3607 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
3608}
3609
3610static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
3611 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3612{
3613 struct l2cap_move_chan_req *req = data;
3614 u16 icid = 0;
3615 u16 result = L2CAP_MR_NOT_ALLOWED;
3616
3617 if (cmd_len != sizeof(*req))
3618 return -EPROTO;
3619
3620 icid = le16_to_cpu(req->icid);
3621
3622 BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
3623
3624 if (!enable_hs)
3625 return -EINVAL;
3626
3627 /* Placeholder: Always refuse */
3628 l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
3629
3630 return 0;
3631}
3632
3633static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
3634 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3635{
3636 struct l2cap_move_chan_rsp *rsp = data;
3637 u16 icid, result;
3638
3639 if (cmd_len != sizeof(*rsp))
3640 return -EPROTO;
3641
3642 icid = le16_to_cpu(rsp->icid);
3643 result = le16_to_cpu(rsp->result);
3644
3645 BT_DBG("icid %d, result %d", icid, result);
3646
3647 /* Placeholder: Always unconfirmed */
3648 l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
3649
3650 return 0;
3651}
3652
3653static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
3654 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3655{
3656 struct l2cap_move_chan_cfm *cfm = data;
3657 u16 icid, result;
3658
3659 if (cmd_len != sizeof(*cfm))
3660 return -EPROTO;
3661
3662 icid = le16_to_cpu(cfm->icid);
3663 result = le16_to_cpu(cfm->result);
3664
3665 BT_DBG("icid %d, result %d", icid, result);
3666
3667 l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
3668
3669 return 0;
3670}
3671
3672static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
3673 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3674{
3675 struct l2cap_move_chan_cfm_rsp *rsp = data;
3676 u16 icid;
3677
3678 if (cmd_len != sizeof(*rsp))
3679 return -EPROTO;
3680
3681 icid = le16_to_cpu(rsp->icid);
3682
3683 BT_DBG("icid %d", icid);
3684
3685 return 0;
3686}
3687
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003688static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02003689 u16 to_multiplier)
3690{
3691 u16 max_latency;
3692
3693 if (min > max || min < 6 || max > 3200)
3694 return -EINVAL;
3695
3696 if (to_multiplier < 10 || to_multiplier > 3200)
3697 return -EINVAL;
3698
3699 if (max >= to_multiplier * 8)
3700 return -EINVAL;
3701
3702 max_latency = (to_multiplier * 8 / max) - 1;
3703 if (latency > 499 || latency > max_latency)
3704 return -EINVAL;
3705
3706 return 0;
3707}
3708
3709static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3710 struct l2cap_cmd_hdr *cmd, u8 *data)
3711{
3712 struct hci_conn *hcon = conn->hcon;
3713 struct l2cap_conn_param_update_req *req;
3714 struct l2cap_conn_param_update_rsp rsp;
3715 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003716 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02003717
3718 if (!(hcon->link_mode & HCI_LM_MASTER))
3719 return -EINVAL;
3720
3721 cmd_len = __le16_to_cpu(cmd->len);
3722 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3723 return -EPROTO;
3724
3725 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003726 min = __le16_to_cpu(req->min);
3727 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02003728 latency = __le16_to_cpu(req->latency);
3729 to_multiplier = __le16_to_cpu(req->to_multiplier);
3730
3731 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3732 min, max, latency, to_multiplier);
3733
3734 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003735
3736 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
3737 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02003738 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3739 else
3740 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3741
3742 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3743 sizeof(rsp), &rsp);
3744
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003745 if (!err)
3746 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
3747
Claudio Takahaside731152011-02-11 19:28:55 -02003748 return 0;
3749}
3750
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003751static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
3752 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
3753{
3754 int err = 0;
3755
3756 switch (cmd->code) {
3757 case L2CAP_COMMAND_REJ:
3758 l2cap_command_rej(conn, cmd, data);
3759 break;
3760
3761 case L2CAP_CONN_REQ:
3762 err = l2cap_connect_req(conn, cmd, data);
3763 break;
3764
3765 case L2CAP_CONN_RSP:
3766 err = l2cap_connect_rsp(conn, cmd, data);
3767 break;
3768
3769 case L2CAP_CONF_REQ:
3770 err = l2cap_config_req(conn, cmd, cmd_len, data);
3771 break;
3772
3773 case L2CAP_CONF_RSP:
3774 err = l2cap_config_rsp(conn, cmd, data);
3775 break;
3776
3777 case L2CAP_DISCONN_REQ:
3778 err = l2cap_disconnect_req(conn, cmd, data);
3779 break;
3780
3781 case L2CAP_DISCONN_RSP:
3782 err = l2cap_disconnect_rsp(conn, cmd, data);
3783 break;
3784
3785 case L2CAP_ECHO_REQ:
3786 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3787 break;
3788
3789 case L2CAP_ECHO_RSP:
3790 break;
3791
3792 case L2CAP_INFO_REQ:
3793 err = l2cap_information_req(conn, cmd, data);
3794 break;
3795
3796 case L2CAP_INFO_RSP:
3797 err = l2cap_information_rsp(conn, cmd, data);
3798 break;
3799
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003800 case L2CAP_CREATE_CHAN_REQ:
3801 err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3802 break;
3803
3804 case L2CAP_CREATE_CHAN_RSP:
3805 err = l2cap_create_channel_rsp(conn, cmd, data);
3806 break;
3807
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003808 case L2CAP_MOVE_CHAN_REQ:
3809 err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
3810 break;
3811
3812 case L2CAP_MOVE_CHAN_RSP:
3813 err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
3814 break;
3815
3816 case L2CAP_MOVE_CHAN_CFM:
3817 err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
3818 break;
3819
3820 case L2CAP_MOVE_CHAN_CFM_RSP:
3821 err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
3822 break;
3823
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003824 default:
3825 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3826 err = -EINVAL;
3827 break;
3828 }
3829
3830 return err;
3831}
3832
3833static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3834 struct l2cap_cmd_hdr *cmd, u8 *data)
3835{
3836 switch (cmd->code) {
3837 case L2CAP_COMMAND_REJ:
3838 return 0;
3839
3840 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003841 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003842
3843 case L2CAP_CONN_PARAM_UPDATE_RSP:
3844 return 0;
3845
3846 default:
3847 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3848 return -EINVAL;
3849 }
3850}
3851
3852static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3853 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854{
3855 u8 *data = skb->data;
3856 int len = skb->len;
3857 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003858 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859
3860 l2cap_raw_recv(conn, skb);
3861
3862 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003863 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3865 data += L2CAP_CMD_HDR_SIZE;
3866 len -= L2CAP_CMD_HDR_SIZE;
3867
Al Viro88219a02007-07-29 00:17:25 -07003868 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869
Al Viro88219a02007-07-29 00:17:25 -07003870 BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871
Al Viro88219a02007-07-29 00:17:25 -07003872 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873 BT_DBG("corrupted command");
3874 break;
3875 }
3876
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003877 if (conn->hcon->type == LE_LINK)
3878 err = l2cap_le_sig_cmd(conn, &cmd, data);
3879 else
3880 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881
3882 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003883 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003884
3885 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003886
3887 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003888 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3890 }
3891
Al Viro88219a02007-07-29 00:17:25 -07003892 data += cmd_len;
3893 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894 }
3895
3896 kfree_skb(skb);
3897}
3898
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003899static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003900{
3901 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003902 int hdr_size;
3903
3904 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3905 hdr_size = L2CAP_EXT_HDR_SIZE;
3906 else
3907 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003908
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003909 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003910 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003911 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3912 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3913
3914 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003915 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003916 }
3917 return 0;
3918}
3919
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003920static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003921{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003922 u32 control = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003923
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003924 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003925
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003926 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003927
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003928 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003929 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003930 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003931 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003932 }
3933
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003934 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003935 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003936
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003937 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003938
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003939 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003940 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003941 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003942 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003943 }
3944}
3945
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003946static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u16 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003947{
3948 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003949 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003950
Mat Martineau3ce35142012-04-25 16:36:14 -07003951 bt_cb(skb)->control.txseq = tx_seq;
3952 bt_cb(skb)->control.sar = sar;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003953
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003954 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003955
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003956 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003957
Szymon Janc039d9572011-11-16 09:32:19 +01003958 while (next_skb) {
Mat Martineau3ce35142012-04-25 16:36:14 -07003959 if (bt_cb(next_skb)->control.txseq == tx_seq)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003960 return -EINVAL;
3961
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003962 next_tx_seq_offset = __seq_offset(chan,
Mat Martineau3ce35142012-04-25 16:36:14 -07003963 bt_cb(next_skb)->control.txseq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003964
3965 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003966 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003967 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003968 }
3969
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003970 if (skb_queue_is_last(&chan->srej_q, next_skb))
Szymon Janc039d9572011-11-16 09:32:19 +01003971 next_skb = NULL;
3972 else
3973 next_skb = skb_queue_next(&chan->srej_q, next_skb);
3974 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003975
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003976 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003977
3978 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003979}
3980
Mat Martineau84084a32011-07-22 14:54:00 -07003981static void append_skb_frag(struct sk_buff *skb,
3982 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003983{
Mat Martineau84084a32011-07-22 14:54:00 -07003984 /* skb->len reflects data in skb as well as all fragments
3985 * skb->data_len reflects only data in fragments
3986 */
3987 if (!skb_has_frag_list(skb))
3988 skb_shinfo(skb)->frag_list = new_frag;
3989
3990 new_frag->next = NULL;
3991
3992 (*last_frag)->next = new_frag;
3993 *last_frag = new_frag;
3994
3995 skb->len += new_frag->len;
3996 skb->data_len += new_frag->len;
3997 skb->truesize += new_frag->truesize;
3998}
3999
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004000static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
Mat Martineau84084a32011-07-22 14:54:00 -07004001{
4002 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004003
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004004 switch (__get_ctrl_sar(chan, control)) {
4005 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07004006 if (chan->sdu)
4007 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004008
Mat Martineau84084a32011-07-22 14:54:00 -07004009 err = chan->ops->recv(chan->data, skb);
4010 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004011
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004012 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07004013 if (chan->sdu)
4014 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004015
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03004016 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004017 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004018
Mat Martineau84084a32011-07-22 14:54:00 -07004019 if (chan->sdu_len > chan->imtu) {
4020 err = -EMSGSIZE;
4021 break;
4022 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004023
Mat Martineau84084a32011-07-22 14:54:00 -07004024 if (skb->len >= chan->sdu_len)
4025 break;
4026
4027 chan->sdu = skb;
4028 chan->sdu_last_frag = skb;
4029
4030 skb = NULL;
4031 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004032 break;
4033
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004034 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03004035 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07004036 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004037
Mat Martineau84084a32011-07-22 14:54:00 -07004038 append_skb_frag(chan->sdu, skb,
4039 &chan->sdu_last_frag);
4040 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004041
Mat Martineau84084a32011-07-22 14:54:00 -07004042 if (chan->sdu->len >= chan->sdu_len)
4043 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03004044
Mat Martineau84084a32011-07-22 14:54:00 -07004045 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004046 break;
4047
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004048 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03004049 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07004050 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004051
Mat Martineau84084a32011-07-22 14:54:00 -07004052 append_skb_frag(chan->sdu, skb,
4053 &chan->sdu_last_frag);
4054 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004055
Mat Martineau84084a32011-07-22 14:54:00 -07004056 if (chan->sdu->len != chan->sdu_len)
4057 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004058
Mat Martineau84084a32011-07-22 14:54:00 -07004059 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03004060
Mat Martineau84084a32011-07-22 14:54:00 -07004061 if (!err) {
4062 /* Reassembly complete */
4063 chan->sdu = NULL;
4064 chan->sdu_last_frag = NULL;
4065 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004066 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004067 break;
4068 }
4069
Mat Martineau84084a32011-07-22 14:54:00 -07004070 if (err) {
4071 kfree_skb(skb);
4072 kfree_skb(chan->sdu);
4073 chan->sdu = NULL;
4074 chan->sdu_last_frag = NULL;
4075 chan->sdu_len = 0;
4076 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004077
Mat Martineau84084a32011-07-22 14:54:00 -07004078 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03004079}
4080
Mat Martineau26f880d2011-07-07 09:39:01 -07004081static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004082{
Mat Martineau26f880d2011-07-07 09:39:01 -07004083 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004084
Mat Martineau26f880d2011-07-07 09:39:01 -07004085 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
Mat Martineau3c588192012-04-11 10:48:42 -07004086 l2cap_seq_list_clear(&chan->srej_list);
Mat Martineau26f880d2011-07-07 09:39:01 -07004087
Szymon Janc77f918b2012-01-11 10:59:48 +01004088 __set_ack_timer(chan);
Mat Martineau26f880d2011-07-07 09:39:01 -07004089}
4090
4091static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
4092{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004093 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004094
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004095 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004096 goto done;
4097
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004098 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004099 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004100 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004101 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004102 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004103
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004104 __clear_retrans_timer(chan);
4105 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004106
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004107 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004108
4109done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004110 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
4111 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004112
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004113 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03004114}
4115
Mat Martineaue3281402011-07-07 09:39:02 -07004116void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03004117{
Mat Martineaue3281402011-07-07 09:39:02 -07004118 if (chan->mode == L2CAP_MODE_ERTM) {
4119 if (busy)
4120 l2cap_ertm_enter_local_busy(chan);
4121 else
4122 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03004123 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004124}
4125
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004126static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004127{
4128 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004129 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004130
Mat Martineaue3281402011-07-07 09:39:02 -07004131 while ((skb = skb_peek(&chan->srej_q)) &&
4132 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4133 int err;
4134
Mat Martineau3ce35142012-04-25 16:36:14 -07004135 if (bt_cb(skb)->control.txseq != tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004136 break;
4137
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004138 skb = skb_dequeue(&chan->srej_q);
Mat Martineau3ce35142012-04-25 16:36:14 -07004139 control = __set_ctrl_sar(chan, bt_cb(skb)->control.sar);
Mat Martineau84084a32011-07-22 14:54:00 -07004140 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07004141
4142 if (err < 0) {
4143 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4144 break;
4145 }
4146
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004147 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
4148 tx_seq = __next_seq(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004149 }
4150}
4151
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004152static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004153{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004154 struct srej_list *l, *tmp;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004155 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004156
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004157 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004158 if (l->tx_seq == tx_seq) {
4159 list_del(&l->list);
4160 kfree(l);
4161 return;
4162 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004163 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004164 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004165 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004166 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004167 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004168 }
4169}
4170
Szymon Jancaef89f22011-11-16 09:32:18 +01004171static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004172{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004173 struct srej_list *new;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004174 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004175
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004176 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004177 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004178 control |= __set_reqseq(chan, chan->expected_tx_seq);
Mat Martineau3c588192012-04-11 10:48:42 -07004179 l2cap_seq_list_append(&chan->srej_list, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004180 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004181
4182 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Szymon Jancaef89f22011-11-16 09:32:18 +01004183 if (!new)
4184 return -ENOMEM;
4185
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004186 new->tx_seq = chan->expected_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004187
4188 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
4189
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004190 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004191 }
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004192
4193 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Szymon Jancaef89f22011-11-16 09:32:18 +01004194
4195 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004196}
4197
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004198static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004199{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004200 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004201 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004202 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03004203 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004204 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004205 int err = 0;
4206
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004207 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%8.8x", chan, skb->len,
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004208 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004209
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004210 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004211 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004212 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004213 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004214 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004215 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004216 }
4217
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004218 chan->expected_ack_seq = req_seq;
4219 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03004220
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004221 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004222
4223 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004224 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004225 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004226 goto drop;
4227 }
4228
Szymon Janc77f918b2012-01-11 10:59:48 +01004229 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4230 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
4231 l2cap_send_ack(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004232 goto drop;
Szymon Janc77f918b2012-01-11 10:59:48 +01004233 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004234
Mat Martineau02f1b642011-06-29 14:35:19 -07004235 if (tx_seq == chan->expected_tx_seq)
4236 goto expected;
4237
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004238 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004239 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004240
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004241 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004242 struct srej_list, list);
4243 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004244 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004245 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004246
4247 list_del(&first->list);
4248 kfree(first);
4249
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004250 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004251 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004252 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004253 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004254 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004255 }
4256 } else {
4257 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004258
4259 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004260 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004261 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004262
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004263 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004264 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004265 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004266 return 0;
4267 }
4268 }
Szymon Jancaef89f22011-11-16 09:32:18 +01004269
4270 err = l2cap_send_srejframe(chan, tx_seq);
4271 if (err < 0) {
4272 l2cap_send_disconn_req(chan->conn, chan, -err);
4273 return err;
4274 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004275 }
4276 } else {
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004277 expected_tx_seq_offset = __seq_offset(chan,
4278 chan->expected_tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004279
4280 /* duplicated tx_seq */
4281 if (tx_seq_offset < expected_tx_seq_offset)
4282 goto drop;
4283
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004284 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004285
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004286 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004287
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03004288 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004289 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004290
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004291 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004292 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004293
Szymon Janc0ef3ef02012-01-11 10:59:46 +01004294 /* Set P-bit only if there are some I-frames to ack. */
4295 if (__clear_ack_timer(chan))
4296 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03004297
Szymon Jancaef89f22011-11-16 09:32:18 +01004298 err = l2cap_send_srejframe(chan, tx_seq);
4299 if (err < 0) {
4300 l2cap_send_disconn_req(chan->conn, chan, -err);
4301 return err;
4302 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004303 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004304 return 0;
4305
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004306expected:
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004307 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004308
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004309 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Mat Martineau3ce35142012-04-25 16:36:14 -07004310 bt_cb(skb)->control.txseq = tx_seq;
4311 bt_cb(skb)->control.sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03004312 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004313 return 0;
4314 }
4315
Mat Martineau84084a32011-07-22 14:54:00 -07004316 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004317 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
4318
Mat Martineaue3281402011-07-07 09:39:02 -07004319 if (err < 0) {
4320 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4321 return err;
4322 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03004323
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004324 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004325 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004326 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03004327 }
4328
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03004329
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004330 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
4331 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004332 l2cap_send_ack(chan);
Gustavo F. Padovan4d611e42011-06-23 19:30:48 -03004333 else
4334 __set_ack_timer(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03004335
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004336 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03004337
4338drop:
4339 kfree_skb(skb);
4340 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004341}
4342
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004343static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004344{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004345 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004346 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004347
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004348 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004349 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004350
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004351 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004352 set_bit(CONN_SEND_FBIT, &chan->conn_state);
4353 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
4354 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004355 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004356 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004357
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004358 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004359 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004360 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004361 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004362 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004363
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004364 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004365 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004366
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004367 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004368 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004369
4370 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004371 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004372 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004373 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004374
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004375 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4376 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004377 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02004378 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004379 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004380 }
4381}
4382
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004383static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004384{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004385 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004386
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004387 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004388
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004389 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004390
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004391 chan->expected_ack_seq = tx_seq;
4392 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004393
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004394 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004395 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004396 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004397 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004398 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004399
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004400 if (test_bit(CONN_WAIT_F, &chan->conn_state))
4401 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004402 }
4403}
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004404static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004405{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004406 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004407
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004408 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004409
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004410 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004411
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004412 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004413 chan->expected_ack_seq = tx_seq;
4414 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004415
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004416 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004417 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004418
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004419 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004420
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004421 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004422 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004423 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004424 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004425 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004426 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004427 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004428 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004429 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004430 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004431 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004432 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004433 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004434 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004435 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004436 }
4437 }
4438}
4439
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004440static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004441{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004442 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004443
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004444 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004445
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004446 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004447 chan->expected_ack_seq = tx_seq;
4448 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004449
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004450 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004451 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004452
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004453 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004454 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004455 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004456 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004457 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004458 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004459
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004460 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004461 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004462 } else {
4463 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4464 l2cap_send_sframe(chan, rx_control);
4465 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004466}
4467
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004468static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004469{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004470 BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004471
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004472 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004473 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004474 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004475 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004476 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004477 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004478 }
4479
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004480 switch (__get_ctrl_super(chan, rx_control)) {
4481 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004482 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004483 break;
4484
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004485 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004486 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004487 break;
4488
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004489 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004490 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004491 break;
4492
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004493 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004494 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004495 break;
4496 }
4497
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004498 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004499 return 0;
4500}
4501
Szymon Janccad8f1d2012-01-23 10:06:05 +01004502static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004503{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004504 u32 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004505 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004506 int len, next_tx_seq_offset, req_seq_offset;
4507
Mat Martineaub76bbd62012-04-11 10:48:43 -07004508 __unpack_control(chan, skb);
4509
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004510 control = __get_control(chan, skb->data);
4511 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004512 len = skb->len;
4513
4514 /*
4515 * We can just drop the corrupted I-frame here.
4516 * Receiver will miss it and start proper recovery
4517 * procedures and ask retransmission.
4518 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004519 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004520 goto drop;
4521
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004522 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004523 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004524
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004525 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004526 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004527
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004528 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004529 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004530 goto drop;
4531 }
4532
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004533 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004534
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004535 req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4536
4537 next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4538 chan->expected_ack_seq);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004539
4540 /* check for invalid req-seq */
4541 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004542 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004543 goto drop;
4544 }
4545
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004546 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004547 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004548 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004549 goto drop;
4550 }
4551
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004552 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004553 } else {
4554 if (len != 0) {
4555 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004556 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004557 goto drop;
4558 }
4559
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004560 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004561 }
4562
4563 return 0;
4564
4565drop:
4566 kfree_skb(skb);
4567 return 0;
4568}
4569
Linus Torvalds1da177e2005-04-16 15:20:36 -07004570static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4571{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004572 struct l2cap_chan *chan;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004573 u32 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004574 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004575 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004576
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004577 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004578 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004579 BT_DBG("unknown cid 0x%4.4x", cid);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004580 /* Drop packet and return */
Dan Carpenter33790132012-02-28 09:52:46 +03004581 kfree_skb(skb);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004582 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004583 }
4584
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004585 l2cap_chan_lock(chan);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004586
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004587 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004588
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004589 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004590 goto drop;
4591
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004592 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004593 case L2CAP_MODE_BASIC:
4594 /* If socket recv buffers overflows we drop data here
4595 * which is *bad* because L2CAP has to be reliable.
4596 * But we don't have any other choice. L2CAP doesn't
4597 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004598
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004599 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004600 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004601
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004602 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004603 goto done;
4604 break;
4605
4606 case L2CAP_MODE_ERTM:
Andrei Emeltchenko5ef8cb92012-01-13 17:21:42 +02004607 l2cap_ertm_data_rcv(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004608
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004609 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004610
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004611 case L2CAP_MODE_STREAMING:
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004612 control = __get_control(chan, skb->data);
4613 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004614 len = skb->len;
4615
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004616 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004617 goto drop;
4618
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004619 if (__is_sar_start(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004620 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004621
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004622 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004623 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004624
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004625 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004626 goto drop;
4627
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004628 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004629
Mat Martineau84084a32011-07-22 14:54:00 -07004630 if (chan->expected_tx_seq != tx_seq) {
4631 /* Frame(s) missing - must discard partial SDU */
4632 kfree_skb(chan->sdu);
4633 chan->sdu = NULL;
4634 chan->sdu_last_frag = NULL;
4635 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004636
Mat Martineau84084a32011-07-22 14:54:00 -07004637 /* TODO: Notify userland of missing data */
4638 }
4639
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004640 chan->expected_tx_seq = __next_seq(chan, tx_seq);
Mat Martineau84084a32011-07-22 14:54:00 -07004641
4642 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
4643 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004644
4645 goto done;
4646
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004647 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004648 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004649 break;
4650 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004651
4652drop:
4653 kfree_skb(skb);
4654
4655done:
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004656 l2cap_chan_unlock(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +02004657
Linus Torvalds1da177e2005-04-16 15:20:36 -07004658 return 0;
4659}
4660
Al Viro8e036fc2007-07-29 00:16:36 -07004661static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004662{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004663 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004664
Ido Yarivc2287682012-04-20 15:46:07 -03004665 chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004666 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004667 goto drop;
4668
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02004669 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004670
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004671 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004672 goto drop;
4673
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004674 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004675 goto drop;
4676
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004677 if (!chan->ops->recv(chan->data, skb))
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02004678 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004679
4680drop:
4681 kfree_skb(skb);
4682
Linus Torvalds1da177e2005-04-16 15:20:36 -07004683 return 0;
4684}
4685
Andrei Emeltchenkod9b88702012-03-12 12:13:08 +02004686static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid,
4687 struct sk_buff *skb)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004688{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004689 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004690
Ido Yarivc2287682012-04-20 15:46:07 -03004691 chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004692 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004693 goto drop;
4694
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02004695 BT_DBG("chan %p, len %d", chan, skb->len);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004696
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004697 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004698 goto drop;
4699
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004700 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004701 goto drop;
4702
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004703 if (!chan->ops->recv(chan->data, skb))
Andrei Emeltchenko5b4ceda2012-02-24 16:35:32 +02004704 return 0;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004705
4706drop:
4707 kfree_skb(skb);
4708
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004709 return 0;
4710}
4711
Linus Torvalds1da177e2005-04-16 15:20:36 -07004712static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4713{
4714 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004715 u16 cid, len;
4716 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004717
4718 skb_pull(skb, L2CAP_HDR_SIZE);
4719 cid = __le16_to_cpu(lh->cid);
4720 len = __le16_to_cpu(lh->len);
4721
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004722 if (len != skb->len) {
4723 kfree_skb(skb);
4724 return;
4725 }
4726
Linus Torvalds1da177e2005-04-16 15:20:36 -07004727 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4728
4729 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004730 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004731 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004732 l2cap_sig_channel(conn, skb);
4733 break;
4734
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004735 case L2CAP_CID_CONN_LESS:
Andrei Emeltchenko097db762012-03-09 14:16:17 +02004736 psm = get_unaligned((__le16 *) skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004737 skb_pull(skb, 2);
4738 l2cap_conless_channel(conn, psm, skb);
4739 break;
4740
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004741 case L2CAP_CID_LE_DATA:
4742 l2cap_att_channel(conn, cid, skb);
4743 break;
4744
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004745 case L2CAP_CID_SMP:
4746 if (smp_sig_channel(conn, skb))
4747 l2cap_conn_del(conn->hcon, EACCES);
4748 break;
4749
Linus Torvalds1da177e2005-04-16 15:20:36 -07004750 default:
4751 l2cap_data_channel(conn, cid, skb);
4752 break;
4753 }
4754}
4755
4756/* ---- L2CAP interface with lower layer (HCI) ---- */
4757
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004758int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004759{
4760 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004761 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004762
Linus Torvalds1da177e2005-04-16 15:20:36 -07004763 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4764
4765 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004766 read_lock(&chan_list_lock);
4767 list_for_each_entry(c, &chan_list, global_l) {
4768 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004769
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004770 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004771 continue;
4772
4773 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004774 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004775 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004776 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004777 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004778 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4779 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004780 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004781 lm2 |= HCI_LM_MASTER;
4782 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004783 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004784 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004785
4786 return exact ? lm1 : lm2;
4787}
4788
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004789int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004790{
Marcel Holtmann01394182006-07-03 10:02:46 +02004791 struct l2cap_conn *conn;
4792
Linus Torvalds1da177e2005-04-16 15:20:36 -07004793 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4794
Linus Torvalds1da177e2005-04-16 15:20:36 -07004795 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004796 conn = l2cap_conn_add(hcon, status);
4797 if (conn)
4798 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004799 } else
Joe Perchese1750722011-06-29 18:18:29 -07004800 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004801
4802 return 0;
4803}
4804
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004805int l2cap_disconn_ind(struct hci_conn *hcon)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004806{
4807 struct l2cap_conn *conn = hcon->l2cap_data;
4808
4809 BT_DBG("hcon %p", hcon);
4810
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004811 if (!conn)
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02004812 return HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01004813 return conn->disc_reason;
4814}
4815
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004816int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004817{
4818 BT_DBG("hcon %p reason %d", hcon, reason);
4819
Joe Perchese1750722011-06-29 18:18:29 -07004820 l2cap_conn_del(hcon, bt_to_errno(reason));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004821 return 0;
4822}
4823
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004824static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004825{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004826 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004827 return;
4828
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004829 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004830 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08004831 __set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004832 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004833 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004834 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004835 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004836 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004837 }
4838}
4839
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004840int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004841{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004842 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004843 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004844
Marcel Holtmann01394182006-07-03 10:02:46 +02004845 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004846 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004847
Linus Torvalds1da177e2005-04-16 15:20:36 -07004848 BT_DBG("conn %p", conn);
4849
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004850 if (hcon->type == LE_LINK) {
Hemant Gupta35d4adcc2012-04-18 14:46:26 +05304851 if (!status && encrypt)
4852 smp_distribute_keys(conn, 0);
Ulisses Furquim17cd3f32012-01-30 18:26:28 -02004853 cancel_delayed_work(&conn->security_timer);
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004854 }
4855
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004856 mutex_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004857
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004858 list_for_each_entry(chan, &conn->chan_l, list) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004859 l2cap_chan_lock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004860
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004861 BT_DBG("chan->scid %d", chan->scid);
4862
4863 if (chan->scid == L2CAP_CID_LE_DATA) {
4864 if (!status && encrypt) {
4865 chan->sec_level = hcon->sec_level;
Andrei Emeltchenkocf4cd002012-02-06 15:03:59 +02004866 l2cap_chan_ready(chan);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004867 }
4868
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004869 l2cap_chan_unlock(chan);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004870 continue;
4871 }
4872
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004873 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004874 l2cap_chan_unlock(chan);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004875 continue;
4876 }
4877
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004878 if (!status && (chan->state == BT_CONNECTED ||
4879 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004880 l2cap_check_encryption(chan, encrypt);
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004881 l2cap_chan_unlock(chan);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004882 continue;
4883 }
4884
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004885 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004886 if (!status) {
Andrei Emeltchenko9b27f352012-02-24 16:00:00 +02004887 l2cap_send_conn_req(chan);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004888 } else {
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08004889 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004890 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004891 } else if (chan->state == BT_CONNECT2) {
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004892 struct sock *sk = chan->sk;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004893 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004894 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004895
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004896 lock_sock(sk);
4897
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004898 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004899 if (bt_sk(sk)->defer_setup) {
4900 struct sock *parent = bt_sk(sk)->parent;
4901 res = L2CAP_CR_PEND;
4902 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004903 if (parent)
4904 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004905 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02004906 __l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004907 res = L2CAP_CR_SUCCESS;
4908 stat = L2CAP_CS_NO_INFO;
4909 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004910 } else {
Andrei Emeltchenko0e587be2012-02-21 12:54:57 +02004911 __l2cap_state_change(chan, BT_DISCONN);
Marcel Holtmannba13ccd2012-03-01 14:25:33 -08004912 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004913 res = L2CAP_CR_SEC_BLOCK;
4914 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004915 }
4916
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004917 release_sock(sk);
4918
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004919 rsp.scid = cpu_to_le16(chan->dcid);
4920 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004921 rsp.result = cpu_to_le16(res);
4922 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004923 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4924 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004925 }
4926
Andrei Emeltchenko6be36552012-02-22 17:11:56 +02004927 l2cap_chan_unlock(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004928 }
4929
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004930 mutex_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004931
Linus Torvalds1da177e2005-04-16 15:20:36 -07004932 return 0;
4933}
4934
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004935int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004936{
4937 struct l2cap_conn *conn = hcon->l2cap_data;
4938
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004939 if (!conn)
4940 conn = l2cap_conn_add(hcon, 0);
4941
4942 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004943 goto drop;
4944
4945 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4946
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004947 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004948 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004949 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004950 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004951 int len;
4952
4953 if (conn->rx_len) {
4954 BT_ERR("Unexpected start frame (len %d)", skb->len);
4955 kfree_skb(conn->rx_skb);
4956 conn->rx_skb = NULL;
4957 conn->rx_len = 0;
4958 l2cap_conn_unreliable(conn, ECOMM);
4959 }
4960
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004961 /* Start fragment always begin with Basic L2CAP header */
4962 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004963 BT_ERR("Frame is too short (len %d)", skb->len);
4964 l2cap_conn_unreliable(conn, ECOMM);
4965 goto drop;
4966 }
4967
4968 hdr = (struct l2cap_hdr *) skb->data;
4969 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004970 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004971
4972 if (len == skb->len) {
4973 /* Complete frame received */
4974 l2cap_recv_frame(conn, skb);
4975 return 0;
4976 }
4977
4978 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4979
4980 if (skb->len > len) {
4981 BT_ERR("Frame is too long (len %d, expected len %d)",
4982 skb->len, len);
4983 l2cap_conn_unreliable(conn, ECOMM);
4984 goto drop;
4985 }
4986
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004987 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004988
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004989 if (chan && chan->sk) {
4990 struct sock *sk = chan->sk;
Andrei Emeltchenko3df91ea2012-02-21 12:54:55 +02004991 lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004992
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004993 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004994 BT_ERR("Frame exceeding recv MTU (len %d, "
4995 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004996 chan->imtu);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004997 release_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004998 l2cap_conn_unreliable(conn, ECOMM);
4999 goto drop;
5000 }
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03005001 release_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03005002 }
5003
Linus Torvalds1da177e2005-04-16 15:20:36 -07005004 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03005005 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
5006 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005007 goto drop;
5008
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03005009 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01005010 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005011 conn->rx_len = len - skb->len;
5012 } else {
5013 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
5014
5015 if (!conn->rx_len) {
5016 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
5017 l2cap_conn_unreliable(conn, ECOMM);
5018 goto drop;
5019 }
5020
5021 if (skb->len > conn->rx_len) {
5022 BT_ERR("Fragment is too long (len %d, expected %d)",
5023 skb->len, conn->rx_len);
5024 kfree_skb(conn->rx_skb);
5025 conn->rx_skb = NULL;
5026 conn->rx_len = 0;
5027 l2cap_conn_unreliable(conn, ECOMM);
5028 goto drop;
5029 }
5030
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03005031 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01005032 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005033 conn->rx_len -= skb->len;
5034
5035 if (!conn->rx_len) {
5036 /* Complete frame received */
5037 l2cap_recv_frame(conn, conn->rx_skb);
5038 conn->rx_skb = NULL;
5039 }
5040 }
5041
5042drop:
5043 kfree_skb(skb);
5044 return 0;
5045}
5046
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005047static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005048{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005049 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005050
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02005051 read_lock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005053 list_for_each_entry(c, &chan_list, global_l) {
5054 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005055
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02005056 seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005057 batostr(&bt_sk(sk)->src),
5058 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03005059 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03005060 c->scid, c->dcid, c->imtu, c->omtu,
5061 c->sec_level, c->mode);
Andrei Emeltchenko61e1b4b2012-01-19 11:19:50 +02005062 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005063
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02005064 read_unlock(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08005065
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005066 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005067}
5068
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005069static int l2cap_debugfs_open(struct inode *inode, struct file *file)
5070{
5071 return single_open(file, l2cap_debugfs_show, inode->i_private);
5072}
5073
5074static const struct file_operations l2cap_debugfs_fops = {
5075 .open = l2cap_debugfs_open,
5076 .read = seq_read,
5077 .llseek = seq_lseek,
5078 .release = single_release,
5079};
5080
5081static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005082
Gustavo F. Padovan64274512011-02-07 20:08:52 -02005083int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005084{
5085 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08005086
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02005087 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005088 if (err < 0)
5089 return err;
5090
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005091 if (bt_debugfs) {
5092 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
5093 bt_debugfs, NULL, &l2cap_debugfs_fops);
5094 if (!l2cap_debugfs)
5095 BT_ERR("Failed to create L2CAP debug file");
5096 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005097
Linus Torvalds1da177e2005-04-16 15:20:36 -07005098 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005099}
5100
Gustavo F. Padovan64274512011-02-07 20:08:52 -02005101void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005102{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01005103 debugfs_remove(l2cap_debugfs);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02005104 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005105}
5106
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03005107module_param(disable_ertm, bool, 0644);
5108MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");