Blame view

net/bluetooth/l2cap_core.c 107 KB
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
     BlueZ - Bluetooth protocol stack for Linux
     Copyright (C) 2000-2001 Qualcomm Incorporated
ce5706bd6   Gustavo F. Padovan   Bluetooth: Add Co...
4
     Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
5d8868ff3   Gustavo F. Padovan   Bluetooth: Add Go...
5
     Copyright (C) 2010 Google Inc.
590051de5   Gustavo F. Padovan   Bluetooth: Add Pr...
6
     Copyright (C) 2011 ProFUSION Embedded Systems
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
9
10
11
12
13
14
15
16
17
  
     Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
  
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License version 2 as
     published by the Free Software Foundation;
  
     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
     IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
18
19
20
     CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
     WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
22
23
     ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
     COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
     SOFTWARE IS DISCLAIMED.
  */
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
26
  /* Bluetooth L2CAP core. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
30
  #include <linux/module.h>
  
  #include <linux/types.h>
4fc268d24   Randy Dunlap   [PATCH] capable/c...
31
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
  #include <linux/errno.h>
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
37
38
39
40
41
  #include <linux/sched.h>
  #include <linux/slab.h>
  #include <linux/poll.h>
  #include <linux/fcntl.h>
  #include <linux/init.h>
  #include <linux/interrupt.h>
  #include <linux/socket.h>
  #include <linux/skbuff.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  #include <linux/list.h>
be9d12273   Marcel Holtmann   [Bluetooth]: Remo...
43
  #include <linux/device.h>
aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
44
45
  #include <linux/debugfs.h>
  #include <linux/seq_file.h>
af05b30bc   Gustavo F. Padovan   Bluetooth: Fix er...
46
  #include <linux/uaccess.h>
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
47
  #include <linux/crc16.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
50
  #include <net/sock.h>
  
  #include <asm/system.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
53
54
55
  #include <asm/unaligned.h>
  
  #include <net/bluetooth/bluetooth.h>
  #include <net/bluetooth/hci_core.h>
  #include <net/bluetooth/l2cap.h>
b501d6a1d   Anderson Briglia   Bluetooth: Start ...
56
  #include <net/bluetooth/smp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57

eb9399220   Rusty Russell   module_param: mak...
58
  bool disable_ertm;
f0709e03a   Marcel Holtmann   [Bluetooth] Adver...
59

47ec1dcd6   Marcel Holtmann   Bluetooth: Add ba...
60
  static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
50a147cd9   Mat Martineau   Bluetooth: Use sy...
61
  static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62

b5ad8b7f8   Johannes Berg   Bluetooth: fix sp...
63
64
  static LIST_HEAD(chan_list);
  static DEFINE_RWLOCK(chan_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
  static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
  				u8 code, u8 ident, u16 dlen, void *data);
4519de9a0   Gustavo F. Padovan   Bluetooth: Create...
68
69
  static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
  								void *data);
710f9b0a4   Gustavo F. Padovan   Bluetooth: clean ...
70
  static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
4519de9a0   Gustavo F. Padovan   Bluetooth: Create...
71
72
  static void l2cap_send_disconn_req(struct l2cap_conn *conn,
  				struct l2cap_chan *chan, int err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73

218bb9dfd   Gustavo F. Padovan   Bluetooth: Add ba...
74
  static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
0139418c9   Marcel Holtmann   [Bluetooth] Small...
75
  /* ---- L2CAP channels ---- */
71ba0e569   Gustavo F. Padovan   Bluetooth: Add re...
76

baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
77
  static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
0139418c9   Marcel Holtmann   [Bluetooth] Small...
78
  {
3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
79
  	struct l2cap_chan *c, *r = NULL;
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
80

3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
81
82
83
84
85
86
87
  	rcu_read_lock();
  
  	list_for_each_entry_rcu(c, &conn->chan_l, list) {
  		if (c->dcid == cid) {
  			r = c;
  			break;
  		}
0139418c9   Marcel Holtmann   [Bluetooth] Small...
88
  	}
3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
89
90
91
  
  	rcu_read_unlock();
  	return r;
0139418c9   Marcel Holtmann   [Bluetooth] Small...
92
  }
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
93
  static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
0139418c9   Marcel Holtmann   [Bluetooth] Small...
94
  {
3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
95
  	struct l2cap_chan *c, *r = NULL;
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
96

3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
97
98
99
100
101
102
103
  	rcu_read_lock();
  
  	list_for_each_entry_rcu(c, &conn->chan_l, list) {
  		if (c->scid == cid) {
  			r = c;
  			break;
  		}
0139418c9   Marcel Holtmann   [Bluetooth] Small...
104
  	}
3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
105
106
107
  
  	rcu_read_unlock();
  	return r;
0139418c9   Marcel Holtmann   [Bluetooth] Small...
108
109
110
111
  }
  
  /* Find channel with given SCID.
   * Returns locked socket */
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
112
  static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
0139418c9   Marcel Holtmann   [Bluetooth] Small...
113
  {
48454079c   Gustavo F. Padovan   Bluetooth: Create...
114
  	struct l2cap_chan *c;
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
115

baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
116
  	c = __l2cap_get_chan_by_scid(conn, cid);
48454079c   Gustavo F. Padovan   Bluetooth: Create...
117
  	if (c)
aa2ac881b   Gustavo F. Padovan   Bluetooth: Don't ...
118
  		lock_sock(c->sk);
48454079c   Gustavo F. Padovan   Bluetooth: Create...
119
  	return c;
0139418c9   Marcel Holtmann   [Bluetooth] Small...
120
  }
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
121
  static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
0139418c9   Marcel Holtmann   [Bluetooth] Small...
122
  {
3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
123
  	struct l2cap_chan *c, *r = NULL;
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
124

3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
125
126
127
128
129
130
131
  	rcu_read_lock();
  
  	list_for_each_entry_rcu(c, &conn->chan_l, list) {
  		if (c->ident == ident) {
  			r = c;
  			break;
  		}
0139418c9   Marcel Holtmann   [Bluetooth] Small...
132
  	}
3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
133
134
135
  
  	rcu_read_unlock();
  	return r;
0139418c9   Marcel Holtmann   [Bluetooth] Small...
136
  }
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
137
  static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
0139418c9   Marcel Holtmann   [Bluetooth] Small...
138
  {
48454079c   Gustavo F. Padovan   Bluetooth: Create...
139
  	struct l2cap_chan *c;
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
140

baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
141
  	c = __l2cap_get_chan_by_ident(conn, ident);
48454079c   Gustavo F. Padovan   Bluetooth: Create...
142
  	if (c)
aa2ac881b   Gustavo F. Padovan   Bluetooth: Don't ...
143
  		lock_sock(c->sk);
48454079c   Gustavo F. Padovan   Bluetooth: Create...
144
  	return c;
0139418c9   Marcel Holtmann   [Bluetooth] Small...
145
  }
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
146
  static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
9e4425fff   Gustavo F. Padovan   Bluetooth: Add l2...
147
  {
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
148
  	struct l2cap_chan *c;
9e4425fff   Gustavo F. Padovan   Bluetooth: Add l2...
149

23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
150
151
  	list_for_each_entry(c, &chan_list, global_l) {
  		if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
250938cb3   Szymon Janc   Bluetooth: Simpli...
152
  			return c;
9e4425fff   Gustavo F. Padovan   Bluetooth: Add l2...
153
  	}
250938cb3   Szymon Janc   Bluetooth: Simpli...
154
  	return NULL;
9e4425fff   Gustavo F. Padovan   Bluetooth: Add l2...
155
156
157
158
  }
  
  int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
  {
73b2ec185   Gustavo F. Padovan   Bluetooth: Handle...
159
  	int err;
333055f2a   Gustavo F. Padovan   Bluetooth: Don't ...
160
  	write_lock(&chan_list_lock);
9e4425fff   Gustavo F. Padovan   Bluetooth: Add l2...
161

23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
162
  	if (psm && __l2cap_global_chan_by_addr(psm, src)) {
73b2ec185   Gustavo F. Padovan   Bluetooth: Handle...
163
164
  		err = -EADDRINUSE;
  		goto done;
9e4425fff   Gustavo F. Padovan   Bluetooth: Add l2...
165
  	}
73b2ec185   Gustavo F. Padovan   Bluetooth: Handle...
166
167
168
169
170
171
172
173
174
  	if (psm) {
  		chan->psm = psm;
  		chan->sport = psm;
  		err = 0;
  	} else {
  		u16 p;
  
  		err = -EINVAL;
  		for (p = 0x1001; p < 0x1100; p += 2)
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
175
  			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
73b2ec185   Gustavo F. Padovan   Bluetooth: Handle...
176
177
178
179
180
181
  				chan->psm   = cpu_to_le16(p);
  				chan->sport = cpu_to_le16(p);
  				err = 0;
  				break;
  			}
  	}
9e4425fff   Gustavo F. Padovan   Bluetooth: Add l2...
182

73b2ec185   Gustavo F. Padovan   Bluetooth: Handle...
183
  done:
333055f2a   Gustavo F. Padovan   Bluetooth: Don't ...
184
  	write_unlock(&chan_list_lock);
73b2ec185   Gustavo F. Padovan   Bluetooth: Handle...
185
  	return err;
9e4425fff   Gustavo F. Padovan   Bluetooth: Add l2...
186
187
188
189
  }
  
  int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
  {
333055f2a   Gustavo F. Padovan   Bluetooth: Don't ...
190
  	write_lock(&chan_list_lock);
9e4425fff   Gustavo F. Padovan   Bluetooth: Add l2...
191
192
  
  	chan->scid = scid;
333055f2a   Gustavo F. Padovan   Bluetooth: Don't ...
193
  	write_unlock(&chan_list_lock);
9e4425fff   Gustavo F. Padovan   Bluetooth: Add l2...
194
195
196
  
  	return 0;
  }
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
197
  static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
0139418c9   Marcel Holtmann   [Bluetooth] Small...
198
  {
8db4dc46d   Gustavo F. Padovan   Bluetooth: Use ma...
199
  	u16 cid = L2CAP_CID_DYN_START;
0139418c9   Marcel Holtmann   [Bluetooth] Small...
200

8db4dc46d   Gustavo F. Padovan   Bluetooth: Use ma...
201
  	for (; cid < L2CAP_CID_DYN_END; cid++) {
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
202
  		if (!__l2cap_get_chan_by_scid(conn, cid))
0139418c9   Marcel Holtmann   [Bluetooth] Small...
203
204
205
206
207
  			return cid;
  	}
  
  	return 0;
  }
badaaa00f   Gustavo F. Padovan   Bluetooth: Add us...
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  static char *state_to_string(int state)
  {
  	switch(state) {
  	case BT_CONNECTED:
  		return "BT_CONNECTED";
  	case BT_OPEN:
  		return "BT_OPEN";
  	case BT_BOUND:
  		return "BT_BOUND";
  	case BT_LISTEN:
  		return "BT_LISTEN";
  	case BT_CONNECT:
  		return "BT_CONNECT";
  	case BT_CONNECT2:
  		return "BT_CONNECT2";
  	case BT_CONFIG:
  		return "BT_CONFIG";
  	case BT_DISCONN:
  		return "BT_DISCONN";
  	case BT_CLOSED:
  		return "BT_CLOSED";
  	}
  
  	return "invalid state";
  }
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
233
234
  static void l2cap_state_change(struct l2cap_chan *chan, int state)
  {
badaaa00f   Gustavo F. Padovan   Bluetooth: Add us...
235
236
  	BT_DBG("%p %s -> %s", chan, state_to_string(chan->state),
  						state_to_string(state));
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
237
238
239
  	chan->state = state;
  	chan->ops->state_change(chan->data, state);
  }
721c41812   Gustavo F. Padovan   Bluetooth: Move L...
240
  static void l2cap_chan_timeout(struct work_struct *work)
ab07801d2   Gustavo F. Padovan   Bluetooth: create...
241
  {
721c41812   Gustavo F. Padovan   Bluetooth: Move L...
242
243
  	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
  							chan_timer.work);
ab07801d2   Gustavo F. Padovan   Bluetooth: create...
244
245
  	struct sock *sk = chan->sk;
  	int reason;
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
246
  	BT_DBG("chan %p state %d", chan, chan->state);
ab07801d2   Gustavo F. Padovan   Bluetooth: create...
247

721c41812   Gustavo F. Padovan   Bluetooth: Move L...
248
  	lock_sock(sk);
ab07801d2   Gustavo F. Padovan   Bluetooth: create...
249

89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
250
  	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
ab07801d2   Gustavo F. Padovan   Bluetooth: create...
251
  		reason = ECONNREFUSED;
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
252
  	else if (chan->state == BT_CONNECT &&
ab07801d2   Gustavo F. Padovan   Bluetooth: create...
253
254
255
256
  					chan->sec_level != BT_SECURITY_SDP)
  		reason = ECONNREFUSED;
  	else
  		reason = ETIMEDOUT;
0f8527249   Gustavo F. Padovan   Bluetooth: Rename...
257
  	l2cap_chan_close(chan, reason);
ab07801d2   Gustavo F. Padovan   Bluetooth: create...
258

721c41812   Gustavo F. Padovan   Bluetooth: Move L...
259
  	release_sock(sk);
ab07801d2   Gustavo F. Padovan   Bluetooth: create...
260

ba3bd0ee3   Gustavo F. Padovan   Bluetooth: add cl...
261
  	chan->ops->close(chan->data);
371fd8356   Ulisses Furquim   Bluetooth: Fix de...
262
  	l2cap_chan_put(chan);
ab07801d2   Gustavo F. Padovan   Bluetooth: create...
263
  }
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
264
  struct l2cap_chan *l2cap_chan_create(struct sock *sk)
48454079c   Gustavo F. Padovan   Bluetooth: Create...
265
266
267
268
269
270
271
272
  {
  	struct l2cap_chan *chan;
  
  	chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
  	if (!chan)
  		return NULL;
  
  	chan->sk = sk;
333055f2a   Gustavo F. Padovan   Bluetooth: Don't ...
273
  	write_lock(&chan_list_lock);
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
274
  	list_add(&chan->global_l, &chan_list);
333055f2a   Gustavo F. Padovan   Bluetooth: Don't ...
275
  	write_unlock(&chan_list_lock);
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
276

721c41812   Gustavo F. Padovan   Bluetooth: Move L...
277
  	INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
ab07801d2   Gustavo F. Padovan   Bluetooth: create...
278

89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
279
  	chan->state = BT_OPEN;
71ba0e569   Gustavo F. Padovan   Bluetooth: Add re...
280
  	atomic_set(&chan->refcnt, 1);
abc545b8e   Szymon Janc   Bluetooth: Add de...
281
  	BT_DBG("sk %p chan %p", sk, chan);
48454079c   Gustavo F. Padovan   Bluetooth: Create...
282
283
  	return chan;
  }
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
284
  void l2cap_chan_destroy(struct l2cap_chan *chan)
6ff5abbf4   Gustavo F. Padovan   Bluetooth: Fix me...
285
  {
333055f2a   Gustavo F. Padovan   Bluetooth: Don't ...
286
  	write_lock(&chan_list_lock);
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
287
  	list_del(&chan->global_l);
333055f2a   Gustavo F. Padovan   Bluetooth: Don't ...
288
  	write_unlock(&chan_list_lock);
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
289

371fd8356   Ulisses Furquim   Bluetooth: Fix de...
290
  	l2cap_chan_put(chan);
6ff5abbf4   Gustavo F. Padovan   Bluetooth: Fix me...
291
  }
3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
292
  static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
0139418c9   Marcel Holtmann   [Bluetooth] Small...
293
  {
af05b30bc   Gustavo F. Padovan   Bluetooth: Fix er...
294
  	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
295
  			chan->psm, chan->dcid);
0139418c9   Marcel Holtmann   [Bluetooth] Small...
296

9f5a0d7bf   Andrei Emeltchenko   Bluetooth: Define...
297
  	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
2950f21ac   Marcel Holtmann   Bluetooth: Ask up...
298

8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
299
  	chan->conn = conn;
0139418c9   Marcel Holtmann   [Bluetooth] Small...
300

715ec005c   Gustavo F. Padovan   Bluetooth: Add ch...
301
  	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
b62f328b8   Ville Tervo   Bluetooth: Add se...
302
303
  		if (conn->hcon->type == LE_LINK) {
  			/* LE connection */
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
304
  			chan->omtu = L2CAP_LE_DEFAULT_MTU;
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
305
306
  			chan->scid = L2CAP_CID_LE_DATA;
  			chan->dcid = L2CAP_CID_LE_DATA;
b62f328b8   Ville Tervo   Bluetooth: Add se...
307
308
  		} else {
  			/* Alloc CID for connection-oriented socket */
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
309
  			chan->scid = l2cap_alloc_cid(conn);
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
310
  			chan->omtu = L2CAP_DEFAULT_MTU;
b62f328b8   Ville Tervo   Bluetooth: Add se...
311
  		}
715ec005c   Gustavo F. Padovan   Bluetooth: Add ch...
312
  	} else if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
0139418c9   Marcel Holtmann   [Bluetooth] Small...
313
  		/* Connectionless socket */
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
314
315
  		chan->scid = L2CAP_CID_CONN_LESS;
  		chan->dcid = L2CAP_CID_CONN_LESS;
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
316
  		chan->omtu = L2CAP_DEFAULT_MTU;
0139418c9   Marcel Holtmann   [Bluetooth] Small...
317
318
  	} else {
  		/* Raw socket can send/recv signalling messages only */
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
319
320
  		chan->scid = L2CAP_CID_SIGNALING;
  		chan->dcid = L2CAP_CID_SIGNALING;
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
321
  		chan->omtu = L2CAP_DEFAULT_MTU;
0139418c9   Marcel Holtmann   [Bluetooth] Small...
322
  	}
8f7975b15   Andrei Emeltchenko   Bluetooth: EFS: a...
323
324
325
326
327
328
  	chan->local_id		= L2CAP_BESTEFFORT_ID;
  	chan->local_stype	= L2CAP_SERV_BESTEFFORT;
  	chan->local_msdu	= L2CAP_DEFAULT_MAX_SDU_SIZE;
  	chan->local_sdu_itime	= L2CAP_DEFAULT_SDU_ITIME;
  	chan->local_acc_lat	= L2CAP_DEFAULT_ACC_LAT;
  	chan->local_flush_to	= L2CAP_DEFAULT_FLUSH_TO;
371fd8356   Ulisses Furquim   Bluetooth: Fix de...
329
  	l2cap_chan_hold(chan);
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
330

3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
331
  	list_add_rcu(&chan->list, &conn->chan_l);
0139418c9   Marcel Holtmann   [Bluetooth] Small...
332
  }
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
333
  /* Delete channel.
0139418c9   Marcel Holtmann   [Bluetooth] Small...
334
   * Must be called on the locked socket. */
4519de9a0   Gustavo F. Padovan   Bluetooth: Create...
335
  static void l2cap_chan_del(struct l2cap_chan *chan, int err)
0139418c9   Marcel Holtmann   [Bluetooth] Small...
336
  {
48454079c   Gustavo F. Padovan   Bluetooth: Create...
337
  	struct sock *sk = chan->sk;
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
338
  	struct l2cap_conn *conn = chan->conn;
0139418c9   Marcel Holtmann   [Bluetooth] Small...
339
  	struct sock *parent = bt_sk(sk)->parent;
c9b666753   Gustavo F. Padovan   Bluetooth: Make t...
340
  	__clear_chan_timer(chan);
0139418c9   Marcel Holtmann   [Bluetooth] Small...
341

49208c9c7   Gustavo F. Padovan   Bluetooth: Remove...
342
  	BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
0139418c9   Marcel Holtmann   [Bluetooth] Small...
343

8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
344
  	if (conn) {
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
345
  		/* Delete from channel list */
3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
346
347
  		list_del_rcu(&chan->list);
  		synchronize_rcu();
371fd8356   Ulisses Furquim   Bluetooth: Fix de...
348
  		l2cap_chan_put(chan);
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
349

8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
350
  		chan->conn = NULL;
0139418c9   Marcel Holtmann   [Bluetooth] Small...
351
352
  		hci_conn_put(conn->hcon);
  	}
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
353
  	l2cap_state_change(chan, BT_CLOSED);
0139418c9   Marcel Holtmann   [Bluetooth] Small...
354
355
356
357
358
359
360
361
362
363
  	sock_set_flag(sk, SOCK_ZAPPED);
  
  	if (err)
  		sk->sk_err = err;
  
  	if (parent) {
  		bt_accept_unlink(sk);
  		parent->sk_data_ready(parent, 0);
  	} else
  		sk->sk_state_change(sk);
c13ffa620   Gustavo F. Padovan   Bluetooth: Proper...
364

c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
365
366
  	if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
  			test_bit(CONF_INPUT_DONE, &chan->conf_state)))
6ff5abbf4   Gustavo F. Padovan   Bluetooth: Fix me...
367
  		return;
2ead70b83   Gustavo F. Padovan   Bluetooth: Fix lo...
368

58d35f87e   Gustavo F. Padovan   Bluetooth: Move t...
369
  	skb_queue_purge(&chan->tx_q);
c13ffa620   Gustavo F. Padovan   Bluetooth: Proper...
370

0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
371
  	if (chan->mode == L2CAP_MODE_ERTM) {
c13ffa620   Gustavo F. Padovan   Bluetooth: Proper...
372
  		struct srej_list *l, *tmp;
1a09bcb97   Gustavo F. Padovan   Bluetooth: keep r...
373
374
375
  		__clear_retrans_timer(chan);
  		__clear_monitor_timer(chan);
  		__clear_ack_timer(chan);
c13ffa620   Gustavo F. Padovan   Bluetooth: Proper...
376

f1c6775be   Gustavo F. Padovan   Bluetooth: Move s...
377
  		skb_queue_purge(&chan->srej_q);
c13ffa620   Gustavo F. Padovan   Bluetooth: Proper...
378

39d5a3ee3   Gustavo F. Padovan   Bluetooth: Move S...
379
  		list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
c13ffa620   Gustavo F. Padovan   Bluetooth: Proper...
380
381
382
383
  			list_del(&l->list);
  			kfree(l);
  		}
  	}
0139418c9   Marcel Holtmann   [Bluetooth] Small...
384
  }
4519de9a0   Gustavo F. Padovan   Bluetooth: Create...
385
386
387
388
389
390
391
  static void l2cap_chan_cleanup_listen(struct sock *parent)
  {
  	struct sock *sk;
  
  	BT_DBG("parent %p", parent);
  
  	/* Close not yet accepted channels */
0f8527249   Gustavo F. Padovan   Bluetooth: Rename...
392
  	while ((sk = bt_accept_dequeue(parent, NULL))) {
ba3bd0ee3   Gustavo F. Padovan   Bluetooth: add cl...
393
  		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
c9b666753   Gustavo F. Padovan   Bluetooth: Make t...
394
  		__clear_chan_timer(chan);
0f8527249   Gustavo F. Padovan   Bluetooth: Rename...
395
  		lock_sock(sk);
ba3bd0ee3   Gustavo F. Padovan   Bluetooth: add cl...
396
  		l2cap_chan_close(chan, ECONNRESET);
0f8527249   Gustavo F. Padovan   Bluetooth: Rename...
397
  		release_sock(sk);
ba3bd0ee3   Gustavo F. Padovan   Bluetooth: add cl...
398
  		chan->ops->close(chan->data);
0f8527249   Gustavo F. Padovan   Bluetooth: Rename...
399
  	}
4519de9a0   Gustavo F. Padovan   Bluetooth: Create...
400
  }
0f8527249   Gustavo F. Padovan   Bluetooth: Rename...
401
  void l2cap_chan_close(struct l2cap_chan *chan, int reason)
4519de9a0   Gustavo F. Padovan   Bluetooth: Create...
402
403
404
  {
  	struct l2cap_conn *conn = chan->conn;
  	struct sock *sk = chan->sk;
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
405
  	BT_DBG("chan %p state %d socket %p", chan, chan->state, sk->sk_socket);
4519de9a0   Gustavo F. Padovan   Bluetooth: Create...
406

89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
407
  	switch (chan->state) {
4519de9a0   Gustavo F. Padovan   Bluetooth: Create...
408
409
  	case BT_LISTEN:
  		l2cap_chan_cleanup_listen(sk);
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
410
411
412
  
  		l2cap_state_change(chan, BT_CLOSED);
  		sock_set_flag(sk, SOCK_ZAPPED);
4519de9a0   Gustavo F. Padovan   Bluetooth: Create...
413
414
415
416
  		break;
  
  	case BT_CONNECTED:
  	case BT_CONFIG:
715ec005c   Gustavo F. Padovan   Bluetooth: Add ch...
417
  		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
4519de9a0   Gustavo F. Padovan   Bluetooth: Create...
418
  					conn->hcon->type == ACL_LINK) {
c9b666753   Gustavo F. Padovan   Bluetooth: Make t...
419
420
  			__clear_chan_timer(chan);
  			__set_chan_timer(chan, sk->sk_sndtimeo);
4519de9a0   Gustavo F. Padovan   Bluetooth: Create...
421
422
423
424
425
426
  			l2cap_send_disconn_req(conn, chan, reason);
  		} else
  			l2cap_chan_del(chan, reason);
  		break;
  
  	case BT_CONNECT2:
715ec005c   Gustavo F. Padovan   Bluetooth: Add ch...
427
  		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
4519de9a0   Gustavo F. Padovan   Bluetooth: Create...
428
429
430
431
432
433
434
435
  					conn->hcon->type == ACL_LINK) {
  			struct l2cap_conn_rsp rsp;
  			__u16 result;
  
  			if (bt_sk(sk)->defer_setup)
  				result = L2CAP_CR_SEC_BLOCK;
  			else
  				result = L2CAP_CR_BAD_PSM;
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
436
  			l2cap_state_change(chan, BT_DISCONN);
4519de9a0   Gustavo F. Padovan   Bluetooth: Create...
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
  
  			rsp.scid   = cpu_to_le16(chan->dcid);
  			rsp.dcid   = cpu_to_le16(chan->scid);
  			rsp.result = cpu_to_le16(result);
  			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
  			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
  							sizeof(rsp), &rsp);
  		}
  
  		l2cap_chan_del(chan, reason);
  		break;
  
  	case BT_CONNECT:
  	case BT_DISCONN:
  		l2cap_chan_del(chan, reason);
  		break;
  
  	default:
  		sock_set_flag(sk, SOCK_ZAPPED);
  		break;
  	}
  }
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
459
  static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
460
  {
715ec005c   Gustavo F. Padovan   Bluetooth: Add ch...
461
  	if (chan->chan_type == L2CAP_CHAN_RAW) {
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
462
  		switch (chan->sec_level) {
8556edd32   Johan Hedberg   Bluetooth: Create...
463
464
465
466
467
468
469
  		case BT_SECURITY_HIGH:
  			return HCI_AT_DEDICATED_BONDING_MITM;
  		case BT_SECURITY_MEDIUM:
  			return HCI_AT_DEDICATED_BONDING;
  		default:
  			return HCI_AT_NO_BONDING;
  		}
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
470
  	} else if (chan->psm == cpu_to_le16(0x0001)) {
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
471
472
  		if (chan->sec_level == BT_SECURITY_LOW)
  			chan->sec_level = BT_SECURITY_SDP;
0684e5f9f   Marcel Holtmann   Bluetooth: Use ge...
473

4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
474
  		if (chan->sec_level == BT_SECURITY_HIGH)
8556edd32   Johan Hedberg   Bluetooth: Create...
475
  			return HCI_AT_NO_BONDING_MITM;
00ae4af91   Marcel Holtmann   Bluetooth: Fix au...
476
  		else
8556edd32   Johan Hedberg   Bluetooth: Create...
477
  			return HCI_AT_NO_BONDING;
00ae4af91   Marcel Holtmann   Bluetooth: Fix au...
478
  	} else {
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
479
  		switch (chan->sec_level) {
00ae4af91   Marcel Holtmann   Bluetooth: Fix au...
480
  		case BT_SECURITY_HIGH:
8556edd32   Johan Hedberg   Bluetooth: Create...
481
  			return HCI_AT_GENERAL_BONDING_MITM;
00ae4af91   Marcel Holtmann   Bluetooth: Fix au...
482
  		case BT_SECURITY_MEDIUM:
8556edd32   Johan Hedberg   Bluetooth: Create...
483
  			return HCI_AT_GENERAL_BONDING;
00ae4af91   Marcel Holtmann   Bluetooth: Fix au...
484
  		default:
8556edd32   Johan Hedberg   Bluetooth: Create...
485
  			return HCI_AT_NO_BONDING;
00ae4af91   Marcel Holtmann   Bluetooth: Fix au...
486
  		}
0684e5f9f   Marcel Holtmann   Bluetooth: Use ge...
487
  	}
8556edd32   Johan Hedberg   Bluetooth: Create...
488
489
490
  }
  
  /* Service level security */
d45fc4232   Gustavo F. Padovan   Bluetooth: Rename...
491
  int l2cap_chan_check_security(struct l2cap_chan *chan)
8556edd32   Johan Hedberg   Bluetooth: Create...
492
  {
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
493
  	struct l2cap_conn *conn = chan->conn;
8556edd32   Johan Hedberg   Bluetooth: Create...
494
  	__u8 auth_type;
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
495
  	auth_type = l2cap_get_auth_type(chan);
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
496

4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
497
  	return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
498
  }
b5ad8b7f8   Johannes Berg   Bluetooth: fix sp...
499
  static u8 l2cap_get_ident(struct l2cap_conn *conn)
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
500
501
502
503
504
505
506
507
  {
  	u8 id;
  
  	/* Get next available identificator.
  	 *    1 - 128 are used by kernel.
  	 *  129 - 199 are reserved.
  	 *  200 - 254 are used by utilities like l2ping, etc.
  	 */
333055f2a   Gustavo F. Padovan   Bluetooth: Don't ...
508
  	spin_lock(&conn->lock);
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
509
510
511
512
513
  
  	if (++conn->tx_ident > 128)
  		conn->tx_ident = 1;
  
  	id = conn->tx_ident;
333055f2a   Gustavo F. Padovan   Bluetooth: Don't ...
514
  	spin_unlock(&conn->lock);
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
515
516
517
  
  	return id;
  }
4519de9a0   Gustavo F. Padovan   Bluetooth: Create...
518
  static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
519
520
  {
  	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
e702112ff   Andrei Emeltchenko   Bluetooth: Use no...
521
  	u8 flags;
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
522
523
524
525
  
  	BT_DBG("code 0x%2.2x", code);
  
  	if (!skb)
9a9c6a344   Gustavo F. Padovan   Bluetooth: Make h...
526
  		return;
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
527

e702112ff   Andrei Emeltchenko   Bluetooth: Use no...
528
529
530
531
  	if (lmp_no_flush_capable(conn->hcon->hdev))
  		flags = ACL_START_NO_FLUSH;
  	else
  		flags = ACL_START;
14b12d0b9   Jaikumar Ganesh   Bluetooth: Add BT...
532
  	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
5e59b791c   Luiz Augusto von Dentz   Bluetooth: set sk...
533
  	skb->priority = HCI_PRIO_MAX;
14b12d0b9   Jaikumar Ganesh   Bluetooth: Add BT...
534

73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
  	hci_send_acl(conn->hchan, skb, flags);
  }
  
  static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
  {
  	struct hci_conn *hcon = chan->conn->hcon;
  	u16 flags;
  
  	BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
  							skb->priority);
  
  	if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
  					lmp_no_flush_capable(hcon->hdev))
  		flags = ACL_START_NO_FLUSH;
  	else
  		flags = ACL_START;
14b12d0b9   Jaikumar Ganesh   Bluetooth: Add BT...
551

73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
552
553
  	bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
  	hci_send_acl(chan->conn->hchan, skb, flags);
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
554
  }
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
555
  static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
556
557
558
  {
  	struct sk_buff *skb;
  	struct l2cap_hdr *lh;
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
559
  	struct l2cap_conn *conn = chan->conn;
e4ca6d985   Andrei Emeltchenko   Bluetooth: EWS: r...
560
  	int count, hlen;
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
561

89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
562
  	if (chan->state != BT_CONNECTED)
c13ffa620   Gustavo F. Padovan   Bluetooth: Proper...
563
  		return;
e4ca6d985   Andrei Emeltchenko   Bluetooth: EWS: r...
564
565
566
567
  	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
  		hlen = L2CAP_EXT_HDR_SIZE;
  	else
  		hlen = L2CAP_ENH_HDR_SIZE;
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
568
  	if (chan->fcs == L2CAP_FCS_CRC16)
03a512137   Andrei Emeltchenko   Bluetooth: EWS: r...
569
  		hlen += L2CAP_FCS_SIZE;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
570

88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
571
  	BT_DBG("chan %p, control 0x%8.8x", chan, control);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
572

fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
573
  	count = min_t(unsigned int, conn->mtu, hlen);
793c2f1cb   Andrei Emeltchenko   Bluetooth: EWS: r...
574
575
  
  	control |= __set_sframe(chan);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
576

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
577
  	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
03f6715d4   Andrei Emeltchenko   Bluetooth: EWS: r...
578
  		control |= __set_ctrl_final(chan);
9e917af13   Gustavo F. Padovan   Bluetooth: Implem...
579

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
580
  	if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
e37817353   Andrei Emeltchenko   Bluetooth: EWS: r...
581
  		control |= __set_ctrl_poll(chan);
f0946ccfc   Gustavo F. Padovan   Bluetooth: Move s...
582

1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
583
584
  	skb = bt_skb_alloc(count, GFP_ATOMIC);
  	if (!skb)
9a9c6a344   Gustavo F. Padovan   Bluetooth: Make h...
585
  		return;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
586
587
  
  	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
588
  	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
589
  	lh->cid = cpu_to_le16(chan->dcid);
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
590
591
  
  	__put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
592

47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
593
  	if (chan->fcs == L2CAP_FCS_CRC16) {
03a512137   Andrei Emeltchenko   Bluetooth: EWS: r...
594
595
  		u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
  		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
596
  	}
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
597
598
  	skb->priority = HCI_PRIO_MAX;
  	l2cap_do_send(chan, skb);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
599
  }
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
600
  static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
7e7430908   Gustavo F. Padovan   Bluetooth: Add su...
601
  {
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
602
  	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
ab784b738   Andrei Emeltchenko   Bluetooth: EWS: r...
603
  		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
604
  		set_bit(CONN_RNR_SENT, &chan->conn_state);
1890d36bb   Gustavo F. Padovan   Bluetooth: Implem...
605
  	} else
ab784b738   Andrei Emeltchenko   Bluetooth: EWS: r...
606
  		control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
7e7430908   Gustavo F. Padovan   Bluetooth: Add su...
607

0b209fae8   Andrei Emeltchenko   Bluetooth: EWS: r...
608
  	control |= __set_reqseq(chan, chan->buffer_seq);
2ab25cdd7   Gustavo F. Padovan   Bluetooth: Fix 'S...
609

525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
610
  	l2cap_send_sframe(chan, control);
7e7430908   Gustavo F. Padovan   Bluetooth: Add su...
611
  }
b44500351   Gustavo F. Padovan   Bluetooth: Move c...
612
  static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
e501d0553   Andrei Emeltchenko   Bluetooth: Check ...
613
  {
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
614
  	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
e501d0553   Andrei Emeltchenko   Bluetooth: Check ...
615
  }
fc7f8a7ed   Gustavo F. Padovan   Bluetooth: Move i...
616
  static void l2cap_do_start(struct l2cap_chan *chan)
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
617
  {
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
618
  	struct l2cap_conn *conn = chan->conn;
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
619
620
  
  	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
984947dc6   Marcel Holtmann   Bluetooth: Fix ra...
621
622
  		if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
  			return;
d45fc4232   Gustavo F. Padovan   Bluetooth: Rename...
623
  		if (l2cap_chan_check_security(chan) &&
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
624
  				__l2cap_no_conn_pending(chan)) {
b1235d796   Marcel Holtmann   [Bluetooth] Allow...
625
  			struct l2cap_conn_req req;
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
626
627
  			req.scid = cpu_to_le16(chan->scid);
  			req.psm  = chan->psm;
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
628

fc7f8a7ed   Gustavo F. Padovan   Bluetooth: Move i...
629
  			chan->ident = l2cap_get_ident(conn);
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
630
  			set_bit(CONF_CONNECT_PEND, &chan->conf_state);
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
631

fc7f8a7ed   Gustavo F. Padovan   Bluetooth: Move i...
632
633
  			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
  							sizeof(req), &req);
b1235d796   Marcel Holtmann   [Bluetooth] Allow...
634
  		}
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
635
636
637
638
639
640
  	} else {
  		struct l2cap_info_req req;
  		req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
  
  		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
  		conn->info_ident = l2cap_get_ident(conn);
030013d85   Gustavo F. Padovan   Bluetooth: Rename...
641
  		schedule_delayed_work(&conn->info_timer,
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
642
643
644
645
646
647
  					msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
  
  		l2cap_send_cmd(conn, conn->info_ident,
  					L2CAP_INFO_REQ, sizeof(req), &req);
  	}
  }
cf6c2c0b9   Gustavo F. Padovan   Bluetooth: Discon...
648
649
650
  static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
  {
  	u32 local_feat_mask = l2cap_feat_mask;
d1c4a17d5   Gustavo F. Padovan   Bluetooth: Enable...
651
  	if (!disable_ertm)
cf6c2c0b9   Gustavo F. Padovan   Bluetooth: Discon...
652
653
654
655
656
657
658
659
660
661
662
  		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
  
  	switch (mode) {
  	case L2CAP_MODE_ERTM:
  		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
  	case L2CAP_MODE_STREAMING:
  		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
  	default:
  		return 0x00;
  	}
  }
4519de9a0   Gustavo F. Padovan   Bluetooth: Create...
663
  static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
22121fc91   Gustavo F. Padovan   Bluetooth: Create...
664
  {
e92c8e70f   Gustavo F. Padovan   Bluetooth: Move E...
665
  	struct sock *sk;
22121fc91   Gustavo F. Padovan   Bluetooth: Create...
666
  	struct l2cap_disconn_req req;
c13ffa620   Gustavo F. Padovan   Bluetooth: Proper...
667
668
  	if (!conn)
  		return;
e92c8e70f   Gustavo F. Padovan   Bluetooth: Move E...
669
  	sk = chan->sk;
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
670
  	if (chan->mode == L2CAP_MODE_ERTM) {
1a09bcb97   Gustavo F. Padovan   Bluetooth: keep r...
671
672
673
  		__clear_retrans_timer(chan);
  		__clear_monitor_timer(chan);
  		__clear_ack_timer(chan);
c13ffa620   Gustavo F. Padovan   Bluetooth: Proper...
674
  	}
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
675
676
  	req.dcid = cpu_to_le16(chan->dcid);
  	req.scid = cpu_to_le16(chan->scid);
22121fc91   Gustavo F. Padovan   Bluetooth: Create...
677
678
  	l2cap_send_cmd(conn, l2cap_get_ident(conn),
  			L2CAP_DISCONN_REQ, sizeof(req), &req);
c13ffa620   Gustavo F. Padovan   Bluetooth: Proper...
679

89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
680
  	l2cap_state_change(chan, BT_DISCONN);
9b108fc0c   Gustavo F. Padovan   Bluetooth: Fix ER...
681
  	sk->sk_err = err;
22121fc91   Gustavo F. Padovan   Bluetooth: Create...
682
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
683
  /* ---- L2CAP connections ---- */
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
684
685
  static void l2cap_conn_start(struct l2cap_conn *conn)
  {
3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
686
  	struct l2cap_chan *chan;
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
687
688
  
  	BT_DBG("conn %p", conn);
3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
689
  	rcu_read_lock();
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
690

3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
691
  	list_for_each_entry_rcu(chan, &conn->chan_l, list) {
48454079c   Gustavo F. Padovan   Bluetooth: Create...
692
  		struct sock *sk = chan->sk;
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
693

4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
694
  		bh_lock_sock(sk);
715ec005c   Gustavo F. Padovan   Bluetooth: Add ch...
695
  		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
696
697
698
  			bh_unlock_sock(sk);
  			continue;
  		}
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
699
  		if (chan->state == BT_CONNECT) {
47731de78   Gustavo F. Padovan   Bluetooth: Keep c...
700
  			struct l2cap_conn_req req;
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
701

d45fc4232   Gustavo F. Padovan   Bluetooth: Rename...
702
  			if (!l2cap_chan_check_security(chan) ||
b44500351   Gustavo F. Padovan   Bluetooth: Move c...
703
  					!__l2cap_no_conn_pending(chan)) {
47731de78   Gustavo F. Padovan   Bluetooth: Keep c...
704
705
706
  				bh_unlock_sock(sk);
  				continue;
  			}
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
707

c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
708
709
710
  			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
  					&& test_bit(CONF_STATE2_DEVICE,
  					&chan->conf_state)) {
0f8527249   Gustavo F. Padovan   Bluetooth: Rename...
711
  				/* l2cap_chan_close() calls list_del(chan)
820ffdb3d   Gustavo F. Padovan   Bluetooth: Remove...
712
  				 * so release the lock */
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
713
  				l2cap_chan_close(chan, ECONNRESET);
47731de78   Gustavo F. Padovan   Bluetooth: Keep c...
714
715
  				bh_unlock_sock(sk);
  				continue;
b1235d796   Marcel Holtmann   [Bluetooth] Allow...
716
  			}
47731de78   Gustavo F. Padovan   Bluetooth: Keep c...
717

fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
718
719
  			req.scid = cpu_to_le16(chan->scid);
  			req.psm  = chan->psm;
47731de78   Gustavo F. Padovan   Bluetooth: Keep c...
720

fc7f8a7ed   Gustavo F. Padovan   Bluetooth: Move i...
721
  			chan->ident = l2cap_get_ident(conn);
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
722
  			set_bit(CONF_CONNECT_PEND, &chan->conf_state);
47731de78   Gustavo F. Padovan   Bluetooth: Keep c...
723

fc7f8a7ed   Gustavo F. Padovan   Bluetooth: Move i...
724
725
  			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
  							sizeof(req), &req);
47731de78   Gustavo F. Padovan   Bluetooth: Keep c...
726

89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
727
  		} else if (chan->state == BT_CONNECT2) {
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
728
  			struct l2cap_conn_rsp rsp;
e9aeb2ddd   Gustavo F. Padovan   Bluetooth: Send C...
729
  			char buf[128];
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
730
731
  			rsp.scid = cpu_to_le16(chan->dcid);
  			rsp.dcid = cpu_to_le16(chan->scid);
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
732

d45fc4232   Gustavo F. Padovan   Bluetooth: Rename...
733
  			if (l2cap_chan_check_security(chan)) {
f66dc81f4   Marcel Holtmann   Bluetooth: Add su...
734
735
736
737
  				if (bt_sk(sk)->defer_setup) {
  					struct sock *parent = bt_sk(sk)->parent;
  					rsp.result = cpu_to_le16(L2CAP_CR_PEND);
  					rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
05e9a2f67   Ilia Kolomisnky   Bluetooth: Fix cr...
738
739
  					if (parent)
  						parent->sk_data_ready(parent, 0);
f66dc81f4   Marcel Holtmann   Bluetooth: Add su...
740
741
  
  				} else {
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
742
  					l2cap_state_change(chan, BT_CONFIG);
f66dc81f4   Marcel Holtmann   Bluetooth: Add su...
743
744
745
  					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
  					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
  				}
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
746
747
748
749
  			} else {
  				rsp.result = cpu_to_le16(L2CAP_CR_PEND);
  				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
  			}
fc7f8a7ed   Gustavo F. Padovan   Bluetooth: Move i...
750
751
  			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
  							sizeof(rsp), &rsp);
e9aeb2ddd   Gustavo F. Padovan   Bluetooth: Send C...
752

c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
753
  			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
e9aeb2ddd   Gustavo F. Padovan   Bluetooth: Send C...
754
755
756
757
  					rsp.result != L2CAP_CR_SUCCESS) {
  				bh_unlock_sock(sk);
  				continue;
  			}
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
758
  			set_bit(CONF_REQ_SENT, &chan->conf_state);
e9aeb2ddd   Gustavo F. Padovan   Bluetooth: Send C...
759
  			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
73ffa904b   Gustavo F. Padovan   Bluetooth: Move c...
760
761
  						l2cap_build_conf_req(chan, buf), buf);
  			chan->num_conf_req++;
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
762
763
764
765
  		}
  
  		bh_unlock_sock(sk);
  	}
3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
766
  	rcu_read_unlock();
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
767
  }
b62f328b8   Ville Tervo   Bluetooth: Add se...
768
769
770
  /* Find socket with cid and source bdaddr.
   * Returns closest match, locked.
   */
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
771
  static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
b62f328b8   Ville Tervo   Bluetooth: Add se...
772
  {
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
773
  	struct l2cap_chan *c, *c1 = NULL;
b62f328b8   Ville Tervo   Bluetooth: Add se...
774

23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
775
  	read_lock(&chan_list_lock);
b62f328b8   Ville Tervo   Bluetooth: Add se...
776

23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
777
778
  	list_for_each_entry(c, &chan_list, global_l) {
  		struct sock *sk = c->sk;
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
779

89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
780
  		if (state && c->state != state)
b62f328b8   Ville Tervo   Bluetooth: Add se...
781
  			continue;
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
782
  		if (c->scid == cid) {
b62f328b8   Ville Tervo   Bluetooth: Add se...
783
  			/* Exact match. */
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
784
785
786
787
  			if (!bacmp(&bt_sk(sk)->src, src)) {
  				read_unlock(&chan_list_lock);
  				return c;
  			}
b62f328b8   Ville Tervo   Bluetooth: Add se...
788
789
790
  
  			/* Closest match */
  			if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
791
  				c1 = c;
b62f328b8   Ville Tervo   Bluetooth: Add se...
792
793
  		}
  	}
280f294f7   Gustavo F. Padovan   Bluetooth: Don't ...
794

23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
795
  	read_unlock(&chan_list_lock);
b62f328b8   Ville Tervo   Bluetooth: Add se...
796

23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
797
  	return c1;
b62f328b8   Ville Tervo   Bluetooth: Add se...
798
799
800
801
  }
  
  static void l2cap_le_conn_ready(struct l2cap_conn *conn)
  {
c916fbe45   Gustavo F. Padovan   Bluetooth: Remove...
802
  	struct sock *parent, *sk;
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
803
  	struct l2cap_chan *chan, *pchan;
b62f328b8   Ville Tervo   Bluetooth: Add se...
804
805
806
807
  
  	BT_DBG("");
  
  	/* Check if we have socket listening on cid */
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
808
  	pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
b62f328b8   Ville Tervo   Bluetooth: Add se...
809
  							conn->src);
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
810
  	if (!pchan)
b62f328b8   Ville Tervo   Bluetooth: Add se...
811
  		return;
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
812
  	parent = pchan->sk;
aa2ac881b   Gustavo F. Padovan   Bluetooth: Don't ...
813
  	lock_sock(parent);
62f3a2cfb   Gustavo F. Padovan   Bluetooth: Fix an...
814

b62f328b8   Ville Tervo   Bluetooth: Add se...
815
816
817
818
819
  	/* Check for backlog size */
  	if (sk_acceptq_is_full(parent)) {
  		BT_DBG("backlog full %d", parent->sk_ack_backlog);
  		goto clean;
  	}
80808e431   Gustavo F. Padovan   Bluetooth: Add l2...
820
821
  	chan = pchan->ops->new_connection(pchan->data);
  	if (!chan)
b62f328b8   Ville Tervo   Bluetooth: Add se...
822
  		goto clean;
80808e431   Gustavo F. Padovan   Bluetooth: Add l2...
823
  	sk = chan->sk;
5d41ce1dd   Gustavo F. Padovan   Bluetooth: Refact...
824

b62f328b8   Ville Tervo   Bluetooth: Add se...
825
  	hci_conn_hold(conn->hcon);
b62f328b8   Ville Tervo   Bluetooth: Add se...
826
827
  	bacpy(&bt_sk(sk)->src, conn->src);
  	bacpy(&bt_sk(sk)->dst, conn->dst);
d1010240f   Gustavo F. Padovan   Bluetooth: Move b...
828
  	bt_accept_enqueue(parent, sk);
3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
829
  	l2cap_chan_add(conn, chan);
48454079c   Gustavo F. Padovan   Bluetooth: Create...
830

c9b666753   Gustavo F. Padovan   Bluetooth: Make t...
831
  	__set_chan_timer(chan, sk->sk_sndtimeo);
b62f328b8   Ville Tervo   Bluetooth: Add se...
832

89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
833
  	l2cap_state_change(chan, BT_CONNECTED);
b62f328b8   Ville Tervo   Bluetooth: Add se...
834
  	parent->sk_data_ready(parent, 0);
b62f328b8   Ville Tervo   Bluetooth: Add se...
835
  clean:
aa2ac881b   Gustavo F. Padovan   Bluetooth: Don't ...
836
  	release_sock(parent);
b62f328b8   Ville Tervo   Bluetooth: Add se...
837
  }
f1cb9af55   Vinicius Costa Gomes   Bluetooth: Add su...
838
839
840
841
842
843
844
845
846
  static void l2cap_chan_ready(struct sock *sk)
  {
  	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
  	struct sock *parent = bt_sk(sk)->parent;
  
  	BT_DBG("sk %p, parent %p", sk, parent);
  
  	chan->conf_state = 0;
  	__clear_chan_timer(chan);
43f3dc415   Vinicius Costa Gomes   Bluetooth: Fix no...
847
  	l2cap_state_change(chan, BT_CONNECTED);
f1cb9af55   Vinicius Costa Gomes   Bluetooth: Add su...
848
849
850
851
852
  	sk->sk_state_change(sk);
  
  	if (parent)
  		parent->sk_data_ready(parent, 0);
  }
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
853
854
  static void l2cap_conn_ready(struct l2cap_conn *conn)
  {
48454079c   Gustavo F. Padovan   Bluetooth: Create...
855
  	struct l2cap_chan *chan;
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
856

79d554a69   Marcel Holtmann   [Bluetooth] Chang...
857
  	BT_DBG("conn %p", conn);
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
858

b62f328b8   Ville Tervo   Bluetooth: Add se...
859
860
  	if (!conn->hcon->out && conn->hcon->type == LE_LINK)
  		l2cap_le_conn_ready(conn);
160dc6ac1   Vinicius Costa Gomes   Bluetooth: Add su...
861
862
  	if (conn->hcon->out && conn->hcon->type == LE_LINK)
  		smp_conn_security(conn, conn->hcon->pending_sec_level);
3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
863
  	rcu_read_lock();
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
864

3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
865
  	list_for_each_entry_rcu(chan, &conn->chan_l, list) {
48454079c   Gustavo F. Padovan   Bluetooth: Create...
866
  		struct sock *sk = chan->sk;
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
867

79d554a69   Marcel Holtmann   [Bluetooth] Chang...
868
  		bh_lock_sock(sk);
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
869

631284516   Vinicius Costa Gomes   Bluetooth: Fix cr...
870
  		if (conn->hcon->type == LE_LINK) {
b501d6a1d   Anderson Briglia   Bluetooth: Start ...
871
  			if (smp_conn_security(conn, chan->sec_level))
f1cb9af55   Vinicius Costa Gomes   Bluetooth: Add su...
872
  				l2cap_chan_ready(sk);
acd7d3708   Ville Tervo   Bluetooth: Add LE...
873

631284516   Vinicius Costa Gomes   Bluetooth: Fix cr...
874
  		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
c9b666753   Gustavo F. Padovan   Bluetooth: Make t...
875
  			__clear_chan_timer(chan);
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
876
  			l2cap_state_change(chan, BT_CONNECTED);
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
877
  			sk->sk_state_change(sk);
b501d6a1d   Anderson Briglia   Bluetooth: Start ...
878

89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
879
  		} else if (chan->state == BT_CONNECT)
fc7f8a7ed   Gustavo F. Padovan   Bluetooth: Move i...
880
  			l2cap_do_start(chan);
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
881

79d554a69   Marcel Holtmann   [Bluetooth] Chang...
882
  		bh_unlock_sock(sk);
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
883
  	}
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
884

3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
885
  	rcu_read_unlock();
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
886
887
888
889
890
  }
  
  /* Notify sockets that we cannot guaranty reliability anymore */
  static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
  {
48454079c   Gustavo F. Padovan   Bluetooth: Create...
891
  	struct l2cap_chan *chan;
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
892
893
  
  	BT_DBG("conn %p", conn);
3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
894
  	rcu_read_lock();
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
895

3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
896
  	list_for_each_entry_rcu(chan, &conn->chan_l, list) {
48454079c   Gustavo F. Padovan   Bluetooth: Create...
897
  		struct sock *sk = chan->sk;
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
898

ecf61bdba   Andrei Emeltchenko   Bluetooth: conver...
899
  		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
900
901
  			sk->sk_err = err;
  	}
3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
902
  	rcu_read_unlock();
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
903
  }
f878fcad1   Gustavo F. Padovan   Bluetooth: conver...
904
  static void l2cap_info_timeout(struct work_struct *work)
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
905
  {
f878fcad1   Gustavo F. Padovan   Bluetooth: conver...
906
  	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
030013d85   Gustavo F. Padovan   Bluetooth: Rename...
907
  							info_timer.work);
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
908

984947dc6   Marcel Holtmann   Bluetooth: Fix ra...
909
  	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
e1027a7c6   Marcel Holtmann   Bluetooth: Reques...
910
  	conn->info_ident = 0;
984947dc6   Marcel Holtmann   Bluetooth: Fix ra...
911

4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
912
913
  	l2cap_conn_start(conn);
  }
5d3de7df1   Vinicius Costa Gomes   Bluetooth: Add su...
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
  static void l2cap_conn_del(struct hci_conn *hcon, int err)
  {
  	struct l2cap_conn *conn = hcon->l2cap_data;
  	struct l2cap_chan *chan, *l;
  	struct sock *sk;
  
  	if (!conn)
  		return;
  
  	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
  
  	kfree_skb(conn->rx_skb);
  
  	/* Kill channels */
  	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
  		sk = chan->sk;
aa2ac881b   Gustavo F. Padovan   Bluetooth: Don't ...
930
  		lock_sock(sk);
5d3de7df1   Vinicius Costa Gomes   Bluetooth: Add su...
931
  		l2cap_chan_del(chan, err);
aa2ac881b   Gustavo F. Padovan   Bluetooth: Don't ...
932
  		release_sock(sk);
5d3de7df1   Vinicius Costa Gomes   Bluetooth: Add su...
933
934
  		chan->ops->close(chan->data);
  	}
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
935
  	hci_chan_del(conn->hchan);
5d3de7df1   Vinicius Costa Gomes   Bluetooth: Add su...
936
  	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
371fd8356   Ulisses Furquim   Bluetooth: Fix de...
937
  		__cancel_delayed_work(&conn->info_timer);
5d3de7df1   Vinicius Costa Gomes   Bluetooth: Add su...
938

d26a23454   Vinicius Costa Gomes   Bluetooth: Add a ...
939
  	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) {
371fd8356   Ulisses Furquim   Bluetooth: Fix de...
940
  		__cancel_delayed_work(&conn->security_timer);
8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
941
  		smp_chan_destroy(conn);
d26a23454   Vinicius Costa Gomes   Bluetooth: Add a ...
942
  	}
5d3de7df1   Vinicius Costa Gomes   Bluetooth: Add su...
943
944
945
946
  
  	hcon->l2cap_data = NULL;
  	kfree(conn);
  }
6c9d42a16   Gustavo F. Padovan   Bluetooth: conver...
947
  static void security_timeout(struct work_struct *work)
5d3de7df1   Vinicius Costa Gomes   Bluetooth: Add su...
948
  {
6c9d42a16   Gustavo F. Padovan   Bluetooth: conver...
949
950
  	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
  						security_timer.work);
5d3de7df1   Vinicius Costa Gomes   Bluetooth: Add su...
951
952
953
  
  	l2cap_conn_del(conn->hcon, ETIMEDOUT);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
954
955
  static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
  {
0139418c9   Marcel Holtmann   [Bluetooth] Small...
956
  	struct l2cap_conn *conn = hcon->l2cap_data;
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
957
  	struct hci_chan *hchan;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
958

0139418c9   Marcel Holtmann   [Bluetooth] Small...
959
  	if (conn || status)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
960
  		return conn;
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
961
962
963
  	hchan = hci_chan_create(hcon);
  	if (!hchan)
  		return NULL;
0139418c9   Marcel Holtmann   [Bluetooth] Small...
964
  	conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
965
966
  	if (!conn) {
  		hci_chan_del(hchan);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
967
  		return NULL;
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
968
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
969
970
971
  
  	hcon->l2cap_data = conn;
  	conn->hcon = hcon;
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
972
  	conn->hchan = hchan;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
973

73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
974
  	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
0139418c9   Marcel Holtmann   [Bluetooth] Small...
975

acd7d3708   Ville Tervo   Bluetooth: Add LE...
976
977
978
979
  	if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
  		conn->mtu = hcon->hdev->le_mtu;
  	else
  		conn->mtu = hcon->hdev->acl_mtu;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980
981
  	conn->src = &hcon->hdev->bdaddr;
  	conn->dst = &hcon->dst;
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
982
  	conn->feat_mask = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983
  	spin_lock_init(&conn->lock);
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
984
985
  
  	INIT_LIST_HEAD(&conn->chan_l);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
986

5d3de7df1   Vinicius Costa Gomes   Bluetooth: Add su...
987
  	if (hcon->type == LE_LINK)
6c9d42a16   Gustavo F. Padovan   Bluetooth: conver...
988
  		INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
5d3de7df1   Vinicius Costa Gomes   Bluetooth: Add su...
989
  	else
030013d85   Gustavo F. Padovan   Bluetooth: Rename...
990
  		INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
45054dc1b   Dave Young   bluetooth: static...
991

9f5a0d7bf   Andrei Emeltchenko   Bluetooth: Define...
992
  	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
2950f21ac   Marcel Holtmann   Bluetooth: Ask up...
993

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
994
995
  	return conn;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
996
  /* ---- Socket interface ---- */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
997
998
999
1000
  
  /* Find socket with psm and source bdaddr.
   * Returns closest match.
   */
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
1001
  static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1002
  {
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
1003
  	struct l2cap_chan *c, *c1 = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1004

23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
1005
  	read_lock(&chan_list_lock);
e0f0cb563   Gustavo F. Padovan   Bluetooth: Get ri...
1006

23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
1007
1008
  	list_for_each_entry(c, &chan_list, global_l) {
  		struct sock *sk = c->sk;
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
1009

89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
1010
  		if (state && c->state != state)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1011
  			continue;
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
1012
  		if (c->psm == psm) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1013
  			/* Exact match. */
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
1014
  			if (!bacmp(&bt_sk(sk)->src, src)) {
a7567b205   Johannes Berg   bluetooth l2cap: ...
1015
  				read_unlock(&chan_list_lock);
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
1016
1017
  				return c;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1018
1019
1020
  
  			/* Closest match */
  			if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
1021
  				c1 = c;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022
1023
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1024

23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
1025
  	read_unlock(&chan_list_lock);
e0f0cb563   Gustavo F. Padovan   Bluetooth: Get ri...
1026

23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
1027
  	return c1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1028
  }
03a001948   Gustavo F. Padovan   Bluetooth: invert...
1029
  inline int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1030
  {
5d41ce1dd   Gustavo F. Padovan   Bluetooth: Refact...
1031
  	struct sock *sk = chan->sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1032
  	bdaddr_t *src = &bt_sk(sk)->src;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1033
1034
1035
  	struct l2cap_conn *conn;
  	struct hci_conn *hcon;
  	struct hci_dev *hdev;
09ab6f4c2   Marcel Holtmann   [Bluetooth] Enfor...
1036
  	__u8 auth_type;
44d0e48e8   Marcel Holtmann   Bluetooth: Remove...
1037
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1038

f29972de8   Marcel Holtmann   Bluetooth: Add CI...
1039
  	BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
1040
  							chan->psm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1041

af05b30bc   Gustavo F. Padovan   Bluetooth: Fix er...
1042
1043
  	hdev = hci_get_route(dst, src);
  	if (!hdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1044
  		return -EHOSTUNREACH;
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1045
  	hci_dev_lock(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1046

03a001948   Gustavo F. Padovan   Bluetooth: invert...
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
  	lock_sock(sk);
  
  	/* PSM must be odd and lsb of upper byte must be 0 */
  	if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
  					chan->chan_type != L2CAP_CHAN_RAW) {
  		err = -EINVAL;
  		goto done;
  	}
  
  	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
  		err = -EINVAL;
  		goto done;
  	}
  
  	switch (chan->mode) {
  	case L2CAP_MODE_BASIC:
  		break;
  	case L2CAP_MODE_ERTM:
  	case L2CAP_MODE_STREAMING:
  		if (!disable_ertm)
  			break;
  		/* fall through */
  	default:
  		err = -ENOTSUPP;
  		goto done;
  	}
  
  	switch (sk->sk_state) {
  	case BT_CONNECT:
  	case BT_CONNECT2:
  	case BT_CONFIG:
  		/* Already connecting */
  		err = 0;
  		goto done;
  
  	case BT_CONNECTED:
  		/* Already connected */
  		err = -EISCONN;
  		goto done;
  
  	case BT_OPEN:
  	case BT_BOUND:
  		/* Can connect */
  		break;
  
  	default:
  		err = -EBADFD;
  		goto done;
  	}
  
  	/* Set destination address and psm */
9219b2a08   Gustavo F. Padovan   Bluetooth: Fix ba...
1098
  	bacpy(&bt_sk(sk)->dst, dst);
03a001948   Gustavo F. Padovan   Bluetooth: invert...
1099
1100
  	chan->psm = psm;
  	chan->dcid = cid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1101

4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
1102
  	auth_type = l2cap_get_auth_type(chan);
09ab6f4c2   Marcel Holtmann   [Bluetooth] Enfor...
1103

fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
1104
  	if (chan->dcid == L2CAP_CID_LE_DATA)
acd7d3708   Ville Tervo   Bluetooth: Add LE...
1105
  		hcon = hci_connect(hdev, LE_LINK, dst,
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
1106
  					chan->sec_level, auth_type);
acd7d3708   Ville Tervo   Bluetooth: Add LE...
1107
1108
  	else
  		hcon = hci_connect(hdev, ACL_LINK, dst,
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
1109
  					chan->sec_level, auth_type);
acd7d3708   Ville Tervo   Bluetooth: Add LE...
1110

30e762721   Ville Tervo   Bluetooth: Use ER...
1111
1112
  	if (IS_ERR(hcon)) {
  		err = PTR_ERR(hcon);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1113
  		goto done;
30e762721   Ville Tervo   Bluetooth: Use ER...
1114
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1115
1116
1117
1118
  
  	conn = l2cap_conn_add(hcon, 0);
  	if (!conn) {
  		hci_conn_put(hcon);
30e762721   Ville Tervo   Bluetooth: Use ER...
1119
  		err = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1120
1121
  		goto done;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1122
1123
  	/* Update source addr of the socket */
  	bacpy(src, conn->src);
48454079c   Gustavo F. Padovan   Bluetooth: Create...
1124
  	l2cap_chan_add(conn, chan);
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
1125
  	l2cap_state_change(chan, BT_CONNECT);
c9b666753   Gustavo F. Padovan   Bluetooth: Make t...
1126
  	__set_chan_timer(chan, sk->sk_sndtimeo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1127
1128
  
  	if (hcon->state == BT_CONNECTED) {
715ec005c   Gustavo F. Padovan   Bluetooth: Add ch...
1129
  		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
c9b666753   Gustavo F. Padovan   Bluetooth: Make t...
1130
  			__clear_chan_timer(chan);
d45fc4232   Gustavo F. Padovan   Bluetooth: Rename...
1131
  			if (l2cap_chan_check_security(chan))
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
1132
  				l2cap_state_change(chan, BT_CONNECTED);
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
1133
  		} else
fc7f8a7ed   Gustavo F. Padovan   Bluetooth: Move i...
1134
  			l2cap_do_start(chan);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1135
  	}
30e762721   Ville Tervo   Bluetooth: Use ER...
1136
  	err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1137
  done:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1138
  	hci_dev_unlock(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1139
1140
1141
  	hci_dev_put(hdev);
  	return err;
  }
dcba0dba5   Gustavo F. Padovan   Bluetooth: move l...
1142
  int __l2cap_wait_ack(struct sock *sk)
6161c0382   Gustavo F. Padovan   Bluetooth: Add wa...
1143
  {
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
1144
  	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
6161c0382   Gustavo F. Padovan   Bluetooth: Add wa...
1145
1146
1147
  	DECLARE_WAITQUEUE(wait, current);
  	int err = 0;
  	int timeo = HZ/5;
2b0b05ddc   Marcel Holtmann   Bluetooth: Fix is...
1148
  	add_wait_queue(sk_sleep(sk), &wait);
a71a0cf4e   Peter Hurley   Bluetooth: l2cap:...
1149
1150
  	set_current_state(TASK_INTERRUPTIBLE);
  	while (chan->unacked_frames > 0 && chan->conn) {
6161c0382   Gustavo F. Padovan   Bluetooth: Add wa...
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
  		if (!timeo)
  			timeo = HZ/5;
  
  		if (signal_pending(current)) {
  			err = sock_intr_errno(timeo);
  			break;
  		}
  
  		release_sock(sk);
  		timeo = schedule_timeout(timeo);
  		lock_sock(sk);
a71a0cf4e   Peter Hurley   Bluetooth: l2cap:...
1162
  		set_current_state(TASK_INTERRUPTIBLE);
6161c0382   Gustavo F. Padovan   Bluetooth: Add wa...
1163
1164
1165
1166
1167
1168
  
  		err = sock_error(sk);
  		if (err)
  			break;
  	}
  	set_current_state(TASK_RUNNING);
2b0b05ddc   Marcel Holtmann   Bluetooth: Fix is...
1169
  	remove_wait_queue(sk_sleep(sk), &wait);
6161c0382   Gustavo F. Padovan   Bluetooth: Add wa...
1170
1171
  	return err;
  }
721c41812   Gustavo F. Padovan   Bluetooth: Move L...
1172
  static void l2cap_monitor_timeout(struct work_struct *work)
e90bac061   Gustavo F. Padovan   Bluetooth: Add su...
1173
  {
721c41812   Gustavo F. Padovan   Bluetooth: Move L...
1174
1175
  	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
  							monitor_timer.work);
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
1176
  	struct sock *sk = chan->sk;
e90bac061   Gustavo F. Padovan   Bluetooth: Add su...
1177

525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
1178
  	BT_DBG("chan %p", chan);
0e98958d4   Gustavo F. Padovan   Bluetooth: Add de...
1179

721c41812   Gustavo F. Padovan   Bluetooth: Move L...
1180
  	lock_sock(sk);
2c03a7a49   Gustavo F. Padovan   Bluetooth: Move r...
1181
  	if (chan->retry_count >= chan->remote_max_tx) {
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
1182
  		l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
721c41812   Gustavo F. Padovan   Bluetooth: Move L...
1183
  		release_sock(sk);
e90bac061   Gustavo F. Padovan   Bluetooth: Add su...
1184
1185
  		return;
  	}
6a026610e   Gustavo F. Padovan   Bluetooth: Move m...
1186
  	chan->retry_count++;
1a09bcb97   Gustavo F. Padovan   Bluetooth: keep r...
1187
  	__set_monitor_timer(chan);
e90bac061   Gustavo F. Padovan   Bluetooth: Add su...
1188

525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
1189
  	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
721c41812   Gustavo F. Padovan   Bluetooth: Move L...
1190
  	release_sock(sk);
e90bac061   Gustavo F. Padovan   Bluetooth: Add su...
1191
  }
721c41812   Gustavo F. Padovan   Bluetooth: Move L...
1192
  static void l2cap_retrans_timeout(struct work_struct *work)
e90bac061   Gustavo F. Padovan   Bluetooth: Add su...
1193
  {
721c41812   Gustavo F. Padovan   Bluetooth: Move L...
1194
1195
  	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
  							retrans_timer.work);
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
1196
  	struct sock *sk = chan->sk;
e90bac061   Gustavo F. Padovan   Bluetooth: Add su...
1197

49208c9c7   Gustavo F. Padovan   Bluetooth: Remove...
1198
  	BT_DBG("chan %p", chan);
0e98958d4   Gustavo F. Padovan   Bluetooth: Add de...
1199

721c41812   Gustavo F. Padovan   Bluetooth: Move L...
1200
  	lock_sock(sk);
6a026610e   Gustavo F. Padovan   Bluetooth: Move m...
1201
  	chan->retry_count = 1;
1a09bcb97   Gustavo F. Padovan   Bluetooth: keep r...
1202
  	__set_monitor_timer(chan);
e90bac061   Gustavo F. Padovan   Bluetooth: Add su...
1203

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
1204
  	set_bit(CONN_WAIT_F, &chan->conn_state);
e90bac061   Gustavo F. Padovan   Bluetooth: Add su...
1205

525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
1206
  	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
721c41812   Gustavo F. Padovan   Bluetooth: Move L...
1207
  	release_sock(sk);
e90bac061   Gustavo F. Padovan   Bluetooth: Add su...
1208
  }
42e5c8027   Gustavo F. Padovan   Bluetooth: Move o...
1209
  static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1210
  {
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1211
  	struct sk_buff *skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1212

58d35f87e   Gustavo F. Padovan   Bluetooth: Move t...
1213
  	while ((skb = skb_peek(&chan->tx_q)) &&
6a026610e   Gustavo F. Padovan   Bluetooth: Move m...
1214
  			chan->unacked_frames) {
42e5c8027   Gustavo F. Padovan   Bluetooth: Move o...
1215
  		if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1216
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1217

58d35f87e   Gustavo F. Padovan   Bluetooth: Move t...
1218
  		skb = skb_dequeue(&chan->tx_q);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1219
  		kfree_skb(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1220

6a026610e   Gustavo F. Padovan   Bluetooth: Move m...
1221
  		chan->unacked_frames--;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1222
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1223

6a026610e   Gustavo F. Padovan   Bluetooth: Move m...
1224
  	if (!chan->unacked_frames)
1a09bcb97   Gustavo F. Padovan   Bluetooth: keep r...
1225
  		__clear_retrans_timer(chan);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1226
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1227

67c9e840a   Szymon Janc   Bluetooth: Mark n...
1228
  static void l2cap_streaming_send(struct l2cap_chan *chan)
6840ed077   Gustavo F. Padovan   Bluetooth: Enable...
1229
  {
ccbb84af2   Gustavo F. Padovan   Bluetooth: Simpli...
1230
  	struct sk_buff *skb;
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
1231
1232
  	u32 control;
  	u16 fcs;
6840ed077   Gustavo F. Padovan   Bluetooth: Enable...
1233

58d35f87e   Gustavo F. Padovan   Bluetooth: Move t...
1234
  	while ((skb = skb_dequeue(&chan->tx_q))) {
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
1235
  		control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
fb45de7db   Andrei Emeltchenko   Bluetooth: EWS: r...
1236
  		control |= __set_txseq(chan, chan->next_tx_seq);
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
1237
  		__put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
6840ed077   Gustavo F. Padovan   Bluetooth: Enable...
1238

47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
1239
  		if (chan->fcs == L2CAP_FCS_CRC16) {
03a512137   Andrei Emeltchenko   Bluetooth: EWS: r...
1240
1241
1242
1243
  			fcs = crc16(0, (u8 *)skb->data,
  						skb->len - L2CAP_FCS_SIZE);
  			put_unaligned_le16(fcs,
  					skb->data + skb->len - L2CAP_FCS_SIZE);
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
1244
  		}
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
1245
  		l2cap_do_send(chan, skb);
6840ed077   Gustavo F. Padovan   Bluetooth: Enable...
1246

836be9342   Andrei Emeltchenko   Bluetooth: EWS: s...
1247
  		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
6840ed077   Gustavo F. Padovan   Bluetooth: Enable...
1248
  	}
6840ed077   Gustavo F. Padovan   Bluetooth: Enable...
1249
  }
fb45de7db   Andrei Emeltchenko   Bluetooth: EWS: r...
1250
  static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
1251
  {
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
1252
  	struct sk_buff *skb, *tx_skb;
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
1253
1254
  	u16 fcs;
  	u32 control;
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
1255

58d35f87e   Gustavo F. Padovan   Bluetooth: Move t...
1256
  	skb = skb_peek(&chan->tx_q);
f11d676da   Gustavo F. Padovan   Bluetooth: Refact...
1257
1258
  	if (!skb)
  		return;
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
1259

d1726b6dc   Szymon Janc   Bluetooth: Refact...
1260
  	while (bt_cb(skb)->tx_seq != tx_seq) {
58d35f87e   Gustavo F. Padovan   Bluetooth: Move t...
1261
  		if (skb_queue_is_last(&chan->tx_q, skb))
f11d676da   Gustavo F. Padovan   Bluetooth: Refact...
1262
  			return;
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
1263

d1726b6dc   Szymon Janc   Bluetooth: Refact...
1264
1265
  		skb = skb_queue_next(&chan->tx_q, skb);
  	}
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
1266

2c03a7a49   Gustavo F. Padovan   Bluetooth: Move r...
1267
1268
  	if (chan->remote_max_tx &&
  			bt_cb(skb)->retries == chan->remote_max_tx) {
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
1269
  		l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
f11d676da   Gustavo F. Padovan   Bluetooth: Refact...
1270
1271
1272
1273
1274
  		return;
  	}
  
  	tx_skb = skb_clone(skb, GFP_ATOMIC);
  	bt_cb(skb)->retries++;
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
1275
1276
  
  	control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
7e0ef6ee1   Andrei Emeltchenko   Bluetooth: EWS: r...
1277
  	control &= __get_sar_mask(chan);
3cb123d1c   Gustavo F. Padovan   Bluetooth: Fix ha...
1278

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
1279
  	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
03f6715d4   Andrei Emeltchenko   Bluetooth: EWS: r...
1280
  		control |= __set_ctrl_final(chan);
95ffa9782   Gustavo F. Padovan   Bluetooth: Fix L2...
1281

0b209fae8   Andrei Emeltchenko   Bluetooth: EWS: r...
1282
  	control |= __set_reqseq(chan, chan->buffer_seq);
fb45de7db   Andrei Emeltchenko   Bluetooth: EWS: r...
1283
  	control |= __set_txseq(chan, tx_seq);
3cb123d1c   Gustavo F. Padovan   Bluetooth: Fix ha...
1284

88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
1285
  	__put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
f11d676da   Gustavo F. Padovan   Bluetooth: Refact...
1286

47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
1287
  	if (chan->fcs == L2CAP_FCS_CRC16) {
03a512137   Andrei Emeltchenko   Bluetooth: EWS: r...
1288
1289
1290
1291
  		fcs = crc16(0, (u8 *)tx_skb->data,
  						tx_skb->len - L2CAP_FCS_SIZE);
  		put_unaligned_le16(fcs,
  				tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
f11d676da   Gustavo F. Padovan   Bluetooth: Refact...
1292
  	}
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
1293
  	l2cap_do_send(chan, tx_skb);
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
1294
  }
67c9e840a   Szymon Janc   Bluetooth: Mark n...
1295
  static int l2cap_ertm_send(struct l2cap_chan *chan)
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1296
1297
  {
  	struct sk_buff *skb, *tx_skb;
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
1298
1299
  	u16 fcs;
  	u32 control;
9a9c6a344   Gustavo F. Padovan   Bluetooth: Make h...
1300
  	int nsent = 0;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1301

89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
1302
  	if (chan->state != BT_CONNECTED)
c13ffa620   Gustavo F. Padovan   Bluetooth: Proper...
1303
  		return -ENOTCONN;
e90bac061   Gustavo F. Padovan   Bluetooth: Add su...
1304

58d35f87e   Gustavo F. Padovan   Bluetooth: Move t...
1305
  	while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1306

2c03a7a49   Gustavo F. Padovan   Bluetooth: Move r...
1307
1308
  		if (chan->remote_max_tx &&
  				bt_cb(skb)->retries == chan->remote_max_tx) {
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
1309
  			l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
e90bac061   Gustavo F. Padovan   Bluetooth: Add su...
1310
1311
  			break;
  		}
e420aba33   Andrei Emeltchenko   Bluetooth: Fix me...
1312
  		tx_skb = skb_clone(skb, GFP_ATOMIC);
e90bac061   Gustavo F. Padovan   Bluetooth: Add su...
1313
  		bt_cb(skb)->retries++;
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
1314
  		control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
7e0ef6ee1   Andrei Emeltchenko   Bluetooth: EWS: r...
1315
  		control &= __get_sar_mask(chan);
95ffa9782   Gustavo F. Padovan   Bluetooth: Fix L2...
1316

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
1317
  		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
03f6715d4   Andrei Emeltchenko   Bluetooth: EWS: r...
1318
  			control |= __set_ctrl_final(chan);
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
1319

0b209fae8   Andrei Emeltchenko   Bluetooth: EWS: r...
1320
  		control |= __set_reqseq(chan, chan->buffer_seq);
fb45de7db   Andrei Emeltchenko   Bluetooth: EWS: r...
1321
  		control |= __set_txseq(chan, chan->next_tx_seq);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1322

88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
1323
  		__put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
e90bac061   Gustavo F. Padovan   Bluetooth: Add su...
1324

47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
1325
  		if (chan->fcs == L2CAP_FCS_CRC16) {
03a512137   Andrei Emeltchenko   Bluetooth: EWS: r...
1326
1327
1328
1329
  			fcs = crc16(0, (u8 *)skb->data,
  						tx_skb->len - L2CAP_FCS_SIZE);
  			put_unaligned_le16(fcs, skb->data +
  						tx_skb->len - L2CAP_FCS_SIZE);
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
1330
  		}
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
1331
  		l2cap_do_send(chan, tx_skb);
9a9c6a344   Gustavo F. Padovan   Bluetooth: Make h...
1332

1a09bcb97   Gustavo F. Padovan   Bluetooth: keep r...
1333
  		__set_retrans_timer(chan);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1334

42e5c8027   Gustavo F. Padovan   Bluetooth: Move o...
1335
  		bt_cb(skb)->tx_seq = chan->next_tx_seq;
836be9342   Andrei Emeltchenko   Bluetooth: EWS: s...
1336
1337
  
  		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1338

23e9fde2b   Suraj Sumangala   Bluetooth: Increm...
1339
  		if (bt_cb(skb)->retries == 1)
6a026610e   Gustavo F. Padovan   Bluetooth: Move m...
1340
  			chan->unacked_frames++;
23e9fde2b   Suraj Sumangala   Bluetooth: Increm...
1341

6a026610e   Gustavo F. Padovan   Bluetooth: Move m...
1342
  		chan->frames_sent++;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1343

58d35f87e   Gustavo F. Padovan   Bluetooth: Move t...
1344
1345
  		if (skb_queue_is_last(&chan->tx_q, skb))
  			chan->tx_send_head = NULL;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1346
  		else
58d35f87e   Gustavo F. Padovan   Bluetooth: Move t...
1347
  			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
9e917af13   Gustavo F. Padovan   Bluetooth: Implem...
1348
1349
  
  		nsent++;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1350
  	}
9e917af13   Gustavo F. Padovan   Bluetooth: Implem...
1351
1352
  	return nsent;
  }
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
1353
  static int l2cap_retransmit_frames(struct l2cap_chan *chan)
dfc909bef   Gustavo F. Padovan   Bluetooth: Fix ra...
1354
  {
dfc909bef   Gustavo F. Padovan   Bluetooth: Fix ra...
1355
  	int ret;
58d35f87e   Gustavo F. Padovan   Bluetooth: Move t...
1356
1357
  	if (!skb_queue_empty(&chan->tx_q))
  		chan->tx_send_head = chan->tx_q.next;
dfc909bef   Gustavo F. Padovan   Bluetooth: Fix ra...
1358

42e5c8027   Gustavo F. Padovan   Bluetooth: Move o...
1359
  	chan->next_tx_seq = chan->expected_ack_seq;
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
1360
  	ret = l2cap_ertm_send(chan);
dfc909bef   Gustavo F. Padovan   Bluetooth: Fix ra...
1361
1362
  	return ret;
  }
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
1363
  static void l2cap_send_ack(struct l2cap_chan *chan)
9e917af13   Gustavo F. Padovan   Bluetooth: Implem...
1364
  {
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
1365
  	u32 control = 0;
9e917af13   Gustavo F. Padovan   Bluetooth: Implem...
1366

0b209fae8   Andrei Emeltchenko   Bluetooth: EWS: r...
1367
  	control |= __set_reqseq(chan, chan->buffer_seq);
9e917af13   Gustavo F. Padovan   Bluetooth: Implem...
1368

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
1369
  	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
ab784b738   Andrei Emeltchenko   Bluetooth: EWS: r...
1370
  		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
1371
  		set_bit(CONN_RNR_SENT, &chan->conn_state);
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
1372
  		l2cap_send_sframe(chan, control);
9a9c6a344   Gustavo F. Padovan   Bluetooth: Make h...
1373
  		return;
9e917af13   Gustavo F. Padovan   Bluetooth: Implem...
1374
  	}
dfc909bef   Gustavo F. Padovan   Bluetooth: Fix ra...
1375

525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
1376
  	if (l2cap_ertm_send(chan) > 0)
dfc909bef   Gustavo F. Padovan   Bluetooth: Fix ra...
1377
  		return;
ab784b738   Andrei Emeltchenko   Bluetooth: EWS: r...
1378
  	control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
1379
  	l2cap_send_sframe(chan, control);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1380
  }
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
1381
  static void l2cap_send_srejtail(struct l2cap_chan *chan)
99b0d4b7b   Gustavo F. Padovan   Bluetooth: Handle...
1382
1383
  {
  	struct srej_list *tail;
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
1384
  	u32 control;
99b0d4b7b   Gustavo F. Padovan   Bluetooth: Handle...
1385

ab784b738   Andrei Emeltchenko   Bluetooth: EWS: r...
1386
  	control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
03f6715d4   Andrei Emeltchenko   Bluetooth: EWS: r...
1387
  	control |= __set_ctrl_final(chan);
99b0d4b7b   Gustavo F. Padovan   Bluetooth: Handle...
1388

39d5a3ee3   Gustavo F. Padovan   Bluetooth: Move S...
1389
  	tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
0b209fae8   Andrei Emeltchenko   Bluetooth: EWS: r...
1390
  	control |= __set_reqseq(chan, tail->tx_seq);
99b0d4b7b   Gustavo F. Padovan   Bluetooth: Handle...
1391

525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
1392
  	l2cap_send_sframe(chan, control);
99b0d4b7b   Gustavo F. Padovan   Bluetooth: Handle...
1393
  }
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1394
1395
  static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb)
  {
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
1396
  	struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1397
1398
  	struct sk_buff **frag;
  	int err, sent = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1399

59203a21a   Gustavo F. Padovan   Bluetooth: Fix er...
1400
  	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1401
  		return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
  
  	sent += count;
  	len  -= count;
  
  	/* Continuation fragments (no L2CAP header) */
  	frag = &skb_shinfo(skb)->frag_list;
  	while (len) {
  		count = min_t(unsigned int, conn->mtu, len);
  
  		*frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
  		if (!*frag)
0175d629e   Gustavo F. Padovan   Bluetooth: Use th...
1413
  			return err;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1414
1415
  		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
  			return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1416

5e59b791c   Luiz Augusto von Dentz   Bluetooth: set sk...
1417
  		(*frag)->priority = skb->priority;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1418
1419
1420
1421
1422
  		sent += count;
  		len  -= count;
  
  		frag = &(*frag)->next;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1423
1424
  
  	return sent;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1425
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1426

5e59b791c   Luiz Augusto von Dentz   Bluetooth: set sk...
1427
1428
1429
  static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
  						struct msghdr *msg, size_t len,
  						u32 priority)
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1430
  {
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
1431
  	struct sock *sk = chan->sk;
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
1432
  	struct l2cap_conn *conn = chan->conn;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1433
  	struct sk_buff *skb;
03a512137   Andrei Emeltchenko   Bluetooth: EWS: r...
1434
  	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1435
  	struct l2cap_hdr *lh;
5e59b791c   Luiz Augusto von Dentz   Bluetooth: set sk...
1436
  	BT_DBG("sk %p len %d priority %u", sk, (int)len, priority);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1437
1438
1439
1440
1441
  
  	count = min_t(unsigned int, (conn->mtu - hlen), len);
  	skb = bt_skb_send_alloc(sk, count + hlen,
  			msg->msg_flags & MSG_DONTWAIT, &err);
  	if (!skb)
0175d629e   Gustavo F. Padovan   Bluetooth: Use th...
1442
  		return ERR_PTR(err);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1443

5e59b791c   Luiz Augusto von Dentz   Bluetooth: set sk...
1444
  	skb->priority = priority;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1445
1446
  	/* Create L2CAP header */
  	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
1447
  	lh->cid = cpu_to_le16(chan->dcid);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1448
  	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
1449
  	put_unaligned_le16(chan->psm, skb_put(skb, 2));
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1450
1451
1452
1453
1454
1455
1456
1457
  
  	err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
  	if (unlikely(err < 0)) {
  		kfree_skb(skb);
  		return ERR_PTR(err);
  	}
  	return skb;
  }
5e59b791c   Luiz Augusto von Dentz   Bluetooth: set sk...
1458
1459
1460
  static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
  						struct msghdr *msg, size_t len,
  						u32 priority)
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1461
  {
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
1462
  	struct sock *sk = chan->sk;
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
1463
  	struct l2cap_conn *conn = chan->conn;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
  	struct sk_buff *skb;
  	int err, count, hlen = L2CAP_HDR_SIZE;
  	struct l2cap_hdr *lh;
  
  	BT_DBG("sk %p len %d", sk, (int)len);
  
  	count = min_t(unsigned int, (conn->mtu - hlen), len);
  	skb = bt_skb_send_alloc(sk, count + hlen,
  			msg->msg_flags & MSG_DONTWAIT, &err);
  	if (!skb)
0175d629e   Gustavo F. Padovan   Bluetooth: Use th...
1474
  		return ERR_PTR(err);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1475

5e59b791c   Luiz Augusto von Dentz   Bluetooth: set sk...
1476
  	skb->priority = priority;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1477
1478
  	/* Create L2CAP header */
  	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
1479
  	lh->cid = cpu_to_le16(chan->dcid);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1480
1481
1482
1483
1484
1485
1486
1487
1488
  	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
  
  	err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
  	if (unlikely(err < 0)) {
  		kfree_skb(skb);
  		return ERR_PTR(err);
  	}
  	return skb;
  }
ab0ff76d1   Luiz Augusto von Dentz   Bluetooth: mark l...
1489
1490
  static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
  						struct msghdr *msg, size_t len,
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
1491
  						u32 control, u16 sdulen)
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1492
  {
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
1493
  	struct sock *sk = chan->sk;
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
1494
  	struct l2cap_conn *conn = chan->conn;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1495
  	struct sk_buff *skb;
e4ca6d985   Andrei Emeltchenko   Bluetooth: EWS: r...
1496
  	int err, count, hlen;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1497
1498
1499
  	struct l2cap_hdr *lh;
  
  	BT_DBG("sk %p len %d", sk, (int)len);
0ee0d2085   Gustavo F. Padovan   Bluetooth: Fix cr...
1500
1501
  	if (!conn)
  		return ERR_PTR(-ENOTCONN);
e4ca6d985   Andrei Emeltchenko   Bluetooth: EWS: r...
1502
1503
1504
1505
  	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
  		hlen = L2CAP_EXT_HDR_SIZE;
  	else
  		hlen = L2CAP_ENH_HDR_SIZE;
c74e560cd   Gustavo F. Padovan   Bluetooth: Add su...
1506
  	if (sdulen)
03a512137   Andrei Emeltchenko   Bluetooth: EWS: r...
1507
  		hlen += L2CAP_SDULEN_SIZE;
c74e560cd   Gustavo F. Padovan   Bluetooth: Add su...
1508

47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
1509
  	if (chan->fcs == L2CAP_FCS_CRC16)
03a512137   Andrei Emeltchenko   Bluetooth: EWS: r...
1510
  		hlen += L2CAP_FCS_SIZE;
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
1511

1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1512
1513
1514
1515
  	count = min_t(unsigned int, (conn->mtu - hlen), len);
  	skb = bt_skb_send_alloc(sk, count + hlen,
  			msg->msg_flags & MSG_DONTWAIT, &err);
  	if (!skb)
0175d629e   Gustavo F. Padovan   Bluetooth: Use th...
1516
  		return ERR_PTR(err);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1517
1518
1519
  
  	/* Create L2CAP header */
  	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
1520
  	lh->cid = cpu_to_le16(chan->dcid);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1521
  	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
1522
1523
  
  	__put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
c74e560cd   Gustavo F. Padovan   Bluetooth: Add su...
1524
  	if (sdulen)
03a512137   Andrei Emeltchenko   Bluetooth: EWS: r...
1525
  		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1526
1527
1528
1529
1530
1531
  
  	err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
  	if (unlikely(err < 0)) {
  		kfree_skb(skb);
  		return ERR_PTR(err);
  	}
e90bac061   Gustavo F. Padovan   Bluetooth: Add su...
1532

47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
1533
  	if (chan->fcs == L2CAP_FCS_CRC16)
03a512137   Andrei Emeltchenko   Bluetooth: EWS: r...
1534
  		put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
1535

e90bac061   Gustavo F. Padovan   Bluetooth: Add su...
1536
  	bt_cb(skb)->retries = 0;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
1537
  	return skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1538
  }
67c9e840a   Szymon Janc   Bluetooth: Mark n...
1539
  static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
c74e560cd   Gustavo F. Padovan   Bluetooth: Add su...
1540
  {
c74e560cd   Gustavo F. Padovan   Bluetooth: Add su...
1541
1542
  	struct sk_buff *skb;
  	struct sk_buff_head sar_queue;
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
1543
  	u32 control;
c74e560cd   Gustavo F. Padovan   Bluetooth: Add su...
1544
  	size_t size = 0;
ff12fd643   Gustavo F. Padovan   Bluetooth: Fix lo...
1545
  	skb_queue_head_init(&sar_queue);
7e0ef6ee1   Andrei Emeltchenko   Bluetooth: EWS: r...
1546
  	control = __set_ctrl_sar(chan, L2CAP_SAR_START);
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
1547
  	skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
c74e560cd   Gustavo F. Padovan   Bluetooth: Add su...
1548
1549
1550
1551
  	if (IS_ERR(skb))
  		return PTR_ERR(skb);
  
  	__skb_queue_tail(&sar_queue, skb);
2c03a7a49   Gustavo F. Padovan   Bluetooth: Move r...
1552
1553
  	len -= chan->remote_mps;
  	size += chan->remote_mps;
c74e560cd   Gustavo F. Padovan   Bluetooth: Add su...
1554
1555
1556
  
  	while (len > 0) {
  		size_t buflen;
2c03a7a49   Gustavo F. Padovan   Bluetooth: Move r...
1557
  		if (len > chan->remote_mps) {
7e0ef6ee1   Andrei Emeltchenko   Bluetooth: EWS: r...
1558
  			control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
2c03a7a49   Gustavo F. Padovan   Bluetooth: Move r...
1559
  			buflen = chan->remote_mps;
c74e560cd   Gustavo F. Padovan   Bluetooth: Add su...
1560
  		} else {
7e0ef6ee1   Andrei Emeltchenko   Bluetooth: EWS: r...
1561
  			control = __set_ctrl_sar(chan, L2CAP_SAR_END);
c74e560cd   Gustavo F. Padovan   Bluetooth: Add su...
1562
1563
  			buflen = len;
  		}
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
1564
  		skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
c74e560cd   Gustavo F. Padovan   Bluetooth: Add su...
1565
1566
1567
1568
1569
1570
1571
1572
  		if (IS_ERR(skb)) {
  			skb_queue_purge(&sar_queue);
  			return PTR_ERR(skb);
  		}
  
  		__skb_queue_tail(&sar_queue, skb);
  		len -= buflen;
  		size += buflen;
c74e560cd   Gustavo F. Padovan   Bluetooth: Add su...
1573
  	}
58d35f87e   Gustavo F. Padovan   Bluetooth: Move t...
1574
1575
1576
  	skb_queue_splice_tail(&sar_queue, &chan->tx_q);
  	if (chan->tx_send_head == NULL)
  		chan->tx_send_head = sar_queue.next;
c74e560cd   Gustavo F. Padovan   Bluetooth: Add su...
1577
1578
1579
  
  	return size;
  }
5e59b791c   Luiz Augusto von Dentz   Bluetooth: set sk...
1580
1581
  int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
  								u32 priority)
9a91a04a9   Gustavo F. Padovan   Bluetooth: Create...
1582
  {
9a91a04a9   Gustavo F. Padovan   Bluetooth: Create...
1583
  	struct sk_buff *skb;
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
1584
  	u32 control;
9a91a04a9   Gustavo F. Padovan   Bluetooth: Create...
1585
1586
1587
  	int err;
  
  	/* Connectionless channel */
715ec005c   Gustavo F. Padovan   Bluetooth: Add ch...
1588
  	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
5e59b791c   Luiz Augusto von Dentz   Bluetooth: set sk...
1589
  		skb = l2cap_create_connless_pdu(chan, msg, len, priority);
9a91a04a9   Gustavo F. Padovan   Bluetooth: Create...
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
  		if (IS_ERR(skb))
  			return PTR_ERR(skb);
  
  		l2cap_do_send(chan, skb);
  		return len;
  	}
  
  	switch (chan->mode) {
  	case L2CAP_MODE_BASIC:
  		/* Check outgoing MTU */
  		if (len > chan->omtu)
  			return -EMSGSIZE;
  
  		/* Create a basic PDU */
5e59b791c   Luiz Augusto von Dentz   Bluetooth: set sk...
1604
  		skb = l2cap_create_basic_pdu(chan, msg, len, priority);
9a91a04a9   Gustavo F. Padovan   Bluetooth: Create...
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
  		if (IS_ERR(skb))
  			return PTR_ERR(skb);
  
  		l2cap_do_send(chan, skb);
  		err = len;
  		break;
  
  	case L2CAP_MODE_ERTM:
  	case L2CAP_MODE_STREAMING:
  		/* Entire SDU fits into one PDU */
  		if (len <= chan->remote_mps) {
7e0ef6ee1   Andrei Emeltchenko   Bluetooth: EWS: r...
1616
  			control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
9a91a04a9   Gustavo F. Padovan   Bluetooth: Create...
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
  			skb = l2cap_create_iframe_pdu(chan, msg, len, control,
  									0);
  			if (IS_ERR(skb))
  				return PTR_ERR(skb);
  
  			__skb_queue_tail(&chan->tx_q, skb);
  
  			if (chan->tx_send_head == NULL)
  				chan->tx_send_head = skb;
  
  		} else {
  			/* Segment SDU into multiples PDUs */
  			err = l2cap_sar_segment_sdu(chan, msg, len);
  			if (err < 0)
  				return err;
  		}
  
  		if (chan->mode == L2CAP_MODE_STREAMING) {
  			l2cap_streaming_send(chan);
  			err = len;
  			break;
  		}
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
1639
1640
  		if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
  				test_bit(CONN_WAIT_F, &chan->conn_state)) {
9a91a04a9   Gustavo F. Padovan   Bluetooth: Create...
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
  			err = len;
  			break;
  		}
  
  		err = l2cap_ertm_send(chan);
  		if (err >= 0)
  			err = len;
  
  		break;
  
  	default:
  		BT_DBG("bad state %1.1x", chan->mode);
  		err = -EBADFD;
  	}
  
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1658
1659
1660
  /* Copy frame to all raw sockets on that connection */
  static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1661
  	struct sk_buff *nskb;
48454079c   Gustavo F. Padovan   Bluetooth: Create...
1662
  	struct l2cap_chan *chan;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1663
1664
  
  	BT_DBG("conn %p", conn);
3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
1665
1666
1667
  	rcu_read_lock();
  
  	list_for_each_entry_rcu(chan, &conn->chan_l, list) {
48454079c   Gustavo F. Padovan   Bluetooth: Create...
1668
  		struct sock *sk = chan->sk;
715ec005c   Gustavo F. Padovan   Bluetooth: Add ch...
1669
  		if (chan->chan_type != L2CAP_CHAN_RAW)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1670
1671
1672
1673
1674
  			continue;
  
  		/* Don't send frame to the socket it came from */
  		if (skb->sk == sk)
  			continue;
af05b30bc   Gustavo F. Padovan   Bluetooth: Fix er...
1675
1676
  		nskb = skb_clone(skb, GFP_ATOMIC);
  		if (!nskb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1677
  			continue;
230704942   Gustavo F. Padovan   Bluetooth: add re...
1678
  		if (chan->ops->recv(chan->data, nskb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1679
1680
  			kfree_skb(nskb);
  	}
3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
1681
1682
  
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
  }
  
  /* ---- L2CAP signalling commands ---- */
  static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
  				u8 code, u8 ident, u16 dlen, void *data)
  {
  	struct sk_buff *skb, **frag;
  	struct l2cap_cmd_hdr *cmd;
  	struct l2cap_hdr *lh;
  	int len, count;
af05b30bc   Gustavo F. Padovan   Bluetooth: Fix er...
1693
1694
  	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
  			conn, code, ident, dlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1695
1696
1697
1698
1699
1700
1701
1702
1703
  
  	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
  	count = min_t(unsigned int, conn->mtu, len);
  
  	skb = bt_skb_alloc(count, GFP_ATOMIC);
  	if (!skb)
  		return NULL;
  
  	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
aca3192cc   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
1704
  	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
3300d9a93   Claudio Takahasi   Bluetooth: Add LE...
1705
1706
1707
1708
1709
  
  	if (conn->hcon->type == LE_LINK)
  		lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
  	else
  		lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1710
1711
1712
1713
  
  	cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
  	cmd->code  = code;
  	cmd->ident = ident;
aca3192cc   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
1714
  	cmd->len   = cpu_to_le16(dlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
  
  	if (dlen) {
  		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
  		memcpy(skb_put(skb, count), data, count);
  		data += count;
  	}
  
  	len -= skb->len;
  
  	/* Continuation fragments (no L2CAP header) */
  	frag = &skb_shinfo(skb)->frag_list;
  	while (len) {
  		count = min_t(unsigned int, conn->mtu, len);
  
  		*frag = bt_skb_alloc(count, GFP_ATOMIC);
  		if (!*frag)
  			goto fail;
  
  		memcpy(skb_put(*frag, count), data, count);
  
  		len  -= count;
  		data += count;
  
  		frag = &(*frag)->next;
  	}
  
  	return skb;
  
  fail:
  	kfree_skb(skb);
  	return NULL;
  }
  
  static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
  {
  	struct l2cap_conf_opt *opt = *ptr;
  	int len;
  
  	len = L2CAP_CONF_OPT_SIZE + opt->len;
  	*ptr += len;
  
  	*type = opt->type;
  	*olen = opt->len;
  
  	switch (opt->len) {
  	case 1:
  		*val = *((u8 *) opt->val);
  		break;
  
  	case 2:
bfaaeb3ed   steven miao   Bluetooth: fix un...
1765
  		*val = get_unaligned_le16(opt->val);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1766
1767
1768
  		break;
  
  	case 4:
bfaaeb3ed   steven miao   Bluetooth: fix un...
1769
  		*val = get_unaligned_le32(opt->val);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
  		break;
  
  	default:
  		*val = (unsigned long) opt->val;
  		break;
  	}
  
  	BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
  	return len;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
  static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
  {
  	struct l2cap_conf_opt *opt = *ptr;
  
  	BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
  
  	opt->type = type;
  	opt->len  = len;
  
  	switch (len) {
  	case 1:
  		*((u8 *) opt->val)  = val;
  		break;
  
  	case 2:
4f8b691c9   Gustavo F. Padovan   Bluetooth: fix en...
1795
  		put_unaligned_le16(val, opt->val);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1796
1797
1798
  		break;
  
  	case 4:
4f8b691c9   Gustavo F. Padovan   Bluetooth: fix en...
1799
  		put_unaligned_le32(val, opt->val);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1800
1801
1802
1803
1804
1805
1806
1807
1808
  		break;
  
  	default:
  		memcpy(opt->val, (void *) val, len);
  		break;
  	}
  
  	*ptr += L2CAP_CONF_OPT_SIZE + len;
  }
f89cef09c   Andrei Emeltchenko   Bluetooth: EFS: a...
1809
1810
1811
  static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
  {
  	struct l2cap_conf_efs efs;
1ec918cef   Szymon Janc   Bluetooth: Fix so...
1812
  	switch (chan->mode) {
f89cef09c   Andrei Emeltchenko   Bluetooth: EFS: a...
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
  	case L2CAP_MODE_ERTM:
  		efs.id		= chan->local_id;
  		efs.stype	= chan->local_stype;
  		efs.msdu	= cpu_to_le16(chan->local_msdu);
  		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
  		efs.acc_lat	= cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
  		efs.flush_to	= cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
  		break;
  
  	case L2CAP_MODE_STREAMING:
  		efs.id		= 1;
  		efs.stype	= L2CAP_SERV_BESTEFFORT;
  		efs.msdu	= cpu_to_le16(chan->local_msdu);
  		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
  		efs.acc_lat	= 0;
  		efs.flush_to	= 0;
  		break;
  
  	default:
  		return;
  	}
  
  	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
  							(unsigned long) &efs);
  }
721c41812   Gustavo F. Padovan   Bluetooth: Move L...
1838
  static void l2cap_ack_timeout(struct work_struct *work)
c1b4f43be   Gustavo F. Padovan   Bluetooth: Add ti...
1839
  {
721c41812   Gustavo F. Padovan   Bluetooth: Move L...
1840
1841
  	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
  							ack_timer.work);
c1b4f43be   Gustavo F. Padovan   Bluetooth: Add ti...
1842

2fb9b3d4e   Gustavo F. Padovan   Bluetooth: add de...
1843
  	BT_DBG("chan %p", chan);
721c41812   Gustavo F. Padovan   Bluetooth: Move L...
1844
  	lock_sock(chan->sk);
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
1845
  	l2cap_send_ack(chan);
721c41812   Gustavo F. Padovan   Bluetooth: Move L...
1846
  	release_sock(chan->sk);
c1b4f43be   Gustavo F. Padovan   Bluetooth: Add ti...
1847
  }
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
1848
  static inline void l2cap_ertm_init(struct l2cap_chan *chan)
0565c1c24   Gustavo F. Padovan   Bluetooth: Initia...
1849
  {
42e5c8027   Gustavo F. Padovan   Bluetooth: Move o...
1850
  	chan->expected_ack_seq = 0;
6a026610e   Gustavo F. Padovan   Bluetooth: Move m...
1851
  	chan->unacked_frames = 0;
42e5c8027   Gustavo F. Padovan   Bluetooth: Move o...
1852
  	chan->buffer_seq = 0;
6a026610e   Gustavo F. Padovan   Bluetooth: Move m...
1853
1854
  	chan->num_acked = 0;
  	chan->frames_sent = 0;
0565c1c24   Gustavo F. Padovan   Bluetooth: Initia...
1855

721c41812   Gustavo F. Padovan   Bluetooth: Move L...
1856
1857
1858
  	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
  	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
  	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
0565c1c24   Gustavo F. Padovan   Bluetooth: Initia...
1859

f1c6775be   Gustavo F. Padovan   Bluetooth: Move s...
1860
  	skb_queue_head_init(&chan->srej_q);
1890d36bb   Gustavo F. Padovan   Bluetooth: Implem...
1861

39d5a3ee3   Gustavo F. Padovan   Bluetooth: Move S...
1862
  	INIT_LIST_HEAD(&chan->srej_l);
0565c1c24   Gustavo F. Padovan   Bluetooth: Initia...
1863
  }
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
  static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
  {
  	switch (mode) {
  	case L2CAP_MODE_STREAMING:
  	case L2CAP_MODE_ERTM:
  		if (l2cap_mode_supported(mode, remote_feat_mask))
  			return mode;
  		/* fall through */
  	default:
  		return L2CAP_MODE_BASIC;
  	}
  }
6327eb980   Andrei Emeltchenko   Bluetooth: EWS: e...
1876
1877
1878
1879
  static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
  {
  	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
  }
f89cef09c   Andrei Emeltchenko   Bluetooth: EFS: a...
1880
1881
1882
1883
  static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
  {
  	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
  }
6327eb980   Andrei Emeltchenko   Bluetooth: EWS: e...
1884
1885
1886
  static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
  {
  	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
836be9342   Andrei Emeltchenko   Bluetooth: EWS: s...
1887
  						__l2cap_ews_supported(chan)) {
6327eb980   Andrei Emeltchenko   Bluetooth: EWS: e...
1888
1889
  		/* use extended control field */
  		set_bit(FLAG_EXT_CTRL, &chan->flags);
836be9342   Andrei Emeltchenko   Bluetooth: EWS: s...
1890
1891
  		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
  	} else {
6327eb980   Andrei Emeltchenko   Bluetooth: EWS: e...
1892
1893
  		chan->tx_win = min_t(u16, chan->tx_win,
  						L2CAP_DEFAULT_TX_WINDOW);
836be9342   Andrei Emeltchenko   Bluetooth: EWS: s...
1894
1895
  		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
  	}
6327eb980   Andrei Emeltchenko   Bluetooth: EWS: e...
1896
  }
710f9b0a4   Gustavo F. Padovan   Bluetooth: clean ...
1897
  static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1898
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1899
  	struct l2cap_conf_req *req = data;
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
1900
  	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1901
  	void *ptr = req->data;
c8f791626   Andrei Emeltchenko   Bluetooth: EWS: f...
1902
  	u16 size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1903

49208c9c7   Gustavo F. Padovan   Bluetooth: Remove...
1904
  	BT_DBG("chan %p", chan);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1905

73ffa904b   Gustavo F. Padovan   Bluetooth: Move c...
1906
  	if (chan->num_conf_req || chan->num_conf_rsp)
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
1907
  		goto done;
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
1908
  	switch (chan->mode) {
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
1909
1910
  	case L2CAP_MODE_STREAMING:
  	case L2CAP_MODE_ERTM:
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
1911
  		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
85eb53c6f   Gustavo F. Padovan   Bluetooth: Change...
1912
  			break;
85eb53c6f   Gustavo F. Padovan   Bluetooth: Change...
1913

f89cef09c   Andrei Emeltchenko   Bluetooth: EFS: a...
1914
1915
  		if (__l2cap_efs_supported(chan))
  			set_bit(FLAG_EFS_ENABLE, &chan->flags);
2ba13ed67   Gustavo F. Padovan   Bluetooth: Remove...
1916
  		/* fall through */
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
1917
  	default:
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
1918
  		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
1919
1920
1921
1922
  		break;
  	}
  
  done:
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
1923
1924
  	if (chan->imtu != L2CAP_DEFAULT_MTU)
  		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
7990681c4   Gustavo F. Padovan   Bluetooth: Fix se...
1925

0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
1926
  	switch (chan->mode) {
65c7c4918   Marcel Holtmann   Bluetooth: Add L2...
1927
  	case L2CAP_MODE_BASIC:
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
1928
1929
  		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
  				!(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
634065040   Gustavo F. Padovan   Bluetooth: Don't ...
1930
  			break;
625477523   Gustavo F. Padovan   Bluetooth: Active...
1931
1932
1933
1934
1935
1936
  		rfc.mode            = L2CAP_MODE_BASIC;
  		rfc.txwin_size      = 0;
  		rfc.max_transmit    = 0;
  		rfc.retrans_timeout = 0;
  		rfc.monitor_timeout = 0;
  		rfc.max_pdu_size    = 0;
634065040   Gustavo F. Padovan   Bluetooth: Don't ...
1937
1938
  		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
  							(unsigned long) &rfc);
65c7c4918   Marcel Holtmann   Bluetooth: Add L2...
1939
1940
1941
1942
  		break;
  
  	case L2CAP_MODE_ERTM:
  		rfc.mode            = L2CAP_MODE_ERTM;
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
1943
  		rfc.max_transmit    = chan->max_tx;
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
1944
1945
  		rfc.retrans_timeout = 0;
  		rfc.monitor_timeout = 0;
c8f791626   Andrei Emeltchenko   Bluetooth: EWS: f...
1946
1947
1948
1949
1950
1951
  
  		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
  						L2CAP_EXT_HDR_SIZE -
  						L2CAP_SDULEN_SIZE -
  						L2CAP_FCS_SIZE);
  		rfc.max_pdu_size = cpu_to_le16(size);
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
1952

6327eb980   Andrei Emeltchenko   Bluetooth: EWS: e...
1953
1954
1955
1956
  		l2cap_txwin_setup(chan);
  
  		rfc.txwin_size = min_t(u16, chan->tx_win,
  						L2CAP_DEFAULT_TX_WINDOW);
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
1957

634065040   Gustavo F. Padovan   Bluetooth: Don't ...
1958
1959
  		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
  							(unsigned long) &rfc);
f89cef09c   Andrei Emeltchenko   Bluetooth: EFS: a...
1960
1961
  		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
  			l2cap_add_opt_efs(&ptr, chan);
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
1962
  		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
1963
  			break;
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
1964
  		if (chan->fcs == L2CAP_FCS_NONE ||
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
1965
  				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
1966
1967
  			chan->fcs = L2CAP_FCS_NONE;
  			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
1968
  		}
6327eb980   Andrei Emeltchenko   Bluetooth: EWS: e...
1969
1970
1971
1972
  
  		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
  			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
  								chan->tx_win);
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
1973
1974
1975
1976
1977
1978
1979
1980
  		break;
  
  	case L2CAP_MODE_STREAMING:
  		rfc.mode            = L2CAP_MODE_STREAMING;
  		rfc.txwin_size      = 0;
  		rfc.max_transmit    = 0;
  		rfc.retrans_timeout = 0;
  		rfc.monitor_timeout = 0;
c8f791626   Andrei Emeltchenko   Bluetooth: EWS: f...
1981
1982
1983
1984
1985
1986
  
  		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
  						L2CAP_EXT_HDR_SIZE -
  						L2CAP_SDULEN_SIZE -
  						L2CAP_FCS_SIZE);
  		rfc.max_pdu_size = cpu_to_le16(size);
65c7c4918   Marcel Holtmann   Bluetooth: Add L2...
1987

634065040   Gustavo F. Padovan   Bluetooth: Don't ...
1988
1989
  		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
  							(unsigned long) &rfc);
f89cef09c   Andrei Emeltchenko   Bluetooth: EFS: a...
1990
1991
  		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
  			l2cap_add_opt_efs(&ptr, chan);
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
1992
  		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
1993
  			break;
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
1994
  		if (chan->fcs == L2CAP_FCS_NONE ||
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
1995
  				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
1996
1997
  			chan->fcs = L2CAP_FCS_NONE;
  			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
1998
  		}
65c7c4918   Marcel Holtmann   Bluetooth: Add L2...
1999
2000
  		break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2001

fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
2002
  	req->dcid  = cpu_to_le16(chan->dcid);
aca3192cc   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
2003
  	req->flags = cpu_to_le16(0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2004
2005
2006
  
  	return ptr - data;
  }
73ffa904b   Gustavo F. Padovan   Bluetooth: Move c...
2007
  static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2008
  {
5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2009
2010
  	struct l2cap_conf_rsp *rsp = data;
  	void *ptr = rsp->data;
73ffa904b   Gustavo F. Padovan   Bluetooth: Move c...
2011
2012
  	void *req = chan->conf_req;
  	int len = chan->conf_len;
5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2013
2014
  	int type, hint, olen;
  	unsigned long val;
6464f35f3   Marcel Holtmann   [Bluetooth] Fall ...
2015
  	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
42dceae28   Andrei Emeltchenko   Bluetooth: EFS: p...
2016
2017
  	struct l2cap_conf_efs efs;
  	u8 remote_efs = 0;
861d6882b   Marcel Holtmann   [Bluetooth] Remov...
2018
  	u16 mtu = L2CAP_DEFAULT_MTU;
5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2019
  	u16 result = L2CAP_CONF_SUCCESS;
c8f791626   Andrei Emeltchenko   Bluetooth: EWS: f...
2020
  	u16 size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2021

73ffa904b   Gustavo F. Padovan   Bluetooth: Move c...
2022
  	BT_DBG("chan %p", chan);
820ae1b86   Marcel Holtmann   [Bluetooth] Alway...
2023

5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2024
2025
  	while (len >= L2CAP_CONF_OPT_SIZE) {
  		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2026

589d27464   Gustavo F. Padovan   Bluetooth: Use ma...
2027
  		hint  = type & L2CAP_CONF_HINT;
47ec1dcd6   Marcel Holtmann   Bluetooth: Add ba...
2028
  		type &= L2CAP_CONF_MASK;
5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2029
2030
2031
  
  		switch (type) {
  		case L2CAP_CONF_MTU:
861d6882b   Marcel Holtmann   [Bluetooth] Remov...
2032
  			mtu = val;
5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2033
2034
2035
  			break;
  
  		case L2CAP_CONF_FLUSH_TO:
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
2036
  			chan->flush_to = val;
5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2037
2038
2039
2040
  			break;
  
  		case L2CAP_CONF_QOS:
  			break;
6464f35f3   Marcel Holtmann   [Bluetooth] Fall ...
2041
2042
2043
2044
  		case L2CAP_CONF_RFC:
  			if (olen == sizeof(rfc))
  				memcpy(&rfc, (void *) val, olen);
  			break;
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
2045
2046
  		case L2CAP_CONF_FCS:
  			if (val == L2CAP_FCS_NONE)
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
2047
  				set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
42dceae28   Andrei Emeltchenko   Bluetooth: EFS: p...
2048
  			break;
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
2049

42dceae28   Andrei Emeltchenko   Bluetooth: EFS: p...
2050
2051
2052
2053
  		case L2CAP_CONF_EFS:
  			remote_efs = 1;
  			if (olen == sizeof(efs))
  				memcpy(&efs, (void *) val, olen);
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
2054
  			break;
6327eb980   Andrei Emeltchenko   Bluetooth: EWS: e...
2055
2056
2057
  		case L2CAP_CONF_EWS:
  			if (!enable_hs)
  				return -ECONNREFUSED;
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
2058

6327eb980   Andrei Emeltchenko   Bluetooth: EWS: e...
2059
2060
  			set_bit(FLAG_EXT_CTRL, &chan->flags);
  			set_bit(CONF_EWS_RECV, &chan->conf_state);
836be9342   Andrei Emeltchenko   Bluetooth: EWS: s...
2061
  			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
6327eb980   Andrei Emeltchenko   Bluetooth: EWS: e...
2062
  			chan->remote_tx_win = val;
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
2063
  			break;
5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2064
2065
2066
2067
2068
2069
2070
2071
2072
  		default:
  			if (hint)
  				break;
  
  			result = L2CAP_CONF_UNKNOWN;
  			*((u8 *) ptr++) = type;
  			break;
  		}
  	}
73ffa904b   Gustavo F. Padovan   Bluetooth: Move c...
2073
  	if (chan->num_conf_rsp || chan->num_conf_req > 1)
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2074
  		goto done;
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
2075
  	switch (chan->mode) {
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2076
2077
  	case L2CAP_MODE_STREAMING:
  	case L2CAP_MODE_ERTM:
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
2078
  		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
2079
  			chan->mode = l2cap_select_mode(rfc.mode,
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
2080
  					chan->conn->feat_mask);
85eb53c6f   Gustavo F. Padovan   Bluetooth: Change...
2081
2082
  			break;
  		}
42dceae28   Andrei Emeltchenko   Bluetooth: EFS: p...
2083
2084
2085
2086
2087
2088
  		if (remote_efs) {
  			if (__l2cap_efs_supported(chan))
  				set_bit(FLAG_EFS_ENABLE, &chan->flags);
  			else
  				return -ECONNREFUSED;
  		}
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
2089
  		if (chan->mode != rfc.mode)
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2090
  			return -ECONNREFUSED;
742e519b0   Gustavo F. Padovan   Bluetooth: Discon...
2091

f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2092
  		break;
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2093
2094
2095
  	}
  
  done:
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
2096
  	if (chan->mode != rfc.mode) {
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2097
  		result = L2CAP_CONF_UNACCEPT;
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
2098
  		rfc.mode = chan->mode;
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2099

73ffa904b   Gustavo F. Padovan   Bluetooth: Move c...
2100
  		if (chan->num_conf_rsp == 1)
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2101
2102
2103
2104
2105
  			return -ECONNREFUSED;
  
  		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
  					sizeof(rfc), (unsigned long) &rfc);
  	}
5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2106
2107
2108
  	if (result == L2CAP_CONF_SUCCESS) {
  		/* Configure output options and let the other side know
  		 * which ones we don't like. */
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2109
2110
2111
  		if (mtu < L2CAP_DEFAULT_MIN_MTU)
  			result = L2CAP_CONF_UNACCEPT;
  		else {
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
2112
  			chan->omtu = mtu;
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
2113
  			set_bit(CONF_MTU_DONE, &chan->conf_state);
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2114
  		}
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
2115
  		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
6464f35f3   Marcel Holtmann   [Bluetooth] Fall ...
2116

42dceae28   Andrei Emeltchenko   Bluetooth: EFS: p...
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
  		if (remote_efs) {
  			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
  					efs.stype != L2CAP_SERV_NOTRAFIC &&
  					efs.stype != chan->local_stype) {
  
  				result = L2CAP_CONF_UNACCEPT;
  
  				if (chan->num_conf_req >= 1)
  					return -ECONNREFUSED;
  
  				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
3e6b3b95f   Gustavo F. Padovan   Bluetooth: small ...
2128
  							sizeof(efs),
42dceae28   Andrei Emeltchenko   Bluetooth: EFS: p...
2129
  							(unsigned long) &efs);
0e8b207e8   Andrei Emeltchenko   Bluetooth: EFS: i...
2130
  			} else {
3e6b3b95f   Gustavo F. Padovan   Bluetooth: small ...
2131
  				/* Send PENDING Conf Rsp */
0e8b207e8   Andrei Emeltchenko   Bluetooth: EFS: i...
2132
2133
  				result = L2CAP_CONF_PENDING;
  				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
42dceae28   Andrei Emeltchenko   Bluetooth: EFS: p...
2134
2135
  			}
  		}
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2136
2137
  		switch (rfc.mode) {
  		case L2CAP_MODE_BASIC:
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
2138
  			chan->fcs = L2CAP_FCS_NONE;
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
2139
  			set_bit(CONF_MODE_DONE, &chan->conf_state);
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2140
2141
2142
  			break;
  
  		case L2CAP_MODE_ERTM:
6327eb980   Andrei Emeltchenko   Bluetooth: EWS: e...
2143
2144
2145
2146
  			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
  				chan->remote_tx_win = rfc.txwin_size;
  			else
  				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
86b1b2632   Mat Martineau   Bluetooth: Fix en...
2147

2c03a7a49   Gustavo F. Padovan   Bluetooth: Move r...
2148
  			chan->remote_max_tx = rfc.max_transmit;
1c7621596   Gustavo F. Padovan   Bluetooth: Fix co...
2149

c8f791626   Andrei Emeltchenko   Bluetooth: EWS: f...
2150
2151
2152
2153
2154
2155
2156
  			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
  						chan->conn->mtu -
  						L2CAP_EXT_HDR_SIZE -
  						L2CAP_SDULEN_SIZE -
  						L2CAP_FCS_SIZE);
  			rfc.max_pdu_size = cpu_to_le16(size);
  			chan->remote_mps = size;
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2157

10467e9e9   Gustavo F. Padovan   Bluetooth: Add le...
2158
2159
2160
2161
  			rfc.retrans_timeout =
  				le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
  			rfc.monitor_timeout =
  				le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2162

c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
2163
  			set_bit(CONF_MODE_DONE, &chan->conf_state);
68ae6639b   Gustavo F. Padovan   Bluetooth: Fix re...
2164
2165
2166
  
  			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
  					sizeof(rfc), (unsigned long) &rfc);
42dceae28   Andrei Emeltchenko   Bluetooth: EFS: p...
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
  			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
  				chan->remote_id = efs.id;
  				chan->remote_stype = efs.stype;
  				chan->remote_msdu = le16_to_cpu(efs.msdu);
  				chan->remote_flush_to =
  						le32_to_cpu(efs.flush_to);
  				chan->remote_acc_lat =
  						le32_to_cpu(efs.acc_lat);
  				chan->remote_sdu_itime =
  					le32_to_cpu(efs.sdu_itime);
  				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
  					sizeof(efs), (unsigned long) &efs);
  			}
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2180
2181
2182
  			break;
  
  		case L2CAP_MODE_STREAMING:
c8f791626   Andrei Emeltchenko   Bluetooth: EWS: f...
2183
2184
2185
2186
2187
2188
2189
  			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
  						chan->conn->mtu -
  						L2CAP_EXT_HDR_SIZE -
  						L2CAP_SDULEN_SIZE -
  						L2CAP_FCS_SIZE);
  			rfc.max_pdu_size = cpu_to_le16(size);
  			chan->remote_mps = size;
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2190

c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
2191
  			set_bit(CONF_MODE_DONE, &chan->conf_state);
68ae6639b   Gustavo F. Padovan   Bluetooth: Fix re...
2192
2193
2194
  
  			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
  					sizeof(rfc), (unsigned long) &rfc);
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2195
2196
2197
  			break;
  
  		default:
5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2198
  			result = L2CAP_CONF_UNACCEPT;
5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2199

6464f35f3   Marcel Holtmann   [Bluetooth] Fall ...
2200
  			memset(&rfc, 0, sizeof(rfc));
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
2201
  			rfc.mode = chan->mode;
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2202
  		}
6464f35f3   Marcel Holtmann   [Bluetooth] Fall ...
2203

f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2204
  		if (result == L2CAP_CONF_SUCCESS)
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
2205
  			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2206
  	}
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
2207
  	rsp->scid   = cpu_to_le16(chan->dcid);
5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2208
2209
2210
2211
  	rsp->result = cpu_to_le16(result);
  	rsp->flags  = cpu_to_le16(0x0000);
  
  	return ptr - data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2212
  }
b44500351   Gustavo F. Padovan   Bluetooth: Move c...
2213
  static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2214
  {
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2215
2216
2217
2218
  	struct l2cap_conf_req *req = data;
  	void *ptr = req->data;
  	int type, olen;
  	unsigned long val;
36e999a83   Mat Martineau   Bluetooth: Preven...
2219
  	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
66af7aaf9   Andrei Emeltchenko   Bluetooth: EFS: p...
2220
  	struct l2cap_conf_efs efs;
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2221

fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
2222
  	BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2223
2224
2225
2226
2227
2228
2229
2230
  
  	while (len >= L2CAP_CONF_OPT_SIZE) {
  		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
  
  		switch (type) {
  		case L2CAP_CONF_MTU:
  			if (val < L2CAP_DEFAULT_MIN_MTU) {
  				*result = L2CAP_CONF_UNACCEPT;
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
2231
  				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2232
  			} else
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
2233
2234
  				chan->imtu = val;
  			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2235
2236
2237
  			break;
  
  		case L2CAP_CONF_FLUSH_TO:
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
2238
  			chan->flush_to = val;
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2239
  			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
2240
  							2, chan->flush_to);
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2241
2242
2243
2244
2245
  			break;
  
  		case L2CAP_CONF_RFC:
  			if (olen == sizeof(rfc))
  				memcpy(&rfc, (void *)val, olen);
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
2246
  			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
2247
  							rfc.mode != chan->mode)
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2248
  				return -ECONNREFUSED;
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
2249
  			chan->fcs = 0;
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2250
2251
2252
2253
  
  			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
  					sizeof(rfc), (unsigned long) &rfc);
  			break;
6327eb980   Andrei Emeltchenko   Bluetooth: EWS: e...
2254
2255
2256
2257
  
  		case L2CAP_CONF_EWS:
  			chan->tx_win = min_t(u16, val,
  						L2CAP_DEFAULT_EXT_WINDOW);
3e6b3b95f   Gustavo F. Padovan   Bluetooth: small ...
2258
2259
  			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
  							chan->tx_win);
6327eb980   Andrei Emeltchenko   Bluetooth: EWS: e...
2260
  			break;
66af7aaf9   Andrei Emeltchenko   Bluetooth: EFS: p...
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
  
  		case L2CAP_CONF_EFS:
  			if (olen == sizeof(efs))
  				memcpy(&efs, (void *)val, olen);
  
  			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
  					efs.stype != L2CAP_SERV_NOTRAFIC &&
  					efs.stype != chan->local_stype)
  				return -ECONNREFUSED;
  
  			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
  					sizeof(efs), (unsigned long) &efs);
  			break;
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2274
2275
  		}
  	}
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
2276
  	if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
6c2ea7a8f   Gustavo F. Padovan   Bluetooth: Refuse...
2277
  		return -ECONNREFUSED;
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
2278
  	chan->mode = rfc.mode;
6c2ea7a8f   Gustavo F. Padovan   Bluetooth: Refuse...
2279

0e8b207e8   Andrei Emeltchenko   Bluetooth: EFS: i...
2280
  	if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2281
2282
  		switch (rfc.mode) {
  		case L2CAP_MODE_ERTM:
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
2283
2284
2285
  			chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
  			chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
  			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
66af7aaf9   Andrei Emeltchenko   Bluetooth: EFS: p...
2286
2287
2288
2289
2290
2291
2292
2293
2294
  
  			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
  				chan->local_msdu = le16_to_cpu(efs.msdu);
  				chan->local_sdu_itime =
  						le32_to_cpu(efs.sdu_itime);
  				chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
  				chan->local_flush_to =
  						le32_to_cpu(efs.flush_to);
  			}
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2295
  			break;
66af7aaf9   Andrei Emeltchenko   Bluetooth: EFS: p...
2296

f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2297
  		case L2CAP_MODE_STREAMING:
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
2298
  			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2299
2300
  		}
  	}
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
2301
  	req->dcid   = cpu_to_le16(chan->dcid);
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2302
2303
2304
2305
  	req->flags  = cpu_to_le16(0x0000);
  
  	return ptr - data;
  }
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
2306
  static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2307
2308
2309
  {
  	struct l2cap_conf_rsp *rsp = data;
  	void *ptr = rsp->data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2310

fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
2311
  	BT_DBG("chan %p", chan);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2312

fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
2313
  	rsp->scid   = cpu_to_le16(chan->dcid);
5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2314
  	rsp->result = cpu_to_le16(result);
aca3192cc   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
2315
  	rsp->flags  = cpu_to_le16(flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2316
2317
2318
  
  	return ptr - data;
  }
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
2319
  void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
710f9b0a4   Gustavo F. Padovan   Bluetooth: clean ...
2320
2321
  {
  	struct l2cap_conn_rsp rsp;
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
2322
  	struct l2cap_conn *conn = chan->conn;
710f9b0a4   Gustavo F. Padovan   Bluetooth: clean ...
2323
  	u8 buf[128];
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
2324
2325
  	rsp.scid   = cpu_to_le16(chan->dcid);
  	rsp.dcid   = cpu_to_le16(chan->scid);
710f9b0a4   Gustavo F. Padovan   Bluetooth: clean ...
2326
2327
2328
2329
  	rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
  	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
  	l2cap_send_cmd(conn, chan->ident,
  				L2CAP_CONN_RSP, sizeof(rsp), &rsp);
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
2330
  	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
710f9b0a4   Gustavo F. Padovan   Bluetooth: clean ...
2331
  		return;
710f9b0a4   Gustavo F. Padovan   Bluetooth: clean ...
2332
2333
2334
2335
  	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
  			l2cap_build_conf_req(chan, buf), buf);
  	chan->num_conf_req++;
  }
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
2336
  static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
7b1c0049b   Gustavo F. Padovan   Bluetooth: Read R...
2337
  {
7b1c0049b   Gustavo F. Padovan   Bluetooth: Read R...
2338
2339
2340
  	int type, olen;
  	unsigned long val;
  	struct l2cap_conf_rfc rfc;
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
2341
  	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
7b1c0049b   Gustavo F. Padovan   Bluetooth: Read R...
2342

0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
2343
  	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
7b1c0049b   Gustavo F. Padovan   Bluetooth: Read R...
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
  		return;
  
  	while (len >= L2CAP_CONF_OPT_SIZE) {
  		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
  
  		switch (type) {
  		case L2CAP_CONF_RFC:
  			if (olen == sizeof(rfc))
  				memcpy(&rfc, (void *)val, olen);
  			goto done;
  		}
  	}
36e999a83   Mat Martineau   Bluetooth: Preven...
2356
2357
2358
2359
2360
2361
2362
2363
2364
  	/* Use sane default values in case a misbehaving remote device
  	 * did not send an RFC option.
  	 */
  	rfc.mode = chan->mode;
  	rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
  	rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
  	rfc.max_pdu_size = cpu_to_le16(chan->imtu);
  
  	BT_ERR("Expected RFC option was not found, using defaults");
7b1c0049b   Gustavo F. Padovan   Bluetooth: Read R...
2365
2366
2367
  done:
  	switch (rfc.mode) {
  	case L2CAP_MODE_ERTM:
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
2368
2369
2370
  		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
  		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
  		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
7b1c0049b   Gustavo F. Padovan   Bluetooth: Read R...
2371
2372
  		break;
  	case L2CAP_MODE_STREAMING:
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
2373
  		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
7b1c0049b   Gustavo F. Padovan   Bluetooth: Read R...
2374
2375
  	}
  }
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
2376
2377
  static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
  {
e2fd318e3   Ilia Kolomisnky   Bluetooth: Fixes ...
2378
  	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
2379

e2fd318e3   Ilia Kolomisnky   Bluetooth: Fixes ...
2380
  	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
2381
2382
2383
2384
  		return 0;
  
  	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
  					cmd->ident == conn->info_ident) {
371fd8356   Ulisses Furquim   Bluetooth: Fix de...
2385
  		__cancel_delayed_work(&conn->info_timer);
984947dc6   Marcel Holtmann   Bluetooth: Fix ra...
2386
2387
  
  		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
e1027a7c6   Marcel Holtmann   Bluetooth: Reques...
2388
  		conn->info_ident = 0;
984947dc6   Marcel Holtmann   Bluetooth: Fix ra...
2389

4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
2390
2391
2392
2393
2394
  		l2cap_conn_start(conn);
  	}
  
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2395
2396
  static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2397
2398
  	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
  	struct l2cap_conn_rsp rsp;
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
2399
  	struct l2cap_chan *chan = NULL, *pchan;
d793fe8ca   Nathan Holstein   Bluetooth: fix oo...
2400
  	struct sock *parent, *sk = NULL;
e7c29cb16   Marcel Holtmann   [Bluetooth] Rejec...
2401
  	int result, status = L2CAP_CS_NO_INFO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2402
2403
  
  	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
e7c29cb16   Marcel Holtmann   [Bluetooth] Rejec...
2404
  	__le16 psm = req->psm;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2405
2406
2407
2408
  
  	BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
  
  	/* Check if we have socket listening on psm */
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
2409
2410
  	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
  	if (!pchan) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2411
2412
2413
  		result = L2CAP_CR_BAD_PSM;
  		goto sendresp;
  	}
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
2414
  	parent = pchan->sk;
aa2ac881b   Gustavo F. Padovan   Bluetooth: Don't ...
2415
  	lock_sock(parent);
e0f0cb563   Gustavo F. Padovan   Bluetooth: Get ri...
2416

e7c29cb16   Marcel Holtmann   [Bluetooth] Rejec...
2417
2418
2419
  	/* Check if the ACL is secure enough (if not SDP) */
  	if (psm != cpu_to_le16(0x0001) &&
  				!hci_conn_check_link_mode(conn->hcon)) {
9f5a0d7bf   Andrei Emeltchenko   Bluetooth: Define...
2420
  		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
e7c29cb16   Marcel Holtmann   [Bluetooth] Rejec...
2421
2422
2423
  		result = L2CAP_CR_SEC_BLOCK;
  		goto response;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2424
2425
2426
2427
  	result = L2CAP_CR_NO_MEM;
  
  	/* Check for backlog size */
  	if (sk_acceptq_is_full(parent)) {
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
2428
  		BT_DBG("backlog full %d", parent->sk_ack_backlog);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2429
2430
  		goto response;
  	}
80808e431   Gustavo F. Padovan   Bluetooth: Add l2...
2431
2432
  	chan = pchan->ops->new_connection(pchan->data);
  	if (!chan)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2433
  		goto response;
80808e431   Gustavo F. Padovan   Bluetooth: Add l2...
2434
  	sk = chan->sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2435
  	/* Check if we already have channel with that dcid */
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
2436
  	if (__l2cap_get_chan_by_dcid(conn, scid)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2437
  		sock_set_flag(sk, SOCK_ZAPPED);
ba3bd0ee3   Gustavo F. Padovan   Bluetooth: add cl...
2438
  		chan->ops->close(chan->data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2439
2440
2441
2442
  		goto response;
  	}
  
  	hci_conn_hold(conn->hcon);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2443
2444
  	bacpy(&bt_sk(sk)->src, conn->src);
  	bacpy(&bt_sk(sk)->dst, conn->dst);
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
2445
2446
  	chan->psm  = psm;
  	chan->dcid = scid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2447

d1010240f   Gustavo F. Padovan   Bluetooth: Move b...
2448
  	bt_accept_enqueue(parent, sk);
3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
2449
  	l2cap_chan_add(conn, chan);
48454079c   Gustavo F. Padovan   Bluetooth: Create...
2450

fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
2451
  	dcid = chan->scid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2452

c9b666753   Gustavo F. Padovan   Bluetooth: Make t...
2453
  	__set_chan_timer(chan, sk->sk_sndtimeo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2454

fc7f8a7ed   Gustavo F. Padovan   Bluetooth: Move i...
2455
  	chan->ident = cmd->ident;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2456

984947dc6   Marcel Holtmann   Bluetooth: Fix ra...
2457
  	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
d45fc4232   Gustavo F. Padovan   Bluetooth: Rename...
2458
  		if (l2cap_chan_check_security(chan)) {
f66dc81f4   Marcel Holtmann   Bluetooth: Add su...
2459
  			if (bt_sk(sk)->defer_setup) {
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
2460
  				l2cap_state_change(chan, BT_CONNECT2);
f66dc81f4   Marcel Holtmann   Bluetooth: Add su...
2461
2462
2463
2464
  				result = L2CAP_CR_PEND;
  				status = L2CAP_CS_AUTHOR_PEND;
  				parent->sk_data_ready(parent, 0);
  			} else {
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
2465
  				l2cap_state_change(chan, BT_CONFIG);
f66dc81f4   Marcel Holtmann   Bluetooth: Add su...
2466
2467
2468
  				result = L2CAP_CR_SUCCESS;
  				status = L2CAP_CS_NO_INFO;
  			}
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
2469
  		} else {
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
2470
  			l2cap_state_change(chan, BT_CONNECT2);
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
2471
2472
2473
2474
  			result = L2CAP_CR_PEND;
  			status = L2CAP_CS_AUTHEN_PEND;
  		}
  	} else {
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
2475
  		l2cap_state_change(chan, BT_CONNECT2);
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
2476
2477
  		result = L2CAP_CR_PEND;
  		status = L2CAP_CS_NO_INFO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2478
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2479
  response:
aa2ac881b   Gustavo F. Padovan   Bluetooth: Don't ...
2480
  	release_sock(parent);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2481
2482
  
  sendresp:
aca3192cc   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
2483
2484
2485
2486
  	rsp.scid   = cpu_to_le16(scid);
  	rsp.dcid   = cpu_to_le16(dcid);
  	rsp.result = cpu_to_le16(result);
  	rsp.status = cpu_to_le16(status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2487
  	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
2488
2489
2490
2491
2492
2493
2494
  
  	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
  		struct l2cap_info_req info;
  		info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
  
  		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
  		conn->info_ident = l2cap_get_ident(conn);
030013d85   Gustavo F. Padovan   Bluetooth: Rename...
2495
  		schedule_delayed_work(&conn->info_timer,
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
2496
2497
2498
2499
2500
  					msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
  
  		l2cap_send_cmd(conn, conn->info_ident,
  					L2CAP_INFO_REQ, sizeof(info), &info);
  	}
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
2501
  	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
e9aeb2ddd   Gustavo F. Padovan   Bluetooth: Send C...
2502
2503
  				result == L2CAP_CR_SUCCESS) {
  		u8 buf[128];
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
2504
  		set_bit(CONF_REQ_SENT, &chan->conf_state);
e9aeb2ddd   Gustavo F. Padovan   Bluetooth: Send C...
2505
  		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
73ffa904b   Gustavo F. Padovan   Bluetooth: Move c...
2506
2507
  					l2cap_build_conf_req(chan, buf), buf);
  		chan->num_conf_req++;
e9aeb2ddd   Gustavo F. Padovan   Bluetooth: Send C...
2508
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2509
2510
2511
2512
2513
2514
2515
  	return 0;
  }
  
  static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
  {
  	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
  	u16 scid, dcid, result, status;
48454079c   Gustavo F. Padovan   Bluetooth: Create...
2516
  	struct l2cap_chan *chan;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
  	struct sock *sk;
  	u8 req[128];
  
  	scid   = __le16_to_cpu(rsp->scid);
  	dcid   = __le16_to_cpu(rsp->dcid);
  	result = __le16_to_cpu(rsp->result);
  	status = __le16_to_cpu(rsp->status);
  
  	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
  
  	if (scid) {
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
2528
  		chan = l2cap_get_chan_by_scid(conn, scid);
48454079c   Gustavo F. Padovan   Bluetooth: Create...
2529
  		if (!chan)
57d3b22bf   João Paulo Rechi Vita   Bluetooth: Fix er...
2530
  			return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2531
  	} else {
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
2532
  		chan = l2cap_get_chan_by_ident(conn, cmd->ident);
48454079c   Gustavo F. Padovan   Bluetooth: Create...
2533
  		if (!chan)
57d3b22bf   João Paulo Rechi Vita   Bluetooth: Fix er...
2534
  			return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2535
  	}
48454079c   Gustavo F. Padovan   Bluetooth: Create...
2536
  	sk = chan->sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2537
2538
  	switch (result) {
  	case L2CAP_CR_SUCCESS:
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
2539
  		l2cap_state_change(chan, BT_CONFIG);
fc7f8a7ed   Gustavo F. Padovan   Bluetooth: Move i...
2540
  		chan->ident = 0;
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
2541
  		chan->dcid = dcid;
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
2542
  		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
6a8d3010b   Marcel Holtmann   Bluetooth: Fix do...
2543

c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
2544
  		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
e9aeb2ddd   Gustavo F. Padovan   Bluetooth: Send C...
2545
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2546
  		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
73ffa904b   Gustavo F. Padovan   Bluetooth: Move c...
2547
2548
  					l2cap_build_conf_req(chan, req), req);
  		chan->num_conf_req++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2549
2550
2551
  		break;
  
  	case L2CAP_CR_PEND:
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
2552
  		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2553
2554
2555
  		break;
  
  	default:
48454079c   Gustavo F. Padovan   Bluetooth: Create...
2556
  		l2cap_chan_del(chan, ECONNREFUSED);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2557
2558
  		break;
  	}
aa2ac881b   Gustavo F. Padovan   Bluetooth: Don't ...
2559
  	release_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2560
2561
  	return 0;
  }
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
2562
  static inline void set_default_fcs(struct l2cap_chan *chan)
8c462b604   Mat Martineau   Bluetooth: Only e...
2563
2564
2565
2566
  {
  	/* FCS is enabled only in ERTM or streaming mode, if one or both
  	 * sides request it.
  	 */
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
2567
  	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
2568
  		chan->fcs = L2CAP_FCS_NONE;
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
2569
  	else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
2570
  		chan->fcs = L2CAP_FCS_CRC16;
8c462b604   Mat Martineau   Bluetooth: Only e...
2571
  }
88219a0f6   Al Viro   [BLUETOOTH]: pass...
2572
  static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2573
2574
2575
2576
  {
  	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
  	u16 dcid, flags;
  	u8 rsp[64];
48454079c   Gustavo F. Padovan   Bluetooth: Create...
2577
  	struct l2cap_chan *chan;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2578
  	struct sock *sk;
5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2579
  	int len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2580
2581
2582
2583
2584
  
  	dcid  = __le16_to_cpu(req->dcid);
  	flags = __le16_to_cpu(req->flags);
  
  	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
2585
  	chan = l2cap_get_chan_by_scid(conn, dcid);
48454079c   Gustavo F. Padovan   Bluetooth: Create...
2586
  	if (!chan)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2587
  		return -ENOENT;
48454079c   Gustavo F. Padovan   Bluetooth: Create...
2588
  	sk = chan->sk;
033b1142f   David S. Miller   Merge branch 'mas...
2589
  	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
e2fd318e3   Ilia Kolomisnky   Bluetooth: Fixes ...
2590
2591
2592
2593
2594
  		struct l2cap_cmd_rej_cid rej;
  
  		rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
  		rej.scid = cpu_to_le16(chan->scid);
  		rej.dcid = cpu_to_le16(chan->dcid);
df6bd743b   Gustavo F. Padovan   Bluetooth: Don't ...
2595

df6bd743b   Gustavo F. Padovan   Bluetooth: Don't ...
2596
2597
  		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
  				sizeof(rej), &rej);
354f60a99   Marcel Holtmann   [Bluetooth] Ignor...
2598
  		goto unlock;
df6bd743b   Gustavo F. Padovan   Bluetooth: Don't ...
2599
  	}
354f60a99   Marcel Holtmann   [Bluetooth] Ignor...
2600

5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2601
  	/* Reject if config buffer is too small. */
88219a0f6   Al Viro   [BLUETOOTH]: pass...
2602
  	len = cmd_len - sizeof(*req);
7ac288175   Dan Rosenberg   Bluetooth: Preven...
2603
  	if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2604
  		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
2605
  				l2cap_build_conf_rsp(chan, rsp,
5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2606
2607
2608
2609
2610
  					L2CAP_CONF_REJECT, flags), rsp);
  		goto unlock;
  	}
  
  	/* Store config. */
73ffa904b   Gustavo F. Padovan   Bluetooth: Move c...
2611
2612
  	memcpy(chan->conf_req + chan->conf_len, req->data, len);
  	chan->conf_len += len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2613
2614
2615
2616
  
  	if (flags & 0x0001) {
  		/* Incomplete config. Send empty response. */
  		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
2617
  				l2cap_build_conf_rsp(chan, rsp,
5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2618
  					L2CAP_CONF_SUCCESS, 0x0001), rsp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2619
2620
2621
2622
  		goto unlock;
  	}
  
  	/* Complete config. */
73ffa904b   Gustavo F. Padovan   Bluetooth: Move c...
2623
  	len = l2cap_parse_conf_req(chan, rsp);
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2624
  	if (len < 0) {
e92c8e70f   Gustavo F. Padovan   Bluetooth: Move E...
2625
  		l2cap_send_disconn_req(conn, chan, ECONNRESET);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2626
  		goto unlock;
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2627
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2628

5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2629
  	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
73ffa904b   Gustavo F. Padovan   Bluetooth: Move c...
2630
  	chan->num_conf_rsp++;
5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2631

5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2632
  	/* Reset config buffer. */
73ffa904b   Gustavo F. Padovan   Bluetooth: Move c...
2633
  	chan->conf_len = 0;
5dee9e7c4   Marcel Holtmann   [Bluetooth] Fix L...
2634

c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
2635
  	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
876d9484e   Marcel Holtmann   [Bluetooth] Finis...
2636
  		goto unlock;
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
2637
  	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
2638
  		set_default_fcs(chan);
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
2639

89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
2640
  		l2cap_state_change(chan, BT_CONNECTED);
e90bac061   Gustavo F. Padovan   Bluetooth: Add su...
2641

42e5c8027   Gustavo F. Padovan   Bluetooth: Move o...
2642
2643
  		chan->next_tx_seq = 0;
  		chan->expected_tx_seq = 0;
58d35f87e   Gustavo F. Padovan   Bluetooth: Move t...
2644
  		skb_queue_head_init(&chan->tx_q);
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
2645
  		if (chan->mode == L2CAP_MODE_ERTM)
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
2646
  			l2cap_ertm_init(chan);
0565c1c24   Gustavo F. Padovan   Bluetooth: Initia...
2647

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2648
  		l2cap_chan_ready(sk);
876d9484e   Marcel Holtmann   [Bluetooth] Finis...
2649
2650
  		goto unlock;
  	}
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
2651
  	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
79d554a69   Marcel Holtmann   [Bluetooth] Chang...
2652
  		u8 buf[64];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2653
  		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
73ffa904b   Gustavo F. Padovan   Bluetooth: Move c...
2654
2655
  					l2cap_build_conf_req(chan, buf), buf);
  		chan->num_conf_req++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2656
  	}
0e8b207e8   Andrei Emeltchenko   Bluetooth: EFS: i...
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
  	/* Got Conf Rsp PENDING from remote side and asume we sent
  	   Conf Rsp PENDING in the code above */
  	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
  			test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
  
  		/* check compatibility */
  
  		clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
  		set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
  
  		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3e6b3b95f   Gustavo F. Padovan   Bluetooth: small ...
2668
  					l2cap_build_conf_rsp(chan, rsp,
0e8b207e8   Andrei Emeltchenko   Bluetooth: EFS: i...
2669
2670
  					L2CAP_CONF_SUCCESS, 0x0000), rsp);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2671
  unlock:
aa2ac881b   Gustavo F. Padovan   Bluetooth: Don't ...
2672
  	release_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2673
2674
2675
2676
2677
2678
2679
  	return 0;
  }
  
  static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
  {
  	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
  	u16 scid, flags, result;
48454079c   Gustavo F. Padovan   Bluetooth: Create...
2680
  	struct l2cap_chan *chan;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2681
  	struct sock *sk;
7b1c0049b   Gustavo F. Padovan   Bluetooth: Read R...
2682
  	int len = cmd->len - sizeof(*rsp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2683
2684
2685
2686
  
  	scid   = __le16_to_cpu(rsp->scid);
  	flags  = __le16_to_cpu(rsp->flags);
  	result = __le16_to_cpu(rsp->result);
af05b30bc   Gustavo F. Padovan   Bluetooth: Fix er...
2687
2688
  	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
  			scid, flags, result);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2689

baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
2690
  	chan = l2cap_get_chan_by_scid(conn, scid);
48454079c   Gustavo F. Padovan   Bluetooth: Create...
2691
  	if (!chan)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2692
  		return 0;
48454079c   Gustavo F. Padovan   Bluetooth: Create...
2693
  	sk = chan->sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2694
2695
  	switch (result) {
  	case L2CAP_CONF_SUCCESS:
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
2696
  		l2cap_conf_rfc_get(chan, rsp->data, len);
0e8b207e8   Andrei Emeltchenko   Bluetooth: EFS: i...
2697
  		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2698
  		break;
0e8b207e8   Andrei Emeltchenko   Bluetooth: EFS: i...
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
  	case L2CAP_CONF_PENDING:
  		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
  
  		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
  			char buf[64];
  
  			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
  								buf, &result);
  			if (len < 0) {
  				l2cap_send_disconn_req(conn, chan, ECONNRESET);
  				goto done;
  			}
  
  			/* check compatibility */
  
  			clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
  			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
  
  			l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3e6b3b95f   Gustavo F. Padovan   Bluetooth: small ...
2718
  						l2cap_build_conf_rsp(chan, buf,
0e8b207e8   Andrei Emeltchenko   Bluetooth: EFS: i...
2719
2720
2721
  						L2CAP_CONF_SUCCESS, 0x0000), buf);
  		}
  		goto done;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2722
  	case L2CAP_CONF_UNACCEPT:
73ffa904b   Gustavo F. Padovan   Bluetooth: Move c...
2723
  		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2724
  			char req[64];
c2c77ec83   Andrei Emeltchenko   Bluetooth: Fix ke...
2725
  			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
e92c8e70f   Gustavo F. Padovan   Bluetooth: Move E...
2726
  				l2cap_send_disconn_req(conn, chan, ECONNRESET);
c2c77ec83   Andrei Emeltchenko   Bluetooth: Fix ke...
2727
2728
  				goto done;
  			}
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2729
2730
  			/* throw out any old stored conf requests */
  			result = L2CAP_CONF_SUCCESS;
b44500351   Gustavo F. Padovan   Bluetooth: Move c...
2731
2732
  			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
  								req, &result);
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2733
  			if (len < 0) {
e92c8e70f   Gustavo F. Padovan   Bluetooth: Move E...
2734
  				l2cap_send_disconn_req(conn, chan, ECONNRESET);
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2735
2736
2737
2738
2739
  				goto done;
  			}
  
  			l2cap_send_cmd(conn, l2cap_get_ident(conn),
  						L2CAP_CONF_REQ, len, req);
73ffa904b   Gustavo F. Padovan   Bluetooth: Move c...
2740
  			chan->num_conf_req++;
f2fcfcd67   Gustavo F. Padovan   Bluetooth: Add co...
2741
2742
2743
  			if (result != L2CAP_CONF_SUCCESS)
  				goto done;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2744
  		}
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
2745
  	default:
b1235d796   Marcel Holtmann   [Bluetooth] Allow...
2746
  		sk->sk_err = ECONNRESET;
f3f668b0e   Andrzej Kaczmarek   Bluetooth: Use mi...
2747
  		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
e92c8e70f   Gustavo F. Padovan   Bluetooth: Move E...
2748
  		l2cap_send_disconn_req(conn, chan, ECONNRESET);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2749
2750
2751
2752
2753
  		goto done;
  	}
  
  	if (flags & 0x01)
  		goto done;
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
2754
  	set_bit(CONF_INPUT_DONE, &chan->conf_state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2755

c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
2756
  	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
2757
  		set_default_fcs(chan);
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
2758

89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
2759
  		l2cap_state_change(chan, BT_CONNECTED);
42e5c8027   Gustavo F. Padovan   Bluetooth: Move o...
2760
2761
  		chan->next_tx_seq = 0;
  		chan->expected_tx_seq = 0;
58d35f87e   Gustavo F. Padovan   Bluetooth: Move t...
2762
  		skb_queue_head_init(&chan->tx_q);
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
2763
  		if (chan->mode ==  L2CAP_MODE_ERTM)
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
2764
  			l2cap_ertm_init(chan);
0565c1c24   Gustavo F. Padovan   Bluetooth: Initia...
2765

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2766
2767
2768
2769
  		l2cap_chan_ready(sk);
  	}
  
  done:
aa2ac881b   Gustavo F. Padovan   Bluetooth: Don't ...
2770
  	release_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2771
2772
2773
2774
2775
2776
2777
2778
  	return 0;
  }
  
  static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
  {
  	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
  	struct l2cap_disconn_rsp rsp;
  	u16 dcid, scid;
48454079c   Gustavo F. Padovan   Bluetooth: Create...
2779
  	struct l2cap_chan *chan;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2780
2781
2782
2783
2784
2785
  	struct sock *sk;
  
  	scid = __le16_to_cpu(req->scid);
  	dcid = __le16_to_cpu(req->dcid);
  
  	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
2786
  	chan = l2cap_get_chan_by_scid(conn, dcid);
48454079c   Gustavo F. Padovan   Bluetooth: Create...
2787
  	if (!chan)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2788
  		return 0;
48454079c   Gustavo F. Padovan   Bluetooth: Create...
2789
  	sk = chan->sk;
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
2790
2791
  	rsp.dcid = cpu_to_le16(chan->scid);
  	rsp.scid = cpu_to_le16(chan->dcid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2792
2793
2794
  	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
  
  	sk->sk_shutdown = SHUTDOWN_MASK;
48454079c   Gustavo F. Padovan   Bluetooth: Create...
2795
  	l2cap_chan_del(chan, ECONNRESET);
aa2ac881b   Gustavo F. Padovan   Bluetooth: Don't ...
2796
  	release_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2797

ba3bd0ee3   Gustavo F. Padovan   Bluetooth: add cl...
2798
  	chan->ops->close(chan->data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2799
2800
2801
2802
2803
2804
2805
  	return 0;
  }
  
  static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
  {
  	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
  	u16 dcid, scid;
48454079c   Gustavo F. Padovan   Bluetooth: Create...
2806
  	struct l2cap_chan *chan;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2807
2808
2809
2810
2811
2812
  	struct sock *sk;
  
  	scid = __le16_to_cpu(rsp->scid);
  	dcid = __le16_to_cpu(rsp->dcid);
  
  	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
2813
  	chan = l2cap_get_chan_by_scid(conn, scid);
48454079c   Gustavo F. Padovan   Bluetooth: Create...
2814
  	if (!chan)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2815
  		return 0;
48454079c   Gustavo F. Padovan   Bluetooth: Create...
2816
  	sk = chan->sk;
48454079c   Gustavo F. Padovan   Bluetooth: Create...
2817
  	l2cap_chan_del(chan, 0);
aa2ac881b   Gustavo F. Padovan   Bluetooth: Don't ...
2818
  	release_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2819

ba3bd0ee3   Gustavo F. Padovan   Bluetooth: add cl...
2820
  	chan->ops->close(chan->data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2821
2822
2823
2824
2825
2826
  	return 0;
  }
  
  static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
  {
  	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2827
2828
2829
2830
2831
  	u16 type;
  
  	type = __le16_to_cpu(req->type);
  
  	BT_DBG("type 0x%4.4x", type);
f0709e03a   Marcel Holtmann   [Bluetooth] Adver...
2832
2833
  	if (type == L2CAP_IT_FEAT_MASK) {
  		u8 buf[8];
44dd46de3   Marcel Holtmann   Bluetooth: Add mo...
2834
  		u32 feat_mask = l2cap_feat_mask;
f0709e03a   Marcel Holtmann   [Bluetooth] Adver...
2835
2836
2837
  		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
  		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK);
  		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
d1c4a17d5   Gustavo F. Padovan   Bluetooth: Enable...
2838
  		if (!disable_ertm)
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
2839
2840
  			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
  							 | L2CAP_FEAT_FCS;
a5fd6f300   Andrei Emeltchenko   Bluetooth: EFS: a...
2841
  		if (enable_hs)
6327eb980   Andrei Emeltchenko   Bluetooth: EWS: e...
2842
2843
  			feat_mask |= L2CAP_FEAT_EXT_FLOW
  						| L2CAP_FEAT_EXT_WINDOW;
a5fd6f300   Andrei Emeltchenko   Bluetooth: EFS: a...
2844

1b7bf4edc   Gustavo F. Padovan   Bluetooth: Use pr...
2845
  		put_unaligned_le32(feat_mask, rsp->data);
f0709e03a   Marcel Holtmann   [Bluetooth] Adver...
2846
2847
  		l2cap_send_cmd(conn, cmd->ident,
  					L2CAP_INFO_RSP, sizeof(buf), buf);
e1027a7c6   Marcel Holtmann   Bluetooth: Reques...
2848
2849
2850
  	} else if (type == L2CAP_IT_FIXED_CHAN) {
  		u8 buf[12];
  		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
50a147cd9   Mat Martineau   Bluetooth: Use sy...
2851
2852
2853
2854
2855
  
  		if (enable_hs)
  			l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
  		else
  			l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
e1027a7c6   Marcel Holtmann   Bluetooth: Reques...
2856
2857
  		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
  		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
c6337ea6e   Andrei Emeltchenko   Bluetooth: remove...
2858
  		memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
e1027a7c6   Marcel Holtmann   Bluetooth: Reques...
2859
2860
  		l2cap_send_cmd(conn, cmd->ident,
  					L2CAP_INFO_RSP, sizeof(buf), buf);
f0709e03a   Marcel Holtmann   [Bluetooth] Adver...
2861
2862
2863
2864
2865
2866
2867
  	} else {
  		struct l2cap_info_rsp rsp;
  		rsp.type   = cpu_to_le16(type);
  		rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
  		l2cap_send_cmd(conn, cmd->ident,
  					L2CAP_INFO_RSP, sizeof(rsp), &rsp);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
  
  	return 0;
  }
  
  static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
  {
  	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
  	u16 type, result;
  
  	type   = __le16_to_cpu(rsp->type);
  	result = __le16_to_cpu(rsp->result);
  
  	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
e90165be9   Andrei Emeltchenko   Bluetooth: check ...
2881
2882
2883
2884
  	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
  	if (cmd->ident != conn->info_ident ||
  			conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
  		return 0;
371fd8356   Ulisses Furquim   Bluetooth: Fix de...
2885
  	__cancel_delayed_work(&conn->info_timer);
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
2886

adb08edea   Ville Tervo   Bluetooth: Check ...
2887
2888
2889
2890
2891
2892
2893
2894
  	if (result != L2CAP_IR_SUCCESS) {
  		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
  		conn->info_ident = 0;
  
  		l2cap_conn_start(conn);
  
  		return 0;
  	}
984947dc6   Marcel Holtmann   Bluetooth: Fix ra...
2895
  	if (type == L2CAP_IT_FEAT_MASK) {
839853193   Harvey Harrison   bluetooth: use ge...
2896
  		conn->feat_mask = get_unaligned_le32(rsp->data);
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
2897

47ec1dcd6   Marcel Holtmann   Bluetooth: Add ba...
2898
  		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
e1027a7c6   Marcel Holtmann   Bluetooth: Reques...
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
  			struct l2cap_info_req req;
  			req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
  
  			conn->info_ident = l2cap_get_ident(conn);
  
  			l2cap_send_cmd(conn, conn->info_ident,
  					L2CAP_INFO_REQ, sizeof(req), &req);
  		} else {
  			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
  			conn->info_ident = 0;
  
  			l2cap_conn_start(conn);
  		}
  	} else if (type == L2CAP_IT_FIXED_CHAN) {
984947dc6   Marcel Holtmann   Bluetooth: Fix ra...
2913
  		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
e1027a7c6   Marcel Holtmann   Bluetooth: Reques...
2914
  		conn->info_ident = 0;
984947dc6   Marcel Holtmann   Bluetooth: Fix ra...
2915
2916
2917
  
  		l2cap_conn_start(conn);
  	}
4e8402a3f   Marcel Holtmann   [Bluetooth] Retri...
2918

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2919
2920
  	return 0;
  }
f94ff6fff   Mat Martineau   Bluetooth: Add si...
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
  static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
  					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
  					void *data)
  {
  	struct l2cap_create_chan_req *req = data;
  	struct l2cap_create_chan_rsp rsp;
  	u16 psm, scid;
  
  	if (cmd_len != sizeof(*req))
  		return -EPROTO;
  
  	if (!enable_hs)
  		return -EINVAL;
  
  	psm = le16_to_cpu(req->psm);
  	scid = le16_to_cpu(req->scid);
  
  	BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
  
  	/* Placeholder: Always reject */
  	rsp.dcid = 0;
  	rsp.scid = cpu_to_le16(scid);
  	rsp.result = L2CAP_CR_NO_MEM;
  	rsp.status = L2CAP_CS_NO_INFO;
  
  	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
  		       sizeof(rsp), &rsp);
  
  	return 0;
  }
  
  static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
  					struct l2cap_cmd_hdr *cmd, void *data)
  {
  	BT_DBG("conn %p", conn);
  
  	return l2cap_connect_rsp(conn, cmd, data);
  }
8d5a04a13   Mat Martineau   Bluetooth: Add si...
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
  static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
  							u16 icid, u16 result)
  {
  	struct l2cap_move_chan_rsp rsp;
  
  	BT_DBG("icid %d, result %d", icid, result);
  
  	rsp.icid = cpu_to_le16(icid);
  	rsp.result = cpu_to_le16(result);
  
  	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
  }
  
  static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
  				struct l2cap_chan *chan, u16 icid, u16 result)
  {
  	struct l2cap_move_chan_cfm cfm;
  	u8 ident;
  
  	BT_DBG("icid %d, result %d", icid, result);
  
  	ident = l2cap_get_ident(conn);
  	if (chan)
  		chan->ident = ident;
  
  	cfm.icid = cpu_to_le16(icid);
  	cfm.result = cpu_to_le16(result);
  
  	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
  }
  
  static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
  								u16 icid)
  {
  	struct l2cap_move_chan_cfm_rsp rsp;
  
  	BT_DBG("icid %d", icid);
  
  	rsp.icid = cpu_to_le16(icid);
  	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
  }
  
  static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
  			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
  {
  	struct l2cap_move_chan_req *req = data;
  	u16 icid = 0;
  	u16 result = L2CAP_MR_NOT_ALLOWED;
  
  	if (cmd_len != sizeof(*req))
  		return -EPROTO;
  
  	icid = le16_to_cpu(req->icid);
  
  	BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
  
  	if (!enable_hs)
  		return -EINVAL;
  
  	/* Placeholder: Always refuse */
  	l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
  
  	return 0;
  }
  
  static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
  			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
  {
  	struct l2cap_move_chan_rsp *rsp = data;
  	u16 icid, result;
  
  	if (cmd_len != sizeof(*rsp))
  		return -EPROTO;
  
  	icid = le16_to_cpu(rsp->icid);
  	result = le16_to_cpu(rsp->result);
  
  	BT_DBG("icid %d, result %d", icid, result);
  
  	/* Placeholder: Always unconfirmed */
  	l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
  
  	return 0;
  }
  
  static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
  			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
  {
  	struct l2cap_move_chan_cfm *cfm = data;
  	u16 icid, result;
  
  	if (cmd_len != sizeof(*cfm))
  		return -EPROTO;
  
  	icid = le16_to_cpu(cfm->icid);
  	result = le16_to_cpu(cfm->result);
  
  	BT_DBG("icid %d, result %d", icid, result);
  
  	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
  
  	return 0;
  }
  
  static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
  			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
  {
  	struct l2cap_move_chan_cfm_rsp *rsp = data;
  	u16 icid;
  
  	if (cmd_len != sizeof(*rsp))
  		return -EPROTO;
  
  	icid = le16_to_cpu(rsp->icid);
  
  	BT_DBG("icid %d", icid);
  
  	return 0;
  }
e2174ca43   Gustavo F. Padovan   Bluetooth: fix er...
3078
  static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
de73115a7   Claudio Takahasi   Bluetooth: Add co...
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
  							u16 to_multiplier)
  {
  	u16 max_latency;
  
  	if (min > max || min < 6 || max > 3200)
  		return -EINVAL;
  
  	if (to_multiplier < 10 || to_multiplier > 3200)
  		return -EINVAL;
  
  	if (max >= to_multiplier * 8)
  		return -EINVAL;
  
  	max_latency = (to_multiplier * 8 / max) - 1;
  	if (latency > 499 || latency > max_latency)
  		return -EINVAL;
  
  	return 0;
  }
  
  static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
  					struct l2cap_cmd_hdr *cmd, u8 *data)
  {
  	struct hci_conn *hcon = conn->hcon;
  	struct l2cap_conn_param_update_req *req;
  	struct l2cap_conn_param_update_rsp rsp;
  	u16 min, max, latency, to_multiplier, cmd_len;
2ce603ebe   Claudio Takahasi   Bluetooth: Send L...
3106
  	int err;
de73115a7   Claudio Takahasi   Bluetooth: Add co...
3107
3108
3109
3110
3111
3112
3113
3114
3115
  
  	if (!(hcon->link_mode & HCI_LM_MASTER))
  		return -EINVAL;
  
  	cmd_len = __le16_to_cpu(cmd->len);
  	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
  		return -EPROTO;
  
  	req = (struct l2cap_conn_param_update_req *) data;
e2174ca43   Gustavo F. Padovan   Bluetooth: fix er...
3116
3117
  	min		= __le16_to_cpu(req->min);
  	max		= __le16_to_cpu(req->max);
de73115a7   Claudio Takahasi   Bluetooth: Add co...
3118
3119
3120
3121
3122
3123
3124
  	latency		= __le16_to_cpu(req->latency);
  	to_multiplier	= __le16_to_cpu(req->to_multiplier);
  
  	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
  						min, max, latency, to_multiplier);
  
  	memset(&rsp, 0, sizeof(rsp));
2ce603ebe   Claudio Takahasi   Bluetooth: Send L...
3125
3126
3127
  
  	err = l2cap_check_conn_param(min, max, latency, to_multiplier);
  	if (err)
de73115a7   Claudio Takahasi   Bluetooth: Add co...
3128
3129
3130
3131
3132
3133
  		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
  	else
  		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
  
  	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
  							sizeof(rsp), &rsp);
2ce603ebe   Claudio Takahasi   Bluetooth: Send L...
3134
3135
  	if (!err)
  		hci_le_conn_update(hcon, min, max, latency, to_multiplier);
de73115a7   Claudio Takahasi   Bluetooth: Add co...
3136
3137
  	return 0;
  }
3300d9a93   Claudio Takahasi   Bluetooth: Add LE...
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
  static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
  			struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
  {
  	int err = 0;
  
  	switch (cmd->code) {
  	case L2CAP_COMMAND_REJ:
  		l2cap_command_rej(conn, cmd, data);
  		break;
  
  	case L2CAP_CONN_REQ:
  		err = l2cap_connect_req(conn, cmd, data);
  		break;
  
  	case L2CAP_CONN_RSP:
  		err = l2cap_connect_rsp(conn, cmd, data);
  		break;
  
  	case L2CAP_CONF_REQ:
  		err = l2cap_config_req(conn, cmd, cmd_len, data);
  		break;
  
  	case L2CAP_CONF_RSP:
  		err = l2cap_config_rsp(conn, cmd, data);
  		break;
  
  	case L2CAP_DISCONN_REQ:
  		err = l2cap_disconnect_req(conn, cmd, data);
  		break;
  
  	case L2CAP_DISCONN_RSP:
  		err = l2cap_disconnect_rsp(conn, cmd, data);
  		break;
  
  	case L2CAP_ECHO_REQ:
  		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
  		break;
  
  	case L2CAP_ECHO_RSP:
  		break;
  
  	case L2CAP_INFO_REQ:
  		err = l2cap_information_req(conn, cmd, data);
  		break;
  
  	case L2CAP_INFO_RSP:
  		err = l2cap_information_rsp(conn, cmd, data);
  		break;
f94ff6fff   Mat Martineau   Bluetooth: Add si...
3186
3187
3188
3189
3190
3191
3192
  	case L2CAP_CREATE_CHAN_REQ:
  		err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
  		break;
  
  	case L2CAP_CREATE_CHAN_RSP:
  		err = l2cap_create_channel_rsp(conn, cmd, data);
  		break;
8d5a04a13   Mat Martineau   Bluetooth: Add si...
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
  	case L2CAP_MOVE_CHAN_REQ:
  		err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
  		break;
  
  	case L2CAP_MOVE_CHAN_RSP:
  		err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
  		break;
  
  	case L2CAP_MOVE_CHAN_CFM:
  		err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
  		break;
  
  	case L2CAP_MOVE_CHAN_CFM_RSP:
  		err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
  		break;
3300d9a93   Claudio Takahasi   Bluetooth: Add LE...
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
  	default:
  		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
  		err = -EINVAL;
  		break;
  	}
  
  	return err;
  }
  
  static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
  					struct l2cap_cmd_hdr *cmd, u8 *data)
  {
  	switch (cmd->code) {
  	case L2CAP_COMMAND_REJ:
  		return 0;
  
  	case L2CAP_CONN_PARAM_UPDATE_REQ:
de73115a7   Claudio Takahasi   Bluetooth: Add co...
3225
  		return l2cap_conn_param_update_req(conn, cmd, data);
3300d9a93   Claudio Takahasi   Bluetooth: Add LE...
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
  
  	case L2CAP_CONN_PARAM_UPDATE_RSP:
  		return 0;
  
  	default:
  		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
  		return -EINVAL;
  	}
  }
  
  static inline void l2cap_sig_channel(struct l2cap_conn *conn,
  							struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3238
3239
3240
3241
  {
  	u8 *data = skb->data;
  	int len = skb->len;
  	struct l2cap_cmd_hdr cmd;
3300d9a93   Claudio Takahasi   Bluetooth: Add LE...
3242
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3243
3244
3245
3246
  
  	l2cap_raw_recv(conn, skb);
  
  	while (len >= L2CAP_CMD_HDR_SIZE) {
88219a0f6   Al Viro   [BLUETOOTH]: pass...
3247
  		u16 cmd_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3248
3249
3250
  		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
  		data += L2CAP_CMD_HDR_SIZE;
  		len  -= L2CAP_CMD_HDR_SIZE;
88219a0f6   Al Viro   [BLUETOOTH]: pass...
3251
  		cmd_len = le16_to_cpu(cmd.len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3252

88219a0f6   Al Viro   [BLUETOOTH]: pass...
3253
  		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3254

88219a0f6   Al Viro   [BLUETOOTH]: pass...
3255
  		if (cmd_len > len || !cmd.ident) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3256
3257
3258
  			BT_DBG("corrupted command");
  			break;
  		}
3300d9a93   Claudio Takahasi   Bluetooth: Add LE...
3259
3260
3261
3262
  		if (conn->hcon->type == LE_LINK)
  			err = l2cap_le_sig_cmd(conn, &cmd, data);
  		else
  			err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3263
3264
  
  		if (err) {
e2fd318e3   Ilia Kolomisnky   Bluetooth: Fixes ...
3265
  			struct l2cap_cmd_rej_unk rej;
2c6d1a2ee   Gustavo F. Padovan   Bluetooth: Improv...
3266
3267
  
  			BT_ERR("Wrong link type (%d)", err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3268
3269
  
  			/* FIXME: Map err to a valid reason */
e2fd318e3   Ilia Kolomisnky   Bluetooth: Fixes ...
3270
  			rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3271
3272
  			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
  		}
88219a0f6   Al Viro   [BLUETOOTH]: pass...
3273
3274
  		data += cmd_len;
  		len  -= cmd_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3275
3276
3277
3278
  	}
  
  	kfree_skb(skb);
  }
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
3279
  static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
3280
3281
  {
  	u16 our_fcs, rcv_fcs;
e4ca6d985   Andrei Emeltchenko   Bluetooth: EWS: r...
3282
3283
3284
3285
3286
3287
  	int hdr_size;
  
  	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
  		hdr_size = L2CAP_EXT_HDR_SIZE;
  	else
  		hdr_size = L2CAP_ENH_HDR_SIZE;
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
3288

47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
3289
  	if (chan->fcs == L2CAP_FCS_CRC16) {
03a512137   Andrei Emeltchenko   Bluetooth: EWS: r...
3290
  		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
3291
3292
3293
3294
  		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
  		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
  
  		if (our_fcs != rcv_fcs)
7a560e5c9   João Paulo Rechi Vita   Bluetooth: Fix er...
3295
  			return -EBADMSG;
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
3296
3297
3298
  	}
  	return 0;
  }
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3299
  static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
d5392c8f1   Gustavo F. Padovan   Bluetooth: Implem...
3300
  {
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3301
  	u32 control = 0;
d5392c8f1   Gustavo F. Padovan   Bluetooth: Implem...
3302

6a026610e   Gustavo F. Padovan   Bluetooth: Move m...
3303
  	chan->frames_sent = 0;
d5392c8f1   Gustavo F. Padovan   Bluetooth: Implem...
3304

0b209fae8   Andrei Emeltchenko   Bluetooth: EWS: r...
3305
  	control |= __set_reqseq(chan, chan->buffer_seq);
d5392c8f1   Gustavo F. Padovan   Bluetooth: Implem...
3306

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3307
  	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
ab784b738   Andrei Emeltchenko   Bluetooth: EWS: r...
3308
  		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3309
  		l2cap_send_sframe(chan, control);
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3310
  		set_bit(CONN_RNR_SENT, &chan->conn_state);
d5392c8f1   Gustavo F. Padovan   Bluetooth: Implem...
3311
  	}
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3312
  	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3313
  		l2cap_retransmit_frames(chan);
d5392c8f1   Gustavo F. Padovan   Bluetooth: Implem...
3314

525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3315
  	l2cap_ertm_send(chan);
d5392c8f1   Gustavo F. Padovan   Bluetooth: Implem...
3316

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3317
  	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
6a026610e   Gustavo F. Padovan   Bluetooth: Move m...
3318
  			chan->frames_sent == 0) {
ab784b738   Andrei Emeltchenko   Bluetooth: EWS: r...
3319
  		control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3320
  		l2cap_send_sframe(chan, control);
d5392c8f1   Gustavo F. Padovan   Bluetooth: Implem...
3321
3322
  	}
  }
fb45de7db   Andrei Emeltchenko   Bluetooth: EWS: r...
3323
  static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u16 tx_seq, u8 sar)
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3324
3325
  {
  	struct sk_buff *next_skb;
bfbacc115   João Paulo Rechi Vita   Bluetooth: Fix SR...
3326
  	int tx_seq_offset, next_tx_seq_offset;
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3327
3328
3329
  
  	bt_cb(skb)->tx_seq = tx_seq;
  	bt_cb(skb)->sar = sar;
f1c6775be   Gustavo F. Padovan   Bluetooth: Move s...
3330
  	next_skb = skb_peek(&chan->srej_q);
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3331

836be9342   Andrei Emeltchenko   Bluetooth: EWS: s...
3332
  	tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
bfbacc115   João Paulo Rechi Vita   Bluetooth: Fix SR...
3333

039d9572f   Szymon Janc   Bluetooth: Simpli...
3334
  	while (next_skb) {
9b53350d3   João Paulo Rechi Vita   Bluetooth: Comple...
3335
3336
  		if (bt_cb(next_skb)->tx_seq == tx_seq)
  			return -EINVAL;
836be9342   Andrei Emeltchenko   Bluetooth: EWS: s...
3337
3338
  		next_tx_seq_offset = __seq_offset(chan,
  				bt_cb(next_skb)->tx_seq, chan->buffer_seq);
bfbacc115   João Paulo Rechi Vita   Bluetooth: Fix SR...
3339
3340
  
  		if (next_tx_seq_offset > tx_seq_offset) {
f1c6775be   Gustavo F. Padovan   Bluetooth: Move s...
3341
  			__skb_queue_before(&chan->srej_q, next_skb, skb);
9b53350d3   João Paulo Rechi Vita   Bluetooth: Comple...
3342
  			return 0;
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3343
  		}
f1c6775be   Gustavo F. Padovan   Bluetooth: Move s...
3344
  		if (skb_queue_is_last(&chan->srej_q, next_skb))
039d9572f   Szymon Janc   Bluetooth: Simpli...
3345
3346
3347
3348
  			next_skb = NULL;
  		else
  			next_skb = skb_queue_next(&chan->srej_q, next_skb);
  	}
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3349

f1c6775be   Gustavo F. Padovan   Bluetooth: Move s...
3350
  	__skb_queue_tail(&chan->srej_q, skb);
9b53350d3   João Paulo Rechi Vita   Bluetooth: Comple...
3351
3352
  
  	return 0;
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3353
  }
84084a319   Mat Martineau   Bluetooth: Perfor...
3354
3355
  static void append_skb_frag(struct sk_buff *skb,
  			struct sk_buff *new_frag, struct sk_buff **last_frag)
18778a63d   Gustavo F. Padovan   Bluetooth: Implem...
3356
  {
84084a319   Mat Martineau   Bluetooth: Perfor...
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
  	/* skb->len reflects data in skb as well as all fragments
  	 * skb->data_len reflects only data in fragments
  	 */
  	if (!skb_has_frag_list(skb))
  		skb_shinfo(skb)->frag_list = new_frag;
  
  	new_frag->next = NULL;
  
  	(*last_frag)->next = new_frag;
  	*last_frag = new_frag;
  
  	skb->len += new_frag->len;
  	skb->data_len += new_frag->len;
  	skb->truesize += new_frag->truesize;
  }
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3372
  static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
84084a319   Mat Martineau   Bluetooth: Perfor...
3373
3374
  {
  	int err = -EINVAL;
18778a63d   Gustavo F. Padovan   Bluetooth: Implem...
3375

7e0ef6ee1   Andrei Emeltchenko   Bluetooth: EWS: r...
3376
3377
  	switch (__get_ctrl_sar(chan, control)) {
  	case L2CAP_SAR_UNSEGMENTED:
84084a319   Mat Martineau   Bluetooth: Perfor...
3378
3379
  		if (chan->sdu)
  			break;
18778a63d   Gustavo F. Padovan   Bluetooth: Implem...
3380

84084a319   Mat Martineau   Bluetooth: Perfor...
3381
3382
  		err = chan->ops->recv(chan->data, skb);
  		break;
18778a63d   Gustavo F. Padovan   Bluetooth: Implem...
3383

7e0ef6ee1   Andrei Emeltchenko   Bluetooth: EWS: r...
3384
  	case L2CAP_SAR_START:
84084a319   Mat Martineau   Bluetooth: Perfor...
3385
3386
  		if (chan->sdu)
  			break;
18778a63d   Gustavo F. Padovan   Bluetooth: Implem...
3387

6f61fd475   Gustavo F. Padovan   Bluetooth: Move S...
3388
  		chan->sdu_len = get_unaligned_le16(skb->data);
03a512137   Andrei Emeltchenko   Bluetooth: EWS: r...
3389
  		skb_pull(skb, L2CAP_SDULEN_SIZE);
18778a63d   Gustavo F. Padovan   Bluetooth: Implem...
3390

84084a319   Mat Martineau   Bluetooth: Perfor...
3391
3392
3393
3394
  		if (chan->sdu_len > chan->imtu) {
  			err = -EMSGSIZE;
  			break;
  		}
1890d36bb   Gustavo F. Padovan   Bluetooth: Implem...
3395

84084a319   Mat Martineau   Bluetooth: Perfor...
3396
3397
  		if (skb->len >= chan->sdu_len)
  			break;
18778a63d   Gustavo F. Padovan   Bluetooth: Implem...
3398

84084a319   Mat Martineau   Bluetooth: Perfor...
3399
3400
  		chan->sdu = skb;
  		chan->sdu_last_frag = skb;
18778a63d   Gustavo F. Padovan   Bluetooth: Implem...
3401

84084a319   Mat Martineau   Bluetooth: Perfor...
3402
3403
  		skb = NULL;
  		err = 0;
18778a63d   Gustavo F. Padovan   Bluetooth: Implem...
3404
  		break;
7e0ef6ee1   Andrei Emeltchenko   Bluetooth: EWS: r...
3405
  	case L2CAP_SAR_CONTINUE:
6f61fd475   Gustavo F. Padovan   Bluetooth: Move S...
3406
  		if (!chan->sdu)
84084a319   Mat Martineau   Bluetooth: Perfor...
3407
  			break;
18778a63d   Gustavo F. Padovan   Bluetooth: Implem...
3408

84084a319   Mat Martineau   Bluetooth: Perfor...
3409
3410
3411
  		append_skb_frag(chan->sdu, skb,
  				&chan->sdu_last_frag);
  		skb = NULL;
18778a63d   Gustavo F. Padovan   Bluetooth: Implem...
3412

84084a319   Mat Martineau   Bluetooth: Perfor...
3413
3414
  		if (chan->sdu->len >= chan->sdu_len)
  			break;
4178ba462   Gustavo F. Padovan   Bluetooth: Preven...
3415

84084a319   Mat Martineau   Bluetooth: Perfor...
3416
  		err = 0;
18778a63d   Gustavo F. Padovan   Bluetooth: Implem...
3417
  		break;
7e0ef6ee1   Andrei Emeltchenko   Bluetooth: EWS: r...
3418
  	case L2CAP_SAR_END:
6f61fd475   Gustavo F. Padovan   Bluetooth: Move S...
3419
  		if (!chan->sdu)
84084a319   Mat Martineau   Bluetooth: Perfor...
3420
  			break;
18778a63d   Gustavo F. Padovan   Bluetooth: Implem...
3421

84084a319   Mat Martineau   Bluetooth: Perfor...
3422
3423
3424
  		append_skb_frag(chan->sdu, skb,
  				&chan->sdu_last_frag);
  		skb = NULL;
4178ba462   Gustavo F. Padovan   Bluetooth: Preven...
3425

84084a319   Mat Martineau   Bluetooth: Perfor...
3426
3427
  		if (chan->sdu->len != chan->sdu_len)
  			break;
18778a63d   Gustavo F. Padovan   Bluetooth: Implem...
3428

84084a319   Mat Martineau   Bluetooth: Perfor...
3429
  		err = chan->ops->recv(chan->data, chan->sdu);
1890d36bb   Gustavo F. Padovan   Bluetooth: Implem...
3430

84084a319   Mat Martineau   Bluetooth: Perfor...
3431
3432
3433
3434
3435
  		if (!err) {
  			/* Reassembly complete */
  			chan->sdu = NULL;
  			chan->sdu_last_frag = NULL;
  			chan->sdu_len = 0;
1890d36bb   Gustavo F. Padovan   Bluetooth: Implem...
3436
  		}
18778a63d   Gustavo F. Padovan   Bluetooth: Implem...
3437
3438
  		break;
  	}
84084a319   Mat Martineau   Bluetooth: Perfor...
3439
3440
3441
3442
3443
3444
3445
  	if (err) {
  		kfree_skb(skb);
  		kfree_skb(chan->sdu);
  		chan->sdu = NULL;
  		chan->sdu_last_frag = NULL;
  		chan->sdu_len = 0;
  	}
18778a63d   Gustavo F. Padovan   Bluetooth: Implem...
3446

84084a319   Mat Martineau   Bluetooth: Perfor...
3447
  	return err;
18778a63d   Gustavo F. Padovan   Bluetooth: Implem...
3448
  }
26f880d22   Mat Martineau   Bluetooth: Move c...
3449
  static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
712132eb5   Gustavo F. Padovan   Bluetooth: Improv...
3450
  {
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3451
  	u32 control;
712132eb5   Gustavo F. Padovan   Bluetooth: Improv...
3452

26f880d22   Mat Martineau   Bluetooth: Move c...
3453
  	BT_DBG("chan %p, Enter local busy", chan);
712132eb5   Gustavo F. Padovan   Bluetooth: Improv...
3454

26f880d22   Mat Martineau   Bluetooth: Move c...
3455
  	set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
0b209fae8   Andrei Emeltchenko   Bluetooth: EWS: r...
3456
  	control = __set_reqseq(chan, chan->buffer_seq);
ab784b738   Andrei Emeltchenko   Bluetooth: EWS: r...
3457
  	control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
26f880d22   Mat Martineau   Bluetooth: Move c...
3458
3459
3460
3461
3462
3463
3464
3465
3466
  	l2cap_send_sframe(chan, control);
  
  	set_bit(CONN_RNR_SENT, &chan->conn_state);
  
  	__clear_ack_timer(chan);
  }
  
  static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
  {
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3467
  	u32 control;
712132eb5   Gustavo F. Padovan   Bluetooth: Improv...
3468

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3469
  	if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
712132eb5   Gustavo F. Padovan   Bluetooth: Improv...
3470
  		goto done;
0b209fae8   Andrei Emeltchenko   Bluetooth: EWS: r...
3471
  	control = __set_reqseq(chan, chan->buffer_seq);
e37817353   Andrei Emeltchenko   Bluetooth: EWS: r...
3472
  	control |= __set_ctrl_poll(chan);
ab784b738   Andrei Emeltchenko   Bluetooth: EWS: r...
3473
  	control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3474
  	l2cap_send_sframe(chan, control);
6a026610e   Gustavo F. Padovan   Bluetooth: Move m...
3475
  	chan->retry_count = 1;
712132eb5   Gustavo F. Padovan   Bluetooth: Improv...
3476

1a09bcb97   Gustavo F. Padovan   Bluetooth: keep r...
3477
3478
  	__clear_retrans_timer(chan);
  	__set_monitor_timer(chan);
712132eb5   Gustavo F. Padovan   Bluetooth: Improv...
3479

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3480
  	set_bit(CONN_WAIT_F, &chan->conn_state);
712132eb5   Gustavo F. Padovan   Bluetooth: Improv...
3481
3482
  
  done:
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3483
3484
  	clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
  	clear_bit(CONN_RNR_SENT, &chan->conn_state);
712132eb5   Gustavo F. Padovan   Bluetooth: Improv...
3485

49208c9c7   Gustavo F. Padovan   Bluetooth: Remove...
3486
  	BT_DBG("chan %p, Exit local busy", chan);
712132eb5   Gustavo F. Padovan   Bluetooth: Improv...
3487
  }
e328140fd   Mat Martineau   Bluetooth: Use ev...
3488
  void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
1890d36bb   Gustavo F. Padovan   Bluetooth: Implem...
3489
  {
e328140fd   Mat Martineau   Bluetooth: Use ev...
3490
3491
3492
3493
3494
  	if (chan->mode == L2CAP_MODE_ERTM) {
  		if (busy)
  			l2cap_ertm_enter_local_busy(chan);
  		else
  			l2cap_ertm_exit_local_busy(chan);
1890d36bb   Gustavo F. Padovan   Bluetooth: Implem...
3495
  	}
1890d36bb   Gustavo F. Padovan   Bluetooth: Implem...
3496
  }
fb45de7db   Andrei Emeltchenko   Bluetooth: EWS: r...
3497
  static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3498
3499
  {
  	struct sk_buff *skb;
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3500
  	u32 control;
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3501

e328140fd   Mat Martineau   Bluetooth: Use ev...
3502
3503
3504
  	while ((skb = skb_peek(&chan->srej_q)) &&
  			!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
  		int err;
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3505
3506
  		if (bt_cb(skb)->tx_seq != tx_seq)
  			break;
f1c6775be   Gustavo F. Padovan   Bluetooth: Move s...
3507
  		skb = skb_dequeue(&chan->srej_q);
7e0ef6ee1   Andrei Emeltchenko   Bluetooth: EWS: r...
3508
  		control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
84084a319   Mat Martineau   Bluetooth: Perfor...
3509
  		err = l2cap_reassemble_sdu(chan, skb, control);
e328140fd   Mat Martineau   Bluetooth: Use ev...
3510
3511
3512
3513
3514
  
  		if (err < 0) {
  			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
  			break;
  		}
836be9342   Andrei Emeltchenko   Bluetooth: EWS: s...
3515
3516
  		chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
  		tx_seq = __next_seq(chan, tx_seq);
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3517
3518
  	}
  }
fb45de7db   Andrei Emeltchenko   Bluetooth: EWS: r...
3519
  static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3520
  {
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3521
  	struct srej_list *l, *tmp;
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3522
  	u32 control;
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3523

39d5a3ee3   Gustavo F. Padovan   Bluetooth: Move S...
3524
  	list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3525
3526
3527
3528
3529
  		if (l->tx_seq == tx_seq) {
  			list_del(&l->list);
  			kfree(l);
  			return;
  		}
ab784b738   Andrei Emeltchenko   Bluetooth: EWS: r...
3530
  		control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
0b209fae8   Andrei Emeltchenko   Bluetooth: EWS: r...
3531
  		control |= __set_reqseq(chan, l->tx_seq);
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3532
  		l2cap_send_sframe(chan, control);
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3533
  		list_del(&l->list);
39d5a3ee3   Gustavo F. Padovan   Bluetooth: Move S...
3534
  		list_add_tail(&l->list, &chan->srej_l);
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3535
3536
  	}
  }
aef89f214   Szymon Janc   Bluetooth: Fix po...
3537
  static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3538
  {
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3539
  	struct srej_list *new;
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3540
  	u32 control;
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3541

42e5c8027   Gustavo F. Padovan   Bluetooth: Move o...
3542
  	while (tx_seq != chan->expected_tx_seq) {
ab784b738   Andrei Emeltchenko   Bluetooth: EWS: r...
3543
  		control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
0b209fae8   Andrei Emeltchenko   Bluetooth: EWS: r...
3544
  		control |= __set_reqseq(chan, chan->expected_tx_seq);
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3545
  		l2cap_send_sframe(chan, control);
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3546
3547
  
  		new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
aef89f214   Szymon Janc   Bluetooth: Fix po...
3548
3549
  		if (!new)
  			return -ENOMEM;
42e5c8027   Gustavo F. Padovan   Bluetooth: Move o...
3550
  		new->tx_seq = chan->expected_tx_seq;
836be9342   Andrei Emeltchenko   Bluetooth: EWS: s...
3551
3552
  
  		chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
39d5a3ee3   Gustavo F. Padovan   Bluetooth: Move S...
3553
  		list_add_tail(&new->list, &chan->srej_l);
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3554
  	}
836be9342   Andrei Emeltchenko   Bluetooth: EWS: s...
3555
3556
  
  	chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
aef89f214   Szymon Janc   Bluetooth: Fix po...
3557
3558
  
  	return 0;
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3559
  }
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3560
  static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
3561
  {
fb45de7db   Andrei Emeltchenko   Bluetooth: EWS: r...
3562
  	u16 tx_seq = __get_txseq(chan, rx_control);
0b209fae8   Andrei Emeltchenko   Bluetooth: EWS: r...
3563
  	u16 req_seq = __get_reqseq(chan, rx_control);
7e0ef6ee1   Andrei Emeltchenko   Bluetooth: EWS: r...
3564
  	u8 sar = __get_ctrl_sar(chan, rx_control);
f6337c771   Gustavo F. Padovan   Bluetooth: Fix dr...
3565
  	int tx_seq_offset, expected_tx_seq_offset;
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
3566
  	int num_to_ack = (chan->tx_win/6) + 1;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
3567
  	int err = 0;
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3568
  	BT_DBG("chan %p len %d tx_seq %d rx_control 0x%8.8x", chan, skb->len,
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3569
  							tx_seq, rx_control);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
3570

03f6715d4   Andrei Emeltchenko   Bluetooth: EWS: r...
3571
  	if (__is_ctrl_final(chan, rx_control) &&
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3572
  			test_bit(CONN_WAIT_F, &chan->conn_state)) {
1a09bcb97   Gustavo F. Padovan   Bluetooth: keep r...
3573
  		__clear_monitor_timer(chan);
6a026610e   Gustavo F. Padovan   Bluetooth: Move m...
3574
  		if (chan->unacked_frames > 0)
1a09bcb97   Gustavo F. Padovan   Bluetooth: keep r...
3575
  			__set_retrans_timer(chan);
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3576
  		clear_bit(CONN_WAIT_F, &chan->conn_state);
1d8f5d169   Gustavo F. Padovan   Bluetooth: Suppor...
3577
  	}
42e5c8027   Gustavo F. Padovan   Bluetooth: Move o...
3578
3579
  	chan->expected_ack_seq = req_seq;
  	l2cap_drop_acked_frames(chan);
9f121a5a8   Gustavo F. Padovan   Bluetooth: Fix se...
3580

836be9342   Andrei Emeltchenko   Bluetooth: EWS: s...
3581
  	tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
9b53350d3   João Paulo Rechi Vita   Bluetooth: Comple...
3582
3583
  
  	/* invalid tx_seq */
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
3584
  	if (tx_seq_offset >= chan->tx_win) {
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
3585
  		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
9b53350d3   João Paulo Rechi Vita   Bluetooth: Comple...
3586
3587
  		goto drop;
  	}
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3588
  	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
1890d36bb   Gustavo F. Padovan   Bluetooth: Implem...
3589
  		goto drop;
02f1b6410   Mat Martineau   Bluetooth: Check ...
3590
3591
  	if (tx_seq == chan->expected_tx_seq)
  		goto expected;
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3592
  	if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3593
  		struct srej_list *first;
30afb5b2a   Gustavo F. Padovan   Bluetooth: Initia...
3594

39d5a3ee3   Gustavo F. Padovan   Bluetooth: Move S...
3595
  		first = list_first_entry(&chan->srej_l,
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3596
3597
  				struct srej_list, list);
  		if (tx_seq == first->tx_seq) {
42e5c8027   Gustavo F. Padovan   Bluetooth: Move o...
3598
  			l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3599
  			l2cap_check_srej_gap(chan, tx_seq);
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3600
3601
3602
  
  			list_del(&first->list);
  			kfree(first);
39d5a3ee3   Gustavo F. Padovan   Bluetooth: Move S...
3603
  			if (list_empty(&chan->srej_l)) {
42e5c8027   Gustavo F. Padovan   Bluetooth: Move o...
3604
  				chan->buffer_seq = chan->buffer_seq_srej;
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3605
  				clear_bit(CONN_SREJ_SENT, &chan->conn_state);
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3606
  				l2cap_send_ack(chan);
49208c9c7   Gustavo F. Padovan   Bluetooth: Remove...
3607
  				BT_DBG("chan %p, Exit SREJ_SENT", chan);
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3608
3609
3610
  			}
  		} else {
  			struct srej_list *l;
9b53350d3   João Paulo Rechi Vita   Bluetooth: Comple...
3611
3612
  
  			/* duplicated tx_seq */
42e5c8027   Gustavo F. Padovan   Bluetooth: Move o...
3613
  			if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
9b53350d3   João Paulo Rechi Vita   Bluetooth: Comple...
3614
  				goto drop;
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3615

39d5a3ee3   Gustavo F. Padovan   Bluetooth: Move S...
3616
  			list_for_each_entry(l, &chan->srej_l, list) {
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3617
  				if (l->tx_seq == tx_seq) {
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3618
  					l2cap_resend_srejframe(chan, tx_seq);
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3619
3620
3621
  					return 0;
  				}
  			}
aef89f214   Szymon Janc   Bluetooth: Fix po...
3622
3623
3624
3625
3626
3627
  
  			err = l2cap_send_srejframe(chan, tx_seq);
  			if (err < 0) {
  				l2cap_send_disconn_req(chan->conn, chan, -err);
  				return err;
  			}
30afb5b2a   Gustavo F. Padovan   Bluetooth: Initia...
3628
3629
  		}
  	} else {
836be9342   Andrei Emeltchenko   Bluetooth: EWS: s...
3630
3631
  		expected_tx_seq_offset = __seq_offset(chan,
  				chan->expected_tx_seq, chan->buffer_seq);
9b53350d3   João Paulo Rechi Vita   Bluetooth: Comple...
3632
3633
3634
3635
  
  		/* duplicated tx_seq */
  		if (tx_seq_offset < expected_tx_seq_offset)
  			goto drop;
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3636
  		set_bit(CONN_SREJ_SENT, &chan->conn_state);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
3637

49208c9c7   Gustavo F. Padovan   Bluetooth: Remove...
3638
  		BT_DBG("chan %p, Enter SREJ", chan);
0e98958d4   Gustavo F. Padovan   Bluetooth: Add de...
3639

39d5a3ee3   Gustavo F. Padovan   Bluetooth: Move S...
3640
  		INIT_LIST_HEAD(&chan->srej_l);
42e5c8027   Gustavo F. Padovan   Bluetooth: Move o...
3641
  		chan->buffer_seq_srej = chan->buffer_seq;
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3642

f1c6775be   Gustavo F. Padovan   Bluetooth: Move s...
3643
  		__skb_queue_head_init(&chan->srej_q);
42e5c8027   Gustavo F. Padovan   Bluetooth: Move o...
3644
  		l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3645

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3646
  		set_bit(CONN_SEND_PBIT, &chan->conn_state);
ef54fd937   Gustavo F. Padovan   Bluetooth: Full s...
3647

aef89f214   Szymon Janc   Bluetooth: Fix po...
3648
3649
3650
3651
3652
  		err = l2cap_send_srejframe(chan, tx_seq);
  		if (err < 0) {
  			l2cap_send_disconn_req(chan->conn, chan, -err);
  			return err;
  		}
7fe9b298c   Gustavo F. Padovan   Bluetooth: Stop a...
3653

1a09bcb97   Gustavo F. Padovan   Bluetooth: keep r...
3654
  		__clear_ack_timer(chan);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
3655
  	}
30afb5b2a   Gustavo F. Padovan   Bluetooth: Initia...
3656
  	return 0;
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3657
  expected:
836be9342   Andrei Emeltchenko   Bluetooth: EWS: s...
3658
  	chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3659

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3660
  	if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3b1a9f3fa   Gustavo F. Padovan   Bluetooth: Optimi...
3661
3662
  		bt_cb(skb)->tx_seq = tx_seq;
  		bt_cb(skb)->sar = sar;
f1c6775be   Gustavo F. Padovan   Bluetooth: Move s...
3663
  		__skb_queue_tail(&chan->srej_q, skb);
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3664
3665
  		return 0;
  	}
84084a319   Mat Martineau   Bluetooth: Perfor...
3666
  	err = l2cap_reassemble_sdu(chan, skb, rx_control);
836be9342   Andrei Emeltchenko   Bluetooth: EWS: s...
3667
  	chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
e328140fd   Mat Martineau   Bluetooth: Use ev...
3668
3669
3670
3671
  	if (err < 0) {
  		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
  		return err;
  	}
2ece3684b   Gustavo F. Padovan   Bluetooth: Update...
3672

03f6715d4   Andrei Emeltchenko   Bluetooth: EWS: r...
3673
  	if (__is_ctrl_final(chan, rx_control)) {
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3674
  		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3675
  			l2cap_retransmit_frames(chan);
4ec10d972   Gustavo F. Padovan   Bluetooth: Implem...
3676
  	}
c1b4f43be   Gustavo F. Padovan   Bluetooth: Add ti...
3677

6a026610e   Gustavo F. Padovan   Bluetooth: Move m...
3678
3679
  	chan->num_acked = (chan->num_acked + 1) % num_to_ack;
  	if (chan->num_acked == num_to_ack - 1)
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3680
  		l2cap_send_ack(chan);
4d611e4d3   Gustavo F. Padovan   Bluetooth: Only s...
3681
3682
  	else
  		__set_ack_timer(chan);
9e917af13   Gustavo F. Padovan   Bluetooth: Implem...
3683

8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3684
  	return 0;
9b53350d3   João Paulo Rechi Vita   Bluetooth: Comple...
3685
3686
3687
3688
  
  drop:
  	kfree_skb(skb);
  	return 0;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
3689
  }
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3690
  static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
3691
  {
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3692
  	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
0b209fae8   Andrei Emeltchenko   Bluetooth: EWS: r...
3693
  				__get_reqseq(chan, rx_control), rx_control);
0e98958d4   Gustavo F. Padovan   Bluetooth: Add de...
3694

0b209fae8   Andrei Emeltchenko   Bluetooth: EWS: r...
3695
  	chan->expected_ack_seq = __get_reqseq(chan, rx_control);
42e5c8027   Gustavo F. Padovan   Bluetooth: Move o...
3696
  	l2cap_drop_acked_frames(chan);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
3697

e37817353   Andrei Emeltchenko   Bluetooth: EWS: r...
3698
  	if (__is_ctrl_poll(chan, rx_control)) {
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3699
3700
3701
  		set_bit(CONN_SEND_FBIT, &chan->conn_state);
  		if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
  			if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
6a026610e   Gustavo F. Padovan   Bluetooth: Move m...
3702
  					(chan->unacked_frames > 0))
1a09bcb97   Gustavo F. Padovan   Bluetooth: keep r...
3703
  				__set_retrans_timer(chan);
05fbd89dd   Gustavo F. Padovan   Bluetooth: Finish...
3704

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3705
  			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3706
  			l2cap_send_srejtail(chan);
05fbd89dd   Gustavo F. Padovan   Bluetooth: Finish...
3707
  		} else {
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3708
  			l2cap_send_i_or_rr_or_rnr(chan);
05fbd89dd   Gustavo F. Padovan   Bluetooth: Finish...
3709
  		}
1d8f5d169   Gustavo F. Padovan   Bluetooth: Suppor...
3710

03f6715d4   Andrei Emeltchenko   Bluetooth: EWS: r...
3711
  	} else if (__is_ctrl_final(chan, rx_control)) {
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3712
  		clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4ec10d972   Gustavo F. Padovan   Bluetooth: Implem...
3713

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3714
  		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3715
  			l2cap_retransmit_frames(chan);
2246b2f1b   Gustavo F. Padovan   Bluetooth: Handle...
3716

e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3717
  	} else {
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3718
  		if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
6a026610e   Gustavo F. Padovan   Bluetooth: Move m...
3719
  				(chan->unacked_frames > 0))
1a09bcb97   Gustavo F. Padovan   Bluetooth: keep r...
3720
  			__set_retrans_timer(chan);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
3721

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3722
3723
  		clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
  		if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3724
  			l2cap_send_ack(chan);
894718a6b   Andrei Emeltchenko   Bluetooth: clean ...
3725
  		else
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3726
  			l2cap_ertm_send(chan);
e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3727
3728
  	}
  }
2246b2f1b   Gustavo F. Padovan   Bluetooth: Handle...
3729

88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3730
  static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3731
  {
0b209fae8   Andrei Emeltchenko   Bluetooth: EWS: r...
3732
  	u16 tx_seq = __get_reqseq(chan, rx_control);
30afb5b2a   Gustavo F. Padovan   Bluetooth: Initia...
3733

88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3734
  	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
0e98958d4   Gustavo F. Padovan   Bluetooth: Add de...
3735

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3736
  	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3737

42e5c8027   Gustavo F. Padovan   Bluetooth: Move o...
3738
3739
  	chan->expected_ack_seq = tx_seq;
  	l2cap_drop_acked_frames(chan);
e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3740

03f6715d4   Andrei Emeltchenko   Bluetooth: EWS: r...
3741
  	if (__is_ctrl_final(chan, rx_control)) {
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3742
  		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3743
  			l2cap_retransmit_frames(chan);
e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3744
  	} else {
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3745
  		l2cap_retransmit_frames(chan);
30afb5b2a   Gustavo F. Padovan   Bluetooth: Initia...
3746

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3747
3748
  		if (test_bit(CONN_WAIT_F, &chan->conn_state))
  			set_bit(CONN_REJ_ACT, &chan->conn_state);
e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3749
3750
  	}
  }
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3751
  static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3752
  {
0b209fae8   Andrei Emeltchenko   Bluetooth: EWS: r...
3753
  	u16 tx_seq = __get_reqseq(chan, rx_control);
30afb5b2a   Gustavo F. Padovan   Bluetooth: Initia...
3754

88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3755
  	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
0e98958d4   Gustavo F. Padovan   Bluetooth: Add de...
3756

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3757
  	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
2246b2f1b   Gustavo F. Padovan   Bluetooth: Handle...
3758

e37817353   Andrei Emeltchenko   Bluetooth: EWS: r...
3759
  	if (__is_ctrl_poll(chan, rx_control)) {
42e5c8027   Gustavo F. Padovan   Bluetooth: Move o...
3760
3761
  		chan->expected_ack_seq = tx_seq;
  		l2cap_drop_acked_frames(chan);
3cb123d1c   Gustavo F. Padovan   Bluetooth: Fix ha...
3762

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3763
  		set_bit(CONN_SEND_FBIT, &chan->conn_state);
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3764
  		l2cap_retransmit_one_frame(chan, tx_seq);
dfc909bef   Gustavo F. Padovan   Bluetooth: Fix ra...
3765

525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3766
  		l2cap_ertm_send(chan);
dfc909bef   Gustavo F. Padovan   Bluetooth: Fix ra...
3767

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3768
  		if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
6a026610e   Gustavo F. Padovan   Bluetooth: Move m...
3769
  			chan->srej_save_reqseq = tx_seq;
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3770
  			set_bit(CONN_SREJ_ACT, &chan->conn_state);
ef54fd937   Gustavo F. Padovan   Bluetooth: Full s...
3771
  		}
03f6715d4   Andrei Emeltchenko   Bluetooth: EWS: r...
3772
  	} else if (__is_ctrl_final(chan, rx_control)) {
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3773
  		if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
6a026610e   Gustavo F. Padovan   Bluetooth: Move m...
3774
  				chan->srej_save_reqseq == tx_seq)
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3775
  			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3776
  		else
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3777
  			l2cap_retransmit_one_frame(chan, tx_seq);
e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3778
  	} else {
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3779
  		l2cap_retransmit_one_frame(chan, tx_seq);
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3780
  		if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
6a026610e   Gustavo F. Padovan   Bluetooth: Move m...
3781
  			chan->srej_save_reqseq = tx_seq;
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3782
  			set_bit(CONN_SREJ_ACT, &chan->conn_state);
ef54fd937   Gustavo F. Padovan   Bluetooth: Full s...
3783
  		}
e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3784
3785
  	}
  }
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3786
  static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3787
  {
0b209fae8   Andrei Emeltchenko   Bluetooth: EWS: r...
3788
  	u16 tx_seq = __get_reqseq(chan, rx_control);
e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3789

88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3790
  	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
0e98958d4   Gustavo F. Padovan   Bluetooth: Add de...
3791

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3792
  	set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
42e5c8027   Gustavo F. Padovan   Bluetooth: Move o...
3793
3794
  	chan->expected_ack_seq = tx_seq;
  	l2cap_drop_acked_frames(chan);
e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3795

e37817353   Andrei Emeltchenko   Bluetooth: EWS: r...
3796
  	if (__is_ctrl_poll(chan, rx_control))
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3797
  		set_bit(CONN_SEND_FBIT, &chan->conn_state);
3cb123d1c   Gustavo F. Padovan   Bluetooth: Fix ha...
3798

e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3799
  	if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
1a09bcb97   Gustavo F. Padovan   Bluetooth: keep r...
3800
  		__clear_retrans_timer(chan);
e37817353   Andrei Emeltchenko   Bluetooth: EWS: r...
3801
  		if (__is_ctrl_poll(chan, rx_control))
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3802
  			l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
99b0d4b7b   Gustavo F. Padovan   Bluetooth: Handle...
3803
  		return;
e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3804
  	}
99b0d4b7b   Gustavo F. Padovan   Bluetooth: Handle...
3805

e37817353   Andrei Emeltchenko   Bluetooth: EWS: r...
3806
  	if (__is_ctrl_poll(chan, rx_control)) {
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3807
  		l2cap_send_srejtail(chan);
ab784b738   Andrei Emeltchenko   Bluetooth: EWS: r...
3808
3809
3810
3811
  	} else {
  		rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
  		l2cap_send_sframe(chan, rx_control);
  	}
e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3812
  }
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3813
  static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3814
  {
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3815
  	BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3816

03f6715d4   Andrei Emeltchenko   Bluetooth: EWS: r...
3817
  	if (__is_ctrl_final(chan, rx_control) &&
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3818
  			test_bit(CONN_WAIT_F, &chan->conn_state)) {
1a09bcb97   Gustavo F. Padovan   Bluetooth: keep r...
3819
  		__clear_monitor_timer(chan);
6a026610e   Gustavo F. Padovan   Bluetooth: Move m...
3820
  		if (chan->unacked_frames > 0)
1a09bcb97   Gustavo F. Padovan   Bluetooth: keep r...
3821
  			__set_retrans_timer(chan);
e2ab43536   Gustavo F. Padovan   Bluetooth: Use bi...
3822
  		clear_bit(CONN_WAIT_F, &chan->conn_state);
e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3823
  	}
ab784b738   Andrei Emeltchenko   Bluetooth: EWS: r...
3824
3825
  	switch (__get_ctrl_super(chan, rx_control)) {
  	case L2CAP_SUPER_RR:
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3826
  		l2cap_data_channel_rrframe(chan, rx_control);
8f17154f1   Gustavo F. Padovan   Bluetooth: Add su...
3827
  		break;
ab784b738   Andrei Emeltchenko   Bluetooth: EWS: r...
3828
  	case L2CAP_SUPER_REJ:
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3829
  		l2cap_data_channel_rejframe(chan, rx_control);
e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3830
  		break;
2246b2f1b   Gustavo F. Padovan   Bluetooth: Handle...
3831

ab784b738   Andrei Emeltchenko   Bluetooth: EWS: r...
3832
  	case L2CAP_SUPER_SREJ:
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3833
  		l2cap_data_channel_srejframe(chan, rx_control);
e072745f4   Gustavo F. Padovan   Bluetooth: Split ...
3834
  		break;
ab784b738   Andrei Emeltchenko   Bluetooth: EWS: r...
3835
  	case L2CAP_SUPER_RNR:
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3836
  		l2cap_data_channel_rnrframe(chan, rx_control);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
3837
3838
  		break;
  	}
faaebd192   Gustavo F. Padovan   Bluetooth: Fix me...
3839
  	kfree_skb(skb);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
3840
3841
  	return 0;
  }
218bb9dfd   Gustavo F. Padovan   Bluetooth: Add ba...
3842
3843
  static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
  {
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3844
  	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3845
  	u32 control;
0b209fae8   Andrei Emeltchenko   Bluetooth: EWS: r...
3846
  	u16 req_seq;
218bb9dfd   Gustavo F. Padovan   Bluetooth: Add ba...
3847
  	int len, next_tx_seq_offset, req_seq_offset;
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3848
3849
  	control = __get_control(chan, skb->data);
  	skb_pull(skb, __ctrl_size(chan));
218bb9dfd   Gustavo F. Padovan   Bluetooth: Add ba...
3850
3851
3852
3853
3854
3855
3856
  	len = skb->len;
  
  	/*
  	 * We can just drop the corrupted I-frame here.
  	 * Receiver will miss it and start proper recovery
  	 * procedures and ask retransmission.
  	 */
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
3857
  	if (l2cap_check_fcs(chan, skb))
218bb9dfd   Gustavo F. Padovan   Bluetooth: Add ba...
3858
  		goto drop;
793c2f1cb   Andrei Emeltchenko   Bluetooth: EWS: r...
3859
  	if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
03a512137   Andrei Emeltchenko   Bluetooth: EWS: r...
3860
  		len -= L2CAP_SDULEN_SIZE;
218bb9dfd   Gustavo F. Padovan   Bluetooth: Add ba...
3861

47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
3862
  	if (chan->fcs == L2CAP_FCS_CRC16)
03a512137   Andrei Emeltchenko   Bluetooth: EWS: r...
3863
  		len -= L2CAP_FCS_SIZE;
218bb9dfd   Gustavo F. Padovan   Bluetooth: Add ba...
3864

47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
3865
  	if (len > chan->mps) {
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
3866
  		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
218bb9dfd   Gustavo F. Padovan   Bluetooth: Add ba...
3867
3868
  		goto drop;
  	}
0b209fae8   Andrei Emeltchenko   Bluetooth: EWS: r...
3869
  	req_seq = __get_reqseq(chan, control);
218bb9dfd   Gustavo F. Padovan   Bluetooth: Add ba...
3870

836be9342   Andrei Emeltchenko   Bluetooth: EWS: s...
3871
3872
3873
3874
  	req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
  
  	next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
  						chan->expected_ack_seq);
218bb9dfd   Gustavo F. Padovan   Bluetooth: Add ba...
3875
3876
3877
  
  	/* check for invalid req-seq */
  	if (req_seq_offset > next_tx_seq_offset) {
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
3878
  		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
218bb9dfd   Gustavo F. Padovan   Bluetooth: Add ba...
3879
3880
  		goto drop;
  	}
793c2f1cb   Andrei Emeltchenko   Bluetooth: EWS: r...
3881
  	if (!__is_sframe(chan, control)) {
218bb9dfd   Gustavo F. Padovan   Bluetooth: Add ba...
3882
  		if (len < 0) {
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
3883
  			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
218bb9dfd   Gustavo F. Padovan   Bluetooth: Add ba...
3884
3885
  			goto drop;
  		}
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3886
  		l2cap_data_channel_iframe(chan, control, skb);
218bb9dfd   Gustavo F. Padovan   Bluetooth: Add ba...
3887
3888
3889
  	} else {
  		if (len != 0) {
  			BT_ERR("%d", len);
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
3890
  			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
218bb9dfd   Gustavo F. Padovan   Bluetooth: Add ba...
3891
3892
  			goto drop;
  		}
525cd1851   Gustavo F. Padovan   Bluetooth: Move c...
3893
  		l2cap_data_channel_sframe(chan, control, skb);
218bb9dfd   Gustavo F. Padovan   Bluetooth: Add ba...
3894
3895
3896
3897
3898
3899
3900
3901
  	}
  
  	return 0;
  
  drop:
  	kfree_skb(skb);
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3902
3903
  static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
  {
48454079c   Gustavo F. Padovan   Bluetooth: Create...
3904
  	struct l2cap_chan *chan;
bf7348431   David S. Miller   bluetooth: Fix us...
3905
  	struct sock *sk = NULL;
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3906
  	u32 control;
fb45de7db   Andrei Emeltchenko   Bluetooth: EWS: r...
3907
  	u16 tx_seq;
218bb9dfd   Gustavo F. Padovan   Bluetooth: Add ba...
3908
  	int len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3909

baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
3910
  	chan = l2cap_get_chan_by_scid(conn, cid);
48454079c   Gustavo F. Padovan   Bluetooth: Create...
3911
  	if (!chan) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3912
3913
3914
  		BT_DBG("unknown cid 0x%4.4x", cid);
  		goto drop;
  	}
48454079c   Gustavo F. Padovan   Bluetooth: Create...
3915
  	sk = chan->sk;
6840ed077   Gustavo F. Padovan   Bluetooth: Enable...
3916

49208c9c7   Gustavo F. Padovan   Bluetooth: Remove...
3917
  	BT_DBG("chan %p, len %d", chan, skb->len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3918

89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
3919
  	if (chan->state != BT_CONNECTED)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3920
  		goto drop;
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
3921
  	switch (chan->mode) {
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
3922
3923
3924
3925
3926
  	case L2CAP_MODE_BASIC:
  		/* If socket recv buffers overflows we drop data here
  		 * which is *bad* because L2CAP has to be reliable.
  		 * But we don't have any other choice. L2CAP doesn't
  		 * provide flow control mechanism. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3927

0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
3928
  		if (chan->imtu < skb->len)
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
3929
  			goto drop;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3930

230704942   Gustavo F. Padovan   Bluetooth: add re...
3931
  		if (!chan->ops->recv(chan->data, skb))
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
3932
3933
3934
3935
  			goto done;
  		break;
  
  	case L2CAP_MODE_ERTM:
eb403a1b7   Gustavo F. Padovan   Bluetooth: Remove...
3936
  		l2cap_ertm_data_rcv(sk, skb);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
3937

fcafde2e6   Andrei Emeltchenko   Bluetooth: Remove...
3938
  		goto done;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
3939

6840ed077   Gustavo F. Padovan   Bluetooth: Enable...
3940
  	case L2CAP_MODE_STREAMING:
88843ab06   Andrei Emeltchenko   Bluetooth: EWS: h...
3941
3942
  		control = __get_control(chan, skb->data);
  		skb_pull(skb, __ctrl_size(chan));
6840ed077   Gustavo F. Padovan   Bluetooth: Enable...
3943
  		len = skb->len;
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
3944
  		if (l2cap_check_fcs(chan, skb))
260000896   Gustavo F. Padovan   Bluetooth: Check ...
3945
  			goto drop;
7e0ef6ee1   Andrei Emeltchenko   Bluetooth: EWS: r...
3946
  		if (__is_sar_start(chan, control))
03a512137   Andrei Emeltchenko   Bluetooth: EWS: r...
3947
  			len -= L2CAP_SDULEN_SIZE;
6840ed077   Gustavo F. Padovan   Bluetooth: Enable...
3948

47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
3949
  		if (chan->fcs == L2CAP_FCS_CRC16)
03a512137   Andrei Emeltchenko   Bluetooth: EWS: r...
3950
  			len -= L2CAP_FCS_SIZE;
fcc203c30   Gustavo F. Padovan   Bluetooth: Add su...
3951

793c2f1cb   Andrei Emeltchenko   Bluetooth: EWS: r...
3952
  		if (len > chan->mps || len < 0 || __is_sframe(chan, control))
6840ed077   Gustavo F. Padovan   Bluetooth: Enable...
3953
  			goto drop;
fb45de7db   Andrei Emeltchenko   Bluetooth: EWS: r...
3954
  		tx_seq = __get_txseq(chan, control);
6840ed077   Gustavo F. Padovan   Bluetooth: Enable...
3955

84084a319   Mat Martineau   Bluetooth: Perfor...
3956
3957
3958
3959
3960
3961
  		if (chan->expected_tx_seq != tx_seq) {
  			/* Frame(s) missing - must discard partial SDU */
  			kfree_skb(chan->sdu);
  			chan->sdu = NULL;
  			chan->sdu_last_frag = NULL;
  			chan->sdu_len = 0;
6840ed077   Gustavo F. Padovan   Bluetooth: Enable...
3962

84084a319   Mat Martineau   Bluetooth: Perfor...
3963
3964
  			/* TODO: Notify userland of missing data */
  		}
836be9342   Andrei Emeltchenko   Bluetooth: EWS: s...
3965
  		chan->expected_tx_seq = __next_seq(chan, tx_seq);
84084a319   Mat Martineau   Bluetooth: Perfor...
3966
3967
3968
  
  		if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
  			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
6840ed077   Gustavo F. Padovan   Bluetooth: Enable...
3969
3970
  
  		goto done;
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
3971
  	default:
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
3972
  		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
3973
3974
  		break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3975
3976
3977
3978
3979
  
  drop:
  	kfree_skb(skb);
  
  done:
0139418c9   Marcel Holtmann   [Bluetooth] Small...
3980
  	if (sk)
aa2ac881b   Gustavo F. Padovan   Bluetooth: Don't ...
3981
  		release_sock(sk);
0139418c9   Marcel Holtmann   [Bluetooth] Small...
3982

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3983
3984
  	return 0;
  }
8e036fc31   Al Viro   [BLUETOOTH] l2cap...
3985
  static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3986
  {
6dcae1eae   David S. Miller   bluetooth: Fix wa...
3987
  	struct sock *sk = NULL;
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
3988
  	struct l2cap_chan *chan;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3989

23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
3990
3991
  	chan = l2cap_global_chan_by_psm(0, psm, conn->src);
  	if (!chan)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3992
  		goto drop;
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
3993
  	sk = chan->sk;
aa2ac881b   Gustavo F. Padovan   Bluetooth: Don't ...
3994
  	lock_sock(sk);
e0f0cb563   Gustavo F. Padovan   Bluetooth: Get ri...
3995

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3996
  	BT_DBG("sk %p, len %d", sk, skb->len);
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
3997
  	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3998
  		goto drop;
e13e21dc5   Vinicius Costa Gomes   Bluetooth: Remove...
3999
  	if (chan->imtu < skb->len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4000
  		goto drop;
230704942   Gustavo F. Padovan   Bluetooth: add re...
4001
  	if (!chan->ops->recv(chan->data, skb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4002
4003
4004
4005
4006
4007
  		goto done;
  
  drop:
  	kfree_skb(skb);
  
  done:
af05b30bc   Gustavo F. Padovan   Bluetooth: Fix er...
4008
  	if (sk)
aa2ac881b   Gustavo F. Padovan   Bluetooth: Don't ...
4009
  		release_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4010
4011
  	return 0;
  }
9f69bda6a   Gustavo F. Padovan   Bluetooth: Add pr...
4012
4013
  static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
  {
6dcae1eae   David S. Miller   bluetooth: Fix wa...
4014
  	struct sock *sk = NULL;
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
4015
  	struct l2cap_chan *chan;
9f69bda6a   Gustavo F. Padovan   Bluetooth: Add pr...
4016

23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
4017
4018
  	chan = l2cap_global_chan_by_scid(0, cid, conn->src);
  	if (!chan)
9f69bda6a   Gustavo F. Padovan   Bluetooth: Add pr...
4019
  		goto drop;
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
4020
  	sk = chan->sk;
aa2ac881b   Gustavo F. Padovan   Bluetooth: Don't ...
4021
  	lock_sock(sk);
9f69bda6a   Gustavo F. Padovan   Bluetooth: Add pr...
4022
4023
  
  	BT_DBG("sk %p, len %d", sk, skb->len);
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
4024
  	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
9f69bda6a   Gustavo F. Padovan   Bluetooth: Add pr...
4025
  		goto drop;
e13e21dc5   Vinicius Costa Gomes   Bluetooth: Remove...
4026
  	if (chan->imtu < skb->len)
9f69bda6a   Gustavo F. Padovan   Bluetooth: Add pr...
4027
  		goto drop;
230704942   Gustavo F. Padovan   Bluetooth: add re...
4028
  	if (!chan->ops->recv(chan->data, skb))
9f69bda6a   Gustavo F. Padovan   Bluetooth: Add pr...
4029
4030
4031
4032
4033
4034
4035
  		goto done;
  
  drop:
  	kfree_skb(skb);
  
  done:
  	if (sk)
aa2ac881b   Gustavo F. Padovan   Bluetooth: Don't ...
4036
  		release_sock(sk);
9f69bda6a   Gustavo F. Padovan   Bluetooth: Add pr...
4037
4038
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4039
4040
4041
  static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
  {
  	struct l2cap_hdr *lh = (void *) skb->data;
8e036fc31   Al Viro   [BLUETOOTH] l2cap...
4042
4043
  	u16 cid, len;
  	__le16 psm;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4044
4045
4046
4047
  
  	skb_pull(skb, L2CAP_HDR_SIZE);
  	cid = __le16_to_cpu(lh->cid);
  	len = __le16_to_cpu(lh->len);
1c2acffb7   Gustavo F. Padovan   Bluetooth: Add in...
4048
4049
4050
4051
  	if (len != skb->len) {
  		kfree_skb(skb);
  		return;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4052
4053
4054
  	BT_DBG("len %d, cid 0x%4.4x", len, cid);
  
  	switch (cid) {
3300d9a93   Claudio Takahasi   Bluetooth: Add LE...
4055
  	case L2CAP_CID_LE_SIGNALING:
8db4dc46d   Gustavo F. Padovan   Bluetooth: Use ma...
4056
  	case L2CAP_CID_SIGNALING:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4057
4058
  		l2cap_sig_channel(conn, skb);
  		break;
8db4dc46d   Gustavo F. Padovan   Bluetooth: Use ma...
4059
  	case L2CAP_CID_CONN_LESS:
1b7bf4edc   Gustavo F. Padovan   Bluetooth: Use pr...
4060
  		psm = get_unaligned_le16(skb->data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4061
4062
4063
  		skb_pull(skb, 2);
  		l2cap_conless_channel(conn, psm, skb);
  		break;
9f69bda6a   Gustavo F. Padovan   Bluetooth: Add pr...
4064
4065
4066
  	case L2CAP_CID_LE_DATA:
  		l2cap_att_channel(conn, cid, skb);
  		break;
b501d6a1d   Anderson Briglia   Bluetooth: Start ...
4067
4068
4069
4070
  	case L2CAP_CID_SMP:
  		if (smp_sig_channel(conn, skb))
  			l2cap_conn_del(conn->hcon, EACCES);
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4071
4072
4073
4074
4075
4076
4077
  	default:
  		l2cap_data_channel(conn, cid, skb);
  		break;
  	}
  }
  
  /* ---- L2CAP interface with lower layer (HCI) ---- */
686ebf283   Ulisses Furquim   Bluetooth: Make H...
4078
  int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4079
4080
  {
  	int exact = 0, lm1 = 0, lm2 = 0;
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
4081
  	struct l2cap_chan *c;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4082

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4083
4084
4085
  	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
  
  	/* Find listening sockets and check their link_mode */
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
4086
4087
4088
  	read_lock(&chan_list_lock);
  	list_for_each_entry(c, &chan_list, global_l) {
  		struct sock *sk = c->sk;
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
4089

89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
4090
  		if (c->state != BT_LISTEN)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4091
4092
4093
  			continue;
  
  		if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
2af6b9d51   Marcel Holtmann   Bluetooth: Replac...
4094
  			lm1 |= HCI_LM_ACCEPT;
43bd0f32d   Andrei Emeltchenko   Bluetooth: conver...
4095
  			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
2af6b9d51   Marcel Holtmann   Bluetooth: Replac...
4096
  				lm1 |= HCI_LM_MASTER;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4097
  			exact++;
2af6b9d51   Marcel Holtmann   Bluetooth: Replac...
4098
4099
  		} else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
  			lm2 |= HCI_LM_ACCEPT;
43bd0f32d   Andrei Emeltchenko   Bluetooth: conver...
4100
  			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
2af6b9d51   Marcel Holtmann   Bluetooth: Replac...
4101
4102
  				lm2 |= HCI_LM_MASTER;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4103
  	}
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
4104
  	read_unlock(&chan_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4105
4106
4107
  
  	return exact ? lm1 : lm2;
  }
686ebf283   Ulisses Furquim   Bluetooth: Make H...
4108
  int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4109
  {
0139418c9   Marcel Holtmann   [Bluetooth] Small...
4110
  	struct l2cap_conn *conn;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4111
  	BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4112
  	if (!status) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4113
4114
4115
  		conn = l2cap_conn_add(hcon, status);
  		if (conn)
  			l2cap_conn_ready(conn);
0139418c9   Marcel Holtmann   [Bluetooth] Small...
4116
  	} else
e175072f3   Joe Perches   Bluetooth: Rename...
4117
  		l2cap_conn_del(hcon, bt_to_errno(status));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4118
4119
4120
  
  	return 0;
  }
686ebf283   Ulisses Furquim   Bluetooth: Make H...
4121
  int l2cap_disconn_ind(struct hci_conn *hcon)
2950f21ac   Marcel Holtmann   Bluetooth: Ask up...
4122
4123
4124
4125
  {
  	struct l2cap_conn *conn = hcon->l2cap_data;
  
  	BT_DBG("hcon %p", hcon);
686ebf283   Ulisses Furquim   Bluetooth: Make H...
4126
  	if (!conn)
9f5a0d7bf   Andrei Emeltchenko   Bluetooth: Define...
4127
  		return HCI_ERROR_REMOTE_USER_TERM;
2950f21ac   Marcel Holtmann   Bluetooth: Ask up...
4128
4129
  	return conn->disc_reason;
  }
686ebf283   Ulisses Furquim   Bluetooth: Make H...
4130
  int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4131
4132
  {
  	BT_DBG("hcon %p reason %d", hcon, reason);
e175072f3   Joe Perches   Bluetooth: Rename...
4133
  	l2cap_conn_del(hcon, bt_to_errno(reason));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4134
4135
  	return 0;
  }
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
4136
  static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
f62e4323a   Marcel Holtmann   Bluetooth: Discon...
4137
  {
715ec005c   Gustavo F. Padovan   Bluetooth: Add ch...
4138
  	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
255c76014   Marcel Holtmann   Bluetooth: Don't ...
4139
  		return;
f62e4323a   Marcel Holtmann   Bluetooth: Discon...
4140
  	if (encrypt == 0x00) {
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
4141
  		if (chan->sec_level == BT_SECURITY_MEDIUM) {
c9b666753   Gustavo F. Padovan   Bluetooth: Make t...
4142
  			__clear_chan_timer(chan);
f3f668b0e   Andrzej Kaczmarek   Bluetooth: Use mi...
4143
  			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
4144
  		} else if (chan->sec_level == BT_SECURITY_HIGH)
0f8527249   Gustavo F. Padovan   Bluetooth: Rename...
4145
  			l2cap_chan_close(chan, ECONNREFUSED);
f62e4323a   Marcel Holtmann   Bluetooth: Discon...
4146
  	} else {
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
4147
  		if (chan->sec_level == BT_SECURITY_MEDIUM)
c9b666753   Gustavo F. Padovan   Bluetooth: Make t...
4148
  			__clear_chan_timer(chan);
f62e4323a   Marcel Holtmann   Bluetooth: Discon...
4149
4150
  	}
  }
686ebf283   Ulisses Furquim   Bluetooth: Make H...
4151
  int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4152
  {
0139418c9   Marcel Holtmann   [Bluetooth] Small...
4153
  	struct l2cap_conn *conn = hcon->l2cap_data;
48454079c   Gustavo F. Padovan   Bluetooth: Create...
4154
  	struct l2cap_chan *chan;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4155

0139418c9   Marcel Holtmann   [Bluetooth] Small...
4156
  	if (!conn)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4157
  		return 0;
0139418c9   Marcel Holtmann   [Bluetooth] Small...
4158

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4159
  	BT_DBG("conn %p", conn);
160dc6ac1   Vinicius Costa Gomes   Bluetooth: Add su...
4160
4161
  	if (hcon->type == LE_LINK) {
  		smp_distribute_keys(conn, 0);
371fd8356   Ulisses Furquim   Bluetooth: Fix de...
4162
  		__cancel_delayed_work(&conn->security_timer);
160dc6ac1   Vinicius Costa Gomes   Bluetooth: Add su...
4163
  	}
3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
4164
  	rcu_read_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4165

3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
4166
  	list_for_each_entry_rcu(chan, &conn->chan_l, list) {
48454079c   Gustavo F. Padovan   Bluetooth: Create...
4167
  		struct sock *sk = chan->sk;
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
4168

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4169
  		bh_lock_sock(sk);
f1cb9af55   Vinicius Costa Gomes   Bluetooth: Add su...
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
  		BT_DBG("chan->scid %d", chan->scid);
  
  		if (chan->scid == L2CAP_CID_LE_DATA) {
  			if (!status && encrypt) {
  				chan->sec_level = hcon->sec_level;
  				l2cap_chan_ready(sk);
  			}
  
  			bh_unlock_sock(sk);
  			continue;
  		}
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
4181
  		if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
6a8d3010b   Marcel Holtmann   Bluetooth: Fix do...
4182
4183
4184
  			bh_unlock_sock(sk);
  			continue;
  		}
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
4185
4186
  		if (!status && (chan->state == BT_CONNECTED ||
  						chan->state == BT_CONFIG)) {
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
4187
  			l2cap_check_encryption(chan, encrypt);
9719f8afc   Marcel Holtmann   [Bluetooth] Disco...
4188
4189
4190
  			bh_unlock_sock(sk);
  			continue;
  		}
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
4191
  		if (chan->state == BT_CONNECT) {
b1235d796   Marcel Holtmann   [Bluetooth] Allow...
4192
4193
  			if (!status) {
  				struct l2cap_conn_req req;
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
4194
4195
  				req.scid = cpu_to_le16(chan->scid);
  				req.psm  = chan->psm;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4196

fc7f8a7ed   Gustavo F. Padovan   Bluetooth: Move i...
4197
  				chan->ident = l2cap_get_ident(conn);
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
4198
  				set_bit(CONF_CONNECT_PEND, &chan->conf_state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4199

fc7f8a7ed   Gustavo F. Padovan   Bluetooth: Move i...
4200
  				l2cap_send_cmd(conn, chan->ident,
b1235d796   Marcel Holtmann   [Bluetooth] Allow...
4201
4202
  					L2CAP_CONN_REQ, sizeof(req), &req);
  			} else {
c9b666753   Gustavo F. Padovan   Bluetooth: Make t...
4203
  				__clear_chan_timer(chan);
f3f668b0e   Andrzej Kaczmarek   Bluetooth: Use mi...
4204
  				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
b1235d796   Marcel Holtmann   [Bluetooth] Allow...
4205
  			}
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
4206
  		} else if (chan->state == BT_CONNECT2) {
b1235d796   Marcel Holtmann   [Bluetooth] Allow...
4207
  			struct l2cap_conn_rsp rsp;
df3c3931e   Johan Hedberg   Bluetooth: Fix ac...
4208
  			__u16 res, stat;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4209

b1235d796   Marcel Holtmann   [Bluetooth] Allow...
4210
  			if (!status) {
df3c3931e   Johan Hedberg   Bluetooth: Fix ac...
4211
4212
4213
4214
  				if (bt_sk(sk)->defer_setup) {
  					struct sock *parent = bt_sk(sk)->parent;
  					res = L2CAP_CR_PEND;
  					stat = L2CAP_CS_AUTHOR_PEND;
05e9a2f67   Ilia Kolomisnky   Bluetooth: Fix cr...
4215
4216
  					if (parent)
  						parent->sk_data_ready(parent, 0);
df3c3931e   Johan Hedberg   Bluetooth: Fix ac...
4217
  				} else {
055589118   Gustavo F. Padovan   Merge master.kern...
4218
  					l2cap_state_change(chan, BT_CONFIG);
df3c3931e   Johan Hedberg   Bluetooth: Fix ac...
4219
4220
4221
  					res = L2CAP_CR_SUCCESS;
  					stat = L2CAP_CS_NO_INFO;
  				}
b1235d796   Marcel Holtmann   [Bluetooth] Allow...
4222
  			} else {
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
4223
  				l2cap_state_change(chan, BT_DISCONN);
f3f668b0e   Andrzej Kaczmarek   Bluetooth: Use mi...
4224
  				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
df3c3931e   Johan Hedberg   Bluetooth: Fix ac...
4225
4226
  				res = L2CAP_CR_SEC_BLOCK;
  				stat = L2CAP_CS_NO_INFO;
b1235d796   Marcel Holtmann   [Bluetooth] Allow...
4227
  			}
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
4228
4229
  			rsp.scid   = cpu_to_le16(chan->dcid);
  			rsp.dcid   = cpu_to_le16(chan->scid);
df3c3931e   Johan Hedberg   Bluetooth: Fix ac...
4230
4231
  			rsp.result = cpu_to_le16(res);
  			rsp.status = cpu_to_le16(stat);
fc7f8a7ed   Gustavo F. Padovan   Bluetooth: Move i...
4232
4233
  			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
  							sizeof(rsp), &rsp);
b1235d796   Marcel Holtmann   [Bluetooth] Allow...
4234
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4235
4236
4237
  
  		bh_unlock_sock(sk);
  	}
3d57dc680   Gustavo F. Padovan   Bluetooth: Change...
4238
  	rcu_read_unlock();
b1235d796   Marcel Holtmann   [Bluetooth] Allow...
4239

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4240
4241
  	return 0;
  }
686ebf283   Ulisses Furquim   Bluetooth: Make H...
4242
  int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4243
4244
  {
  	struct l2cap_conn *conn = hcon->l2cap_data;
5a08ecced   Andrei Emeltchenko   Bluetooth: Do not...
4245
4246
4247
4248
  	if (!conn)
  		conn = l2cap_conn_add(hcon, 0);
  
  	if (!conn)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4249
4250
4251
  		goto drop;
  
  	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
e702112ff   Andrei Emeltchenko   Bluetooth: Use no...
4252
  	if (!(flags & ACL_CONT)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4253
  		struct l2cap_hdr *hdr;
48454079c   Gustavo F. Padovan   Bluetooth: Create...
4254
  		struct l2cap_chan *chan;
897948132   Andrei Emeltchenko   Bluetooth: check ...
4255
  		u16 cid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4256
4257
4258
4259
4260
4261
4262
4263
4264
  		int len;
  
  		if (conn->rx_len) {
  			BT_ERR("Unexpected start frame (len %d)", skb->len);
  			kfree_skb(conn->rx_skb);
  			conn->rx_skb = NULL;
  			conn->rx_len = 0;
  			l2cap_conn_unreliable(conn, ECOMM);
  		}
aae7fe22a   Andrei Emeltchenko   Bluetooth: check ...
4265
4266
  		/* Start fragment always begin with Basic L2CAP header */
  		if (skb->len < L2CAP_HDR_SIZE) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4267
4268
4269
4270
4271
4272
4273
  			BT_ERR("Frame is too short (len %d)", skb->len);
  			l2cap_conn_unreliable(conn, ECOMM);
  			goto drop;
  		}
  
  		hdr = (struct l2cap_hdr *) skb->data;
  		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
897948132   Andrei Emeltchenko   Bluetooth: check ...
4274
  		cid = __le16_to_cpu(hdr->cid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
  
  		if (len == skb->len) {
  			/* Complete frame received */
  			l2cap_recv_frame(conn, skb);
  			return 0;
  		}
  
  		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
  
  		if (skb->len > len) {
  			BT_ERR("Frame is too long (len %d, expected len %d)",
  				skb->len, len);
  			l2cap_conn_unreliable(conn, ECOMM);
  			goto drop;
  		}
baa7e1fa6   Gustavo F. Padovan   Bluetooth: Use st...
4290
  		chan = l2cap_get_chan_by_scid(conn, cid);
897948132   Andrei Emeltchenko   Bluetooth: check ...
4291

48454079c   Gustavo F. Padovan   Bluetooth: Create...
4292
4293
  		if (chan && chan->sk) {
  			struct sock *sk = chan->sk;
897948132   Andrei Emeltchenko   Bluetooth: check ...
4294

0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
4295
  			if (chan->imtu < len - L2CAP_HDR_SIZE) {
48454079c   Gustavo F. Padovan   Bluetooth: Create...
4296
4297
  				BT_ERR("Frame exceeding recv MTU (len %d, "
  							"MTU %d)", len,
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
4298
  							chan->imtu);
aa2ac881b   Gustavo F. Padovan   Bluetooth: Don't ...
4299
  				release_sock(sk);
48454079c   Gustavo F. Padovan   Bluetooth: Create...
4300
4301
4302
  				l2cap_conn_unreliable(conn, ECOMM);
  				goto drop;
  			}
aa2ac881b   Gustavo F. Padovan   Bluetooth: Don't ...
4303
  			release_sock(sk);
48454079c   Gustavo F. Padovan   Bluetooth: Create...
4304
  		}
897948132   Andrei Emeltchenko   Bluetooth: check ...
4305

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4306
  		/* Allocate skb for the complete frame (with header) */
af05b30bc   Gustavo F. Padovan   Bluetooth: Fix er...
4307
4308
  		conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
  		if (!conn->rx_skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4309
  			goto drop;
d626f62b1   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
4310
  		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
e1027a7c6   Marcel Holtmann   Bluetooth: Reques...
4311
  								skb->len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
  		conn->rx_len = len - skb->len;
  	} else {
  		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
  
  		if (!conn->rx_len) {
  			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
  			l2cap_conn_unreliable(conn, ECOMM);
  			goto drop;
  		}
  
  		if (skb->len > conn->rx_len) {
  			BT_ERR("Fragment is too long (len %d, expected %d)",
  					skb->len, conn->rx_len);
  			kfree_skb(conn->rx_skb);
  			conn->rx_skb = NULL;
  			conn->rx_len = 0;
  			l2cap_conn_unreliable(conn, ECOMM);
  			goto drop;
  		}
d626f62b1   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
4331
  		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
e1027a7c6   Marcel Holtmann   Bluetooth: Reques...
4332
  								skb->len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
  		conn->rx_len -= skb->len;
  
  		if (!conn->rx_len) {
  			/* Complete frame received */
  			l2cap_recv_frame(conn, conn->rx_skb);
  			conn->rx_skb = NULL;
  		}
  	}
  
  drop:
  	kfree_skb(skb);
  	return 0;
  }
aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
4346
  static int l2cap_debugfs_show(struct seq_file *f, void *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4347
  {
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
4348
  	struct l2cap_chan *c;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4349

333055f2a   Gustavo F. Padovan   Bluetooth: Don't ...
4350
  	read_lock(&chan_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4351

23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
4352
4353
  	list_for_each_entry(c, &chan_list, global_l) {
  		struct sock *sk = c->sk;
101545f6f   Marcel Holtmann   Bluetooth: Fix po...
4354

903d343e2   Gustavo F. Padovan   Bluetooth: Add L2...
4355
4356
  		seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d
  ",
aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
4357
4358
  					batostr(&bt_sk(sk)->src),
  					batostr(&bt_sk(sk)->dst),
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
4359
  					c->state, __le16_to_cpu(c->psm),
23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
4360
4361
  					c->scid, c->dcid, c->imtu, c->omtu,
  					c->sec_level, c->mode);
055589118   Gustavo F. Padovan   Merge master.kern...
4362
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4363

333055f2a   Gustavo F. Padovan   Bluetooth: Don't ...
4364
  	read_unlock(&chan_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4365

aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
4366
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4367
  }
aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
  static int l2cap_debugfs_open(struct inode *inode, struct file *file)
  {
  	return single_open(file, l2cap_debugfs_show, inode->i_private);
  }
  
  static const struct file_operations l2cap_debugfs_fops = {
  	.open		= l2cap_debugfs_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= single_release,
  };
  
  static struct dentry *l2cap_debugfs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4381

642745184   Gustavo F. Padovan   Bluetooth: Merge ...
4382
  int __init l2cap_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4383
4384
  {
  	int err;
be9d12273   Marcel Holtmann   [Bluetooth]: Remo...
4385

bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
4386
  	err = l2cap_init_sockets();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4387
4388
  	if (err < 0)
  		return err;
aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
4389
4390
4391
4392
4393
4394
  	if (bt_debugfs) {
  		l2cap_debugfs = debugfs_create_file("l2cap", 0444,
  					bt_debugfs, NULL, &l2cap_debugfs_fops);
  		if (!l2cap_debugfs)
  			BT_ERR("Failed to create L2CAP debug file");
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4395

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4396
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4397
  }
642745184   Gustavo F. Padovan   Bluetooth: Merge ...
4398
  void l2cap_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4399
  {
aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
4400
  	debugfs_remove(l2cap_debugfs);
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
4401
  	l2cap_cleanup_sockets();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4402
  }
d1c4a17d5   Gustavo F. Padovan   Bluetooth: Enable...
4403
4404
  module_param(disable_ertm, bool, 0644);
  MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");