blob: 7264119b64a65265350c8a1f5d7e6401cf648cce [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006
7 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation;
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
16 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090017 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
18 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090022 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
23 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 SOFTWARE IS DISCLAIMED.
25*/
26
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020027/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30
31#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080032#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/errno.h>
34#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/sched.h>
36#include <linux/slab.h>
37#include <linux/poll.h>
38#include <linux/fcntl.h>
39#include <linux/init.h>
40#include <linux/interrupt.h>
41#include <linux/socket.h>
42#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080044#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010045#include <linux/debugfs.h>
46#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030047#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030048#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <net/sock.h>
50
51#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
57
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020058int disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020059
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070060static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010061static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030063static struct workqueue_struct *_busy_wq;
64
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020065struct bt_sock_list l2cap_sk_list = {
Robert P. J. Dayd5fb2962008-03-28 16:17:38 -070066 .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070067};
68
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030069static void l2cap_busy_work(struct work_struct *work);
70
Linus Torvalds1da177e2005-04-16 15:20:36 -070071static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
72 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -030073static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030075static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
76
Marcel Holtmann01394182006-07-03 10:02:46 +020077/* ---- L2CAP channels ---- */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030078static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020079{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030080 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030081
82 list_for_each_entry(c, &conn->chan_l, list) {
83 struct sock *s = c->sk;
84 if (l2cap_pi(s)->dcid == cid)
85 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020086 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030087 return NULL;
88
Marcel Holtmann01394182006-07-03 10:02:46 +020089}
90
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030091static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020092{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030093 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030094
95 list_for_each_entry(c, &conn->chan_l, list) {
96 struct sock *s = c->sk;
97 if (l2cap_pi(s)->scid == cid)
98 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020099 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300100 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200101}
102
103/* Find channel with given SCID.
104 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300105static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200106{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300107 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300108
109 read_lock(&conn->chan_lock);
110 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300111 if (c)
112 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300113 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300114 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200115}
116
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300117static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200118{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300119 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300120
121 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300122 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300123 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200124 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300125 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200126}
127
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300128static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200129{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300130 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300131
132 read_lock(&conn->chan_lock);
133 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300134 if (c)
135 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300136 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300137 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200138}
139
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300140static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200141{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300142 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200143
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300144 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300145 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200146 return cid;
147 }
148
149 return 0;
150}
151
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300152static struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200153{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300154 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200155
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300156 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
157 if (!chan)
158 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200159
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300160 chan->sk = sk;
161
162 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200163}
164
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300165static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200166{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300167 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200168
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300169 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
170 l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200171
Marcel Holtmann2950f212009-02-12 14:02:50 +0100172 conn->disc_reason = 0x13;
173
Marcel Holtmann01394182006-07-03 10:02:46 +0200174 l2cap_pi(sk)->conn = conn;
175
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300176 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Ville Tervob62f3282011-02-10 22:38:50 -0300177 if (conn->hcon->type == LE_LINK) {
178 /* LE connection */
179 l2cap_pi(sk)->omtu = L2CAP_LE_DEFAULT_MTU;
180 l2cap_pi(sk)->scid = L2CAP_CID_LE_DATA;
181 l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA;
182 } else {
183 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300184 l2cap_pi(sk)->scid = l2cap_alloc_cid(conn);
Ville Tervob62f3282011-02-10 22:38:50 -0300185 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
186 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200187 } else if (sk->sk_type == SOCK_DGRAM) {
188 /* Connectionless socket */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300189 l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
190 l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
Marcel Holtmann01394182006-07-03 10:02:46 +0200191 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
192 } else {
193 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300194 l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
195 l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
Marcel Holtmann01394182006-07-03 10:02:46 +0200196 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
197 }
198
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300199 sock_hold(sk);
200
201 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200202}
203
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900204/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200205 * Must be called on the locked socket. */
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300206void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200207{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300208 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200209 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
210 struct sock *parent = bt_sk(sk)->parent;
211
212 l2cap_sock_clear_timer(sk);
213
214 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
215
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900216 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300217 /* Delete from channel list */
218 write_lock_bh(&conn->chan_lock);
219 list_del(&chan->list);
220 write_unlock_bh(&conn->chan_lock);
221 __sock_put(sk);
222
Marcel Holtmann01394182006-07-03 10:02:46 +0200223 l2cap_pi(sk)->conn = NULL;
224 hci_conn_put(conn->hcon);
225 }
226
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200227 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200228 sock_set_flag(sk, SOCK_ZAPPED);
229
230 if (err)
231 sk->sk_err = err;
232
233 if (parent) {
234 bt_accept_unlink(sk);
235 parent->sk_data_ready(parent, 0);
236 } else
237 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300238
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300239 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE &&
240 l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE))
241 goto free;
242
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300243 skb_queue_purge(TX_QUEUE(sk));
244
245 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
246 struct srej_list *l, *tmp;
247
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300248 del_timer(&chan->retrans_timer);
249 del_timer(&chan->monitor_timer);
250 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300251
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300252 skb_queue_purge(&chan->srej_q);
253 skb_queue_purge(&chan->busy_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300254
255 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
256 list_del(&l->list);
257 kfree(l);
258 }
259 }
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300260
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300261free:
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300262 kfree(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200263}
264
Johan Hedberg8556edd32011-01-19 12:06:50 +0530265static inline u8 l2cap_get_auth_type(struct sock *sk)
266{
267 if (sk->sk_type == SOCK_RAW) {
268 switch (l2cap_pi(sk)->sec_level) {
269 case BT_SECURITY_HIGH:
270 return HCI_AT_DEDICATED_BONDING_MITM;
271 case BT_SECURITY_MEDIUM:
272 return HCI_AT_DEDICATED_BONDING;
273 default:
274 return HCI_AT_NO_BONDING;
275 }
276 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
277 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
278 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
279
280 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
281 return HCI_AT_NO_BONDING_MITM;
282 else
283 return HCI_AT_NO_BONDING;
284 } else {
285 switch (l2cap_pi(sk)->sec_level) {
286 case BT_SECURITY_HIGH:
287 return HCI_AT_GENERAL_BONDING_MITM;
288 case BT_SECURITY_MEDIUM:
289 return HCI_AT_GENERAL_BONDING;
290 default:
291 return HCI_AT_NO_BONDING;
292 }
293 }
294}
295
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200296/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100297static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200298{
299 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100300 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200301
Johan Hedberg8556edd32011-01-19 12:06:50 +0530302 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100303
304 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
305 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200306}
307
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200308u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200309{
310 u8 id;
311
312 /* Get next available identificator.
313 * 1 - 128 are used by kernel.
314 * 129 - 199 are reserved.
315 * 200 - 254 are used by utilities like l2ping, etc.
316 */
317
318 spin_lock_bh(&conn->lock);
319
320 if (++conn->tx_ident > 128)
321 conn->tx_ident = 1;
322
323 id = conn->tx_ident;
324
325 spin_unlock_bh(&conn->lock);
326
327 return id;
328}
329
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200330void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200331{
332 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200333 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200334
335 BT_DBG("code 0x%2.2x", code);
336
337 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300338 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200339
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200340 if (lmp_no_flush_capable(conn->hcon->hdev))
341 flags = ACL_START_NO_FLUSH;
342 else
343 flags = ACL_START;
344
345 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200346}
347
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300348static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300349{
350 struct sk_buff *skb;
351 struct l2cap_hdr *lh;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300352 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300353 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300354 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300355 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200356 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300357
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300358 if (sk->sk_state != BT_CONNECTED)
359 return;
360
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300361 if (pi->fcs == L2CAP_FCS_CRC16)
362 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300363
364 BT_DBG("pi %p, control 0x%2.2x", pi, control);
365
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300366 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300367 control |= L2CAP_CTRL_FRAME_TYPE;
368
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300369 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300370 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300371 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300372 }
373
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300374 if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300375 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300376 chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300377 }
378
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300379 skb = bt_skb_alloc(count, GFP_ATOMIC);
380 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300381 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300382
383 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300384 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300385 lh->cid = cpu_to_le16(pi->dcid);
386 put_unaligned_le16(control, skb_put(skb, 2));
387
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300388 if (pi->fcs == L2CAP_FCS_CRC16) {
389 u16 fcs = crc16(0, (u8 *)lh, count - 2);
390 put_unaligned_le16(fcs, skb_put(skb, 2));
391 }
392
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200393 if (lmp_no_flush_capable(conn->hcon->hdev))
394 flags = ACL_START_NO_FLUSH;
395 else
396 flags = ACL_START;
397
398 hci_send_acl(pi->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300399}
400
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300401static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300402{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300403 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300404 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300405 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300406 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300407 control |= L2CAP_SUPER_RCV_READY;
408
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300409 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300410
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300411 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300412}
413
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300414static inline int __l2cap_no_conn_pending(struct sock *sk)
415{
416 return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
417}
418
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300419static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200420{
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300421 struct sock *sk = chan->sk;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200422 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
423
424 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100425 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
426 return;
427
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300428 if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200429 struct l2cap_conn_req req;
430 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
431 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200432
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300433 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300434 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200435
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300436 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
437 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200438 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200439 } else {
440 struct l2cap_info_req req;
441 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
442
443 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
444 conn->info_ident = l2cap_get_ident(conn);
445
446 mod_timer(&conn->info_timer, jiffies +
447 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
448
449 l2cap_send_cmd(conn, conn->info_ident,
450 L2CAP_INFO_REQ, sizeof(req), &req);
451 }
452}
453
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300454static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
455{
456 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300457 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300458 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
459
460 switch (mode) {
461 case L2CAP_MODE_ERTM:
462 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
463 case L2CAP_MODE_STREAMING:
464 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
465 default:
466 return 0x00;
467 }
468}
469
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300470void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300471{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300472 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300473 struct l2cap_disconn_req req;
474
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300475 if (!conn)
476 return;
477
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300478 sk = chan->sk;
479
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300480 skb_queue_purge(TX_QUEUE(sk));
481
482 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300483 del_timer(&chan->retrans_timer);
484 del_timer(&chan->monitor_timer);
485 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300486 }
487
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300488 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
489 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
490 l2cap_send_cmd(conn, l2cap_get_ident(conn),
491 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300492
493 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300494 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300495}
496
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200498static void l2cap_conn_start(struct l2cap_conn *conn)
499{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300500 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200501
502 BT_DBG("conn %p", conn);
503
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300504 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200505
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300506 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300507 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300508
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200509 bh_lock_sock(sk);
510
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300511 if (sk->sk_type != SOCK_SEQPACKET &&
512 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200513 bh_unlock_sock(sk);
514 continue;
515 }
516
517 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300518 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300519
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300520 if (!l2cap_check_security(sk) ||
521 !__l2cap_no_conn_pending(sk)) {
522 bh_unlock_sock(sk);
523 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200524 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300525
526 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
527 conn->feat_mask)
528 && l2cap_pi(sk)->conf_state &
529 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300530 /* __l2cap_sock_close() calls list_del(chan)
531 * so release the lock */
532 read_unlock_bh(&conn->chan_lock);
533 __l2cap_sock_close(sk, ECONNRESET);
534 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300535 bh_unlock_sock(sk);
536 continue;
537 }
538
539 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
540 req.psm = l2cap_pi(sk)->psm;
541
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300542 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300543 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
544
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300545 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
546 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300547
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200548 } else if (sk->sk_state == BT_CONNECT2) {
549 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300550 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200551 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
552 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
553
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100554 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100555 if (bt_sk(sk)->defer_setup) {
556 struct sock *parent = bt_sk(sk)->parent;
557 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
558 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
559 parent->sk_data_ready(parent, 0);
560
561 } else {
562 sk->sk_state = BT_CONFIG;
563 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
564 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
565 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200566 } else {
567 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
568 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
569 }
570
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300571 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
572 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300573
574 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
575 rsp.result != L2CAP_CR_SUCCESS) {
576 bh_unlock_sock(sk);
577 continue;
578 }
579
580 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
581 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300582 l2cap_build_conf_req(chan, buf), buf);
583 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200584 }
585
586 bh_unlock_sock(sk);
587 }
588
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300589 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200590}
591
Ville Tervob62f3282011-02-10 22:38:50 -0300592/* Find socket with cid and source bdaddr.
593 * Returns closest match, locked.
594 */
595static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
596{
597 struct sock *s, *sk = NULL, *sk1 = NULL;
598 struct hlist_node *node;
599
600 read_lock(&l2cap_sk_list.lock);
601
602 sk_for_each(sk, node, &l2cap_sk_list.head) {
603 if (state && sk->sk_state != state)
604 continue;
605
606 if (l2cap_pi(sk)->scid == cid) {
607 /* Exact match. */
608 if (!bacmp(&bt_sk(sk)->src, src))
609 break;
610
611 /* Closest match */
612 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
613 sk1 = sk;
614 }
615 }
616 s = node ? sk : sk1;
617 if (s)
618 bh_lock_sock(s);
619 read_unlock(&l2cap_sk_list.lock);
620
621 return s;
622}
623
624static void l2cap_le_conn_ready(struct l2cap_conn *conn)
625{
Ville Tervob62f3282011-02-10 22:38:50 -0300626 struct sock *parent, *uninitialized_var(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300627 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300628
629 BT_DBG("");
630
631 /* Check if we have socket listening on cid */
632 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
633 conn->src);
634 if (!parent)
635 return;
636
637 /* Check for backlog size */
638 if (sk_acceptq_is_full(parent)) {
639 BT_DBG("backlog full %d", parent->sk_ack_backlog);
640 goto clean;
641 }
642
643 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
644 if (!sk)
645 goto clean;
646
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300647 chan = l2cap_chan_alloc(sk);
648 if (!chan) {
649 l2cap_sock_kill(sk);
650 goto clean;
651 }
652
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300653 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300654
655 hci_conn_hold(conn->hcon);
656
657 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300658
Ville Tervob62f3282011-02-10 22:38:50 -0300659 bacpy(&bt_sk(sk)->src, conn->src);
660 bacpy(&bt_sk(sk)->dst, conn->dst);
661
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300662 bt_accept_enqueue(parent, sk);
663
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300664 __l2cap_chan_add(conn, chan);
665
666 l2cap_pi(sk)->chan = chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300667
668 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
669
670 sk->sk_state = BT_CONNECTED;
671 parent->sk_data_ready(parent, 0);
672
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300673 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300674
675clean:
676 bh_unlock_sock(parent);
677}
678
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200679static void l2cap_conn_ready(struct l2cap_conn *conn)
680{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300681 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200682
683 BT_DBG("conn %p", conn);
684
Ville Tervob62f3282011-02-10 22:38:50 -0300685 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
686 l2cap_le_conn_ready(conn);
687
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300688 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200689
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300690 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300691 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300692
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200693 bh_lock_sock(sk);
694
Ville Tervoacd7d372011-02-10 22:38:49 -0300695 if (conn->hcon->type == LE_LINK) {
696 l2cap_sock_clear_timer(sk);
697 sk->sk_state = BT_CONNECTED;
698 sk->sk_state_change(sk);
699 }
700
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300701 if (sk->sk_type != SOCK_SEQPACKET &&
702 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200703 l2cap_sock_clear_timer(sk);
704 sk->sk_state = BT_CONNECTED;
705 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200706 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300707 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200708
709 bh_unlock_sock(sk);
710 }
711
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300712 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200713}
714
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200715/* Notify sockets that we cannot guaranty reliability anymore */
716static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
717{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300718 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200719
720 BT_DBG("conn %p", conn);
721
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300722 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200723
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300724 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300725 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300726
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100727 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200728 sk->sk_err = err;
729 }
730
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300731 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200732}
733
734static void l2cap_info_timeout(unsigned long arg)
735{
736 struct l2cap_conn *conn = (void *) arg;
737
Marcel Holtmann984947d2009-02-06 23:35:19 +0100738 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100739 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100740
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200741 l2cap_conn_start(conn);
742}
743
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
745{
Marcel Holtmann01394182006-07-03 10:02:46 +0200746 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747
Marcel Holtmann01394182006-07-03 10:02:46 +0200748 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 return conn;
750
Marcel Holtmann01394182006-07-03 10:02:46 +0200751 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
752 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
755 hcon->l2cap_data = conn;
756 conn->hcon = hcon;
757
Marcel Holtmann01394182006-07-03 10:02:46 +0200758 BT_DBG("hcon %p conn %p", hcon, conn);
759
Ville Tervoacd7d372011-02-10 22:38:49 -0300760 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
761 conn->mtu = hcon->hdev->le_mtu;
762 else
763 conn->mtu = hcon->hdev->acl_mtu;
764
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 conn->src = &hcon->hdev->bdaddr;
766 conn->dst = &hcon->dst;
767
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200768 conn->feat_mask = 0;
769
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300771 rwlock_init(&conn->chan_lock);
772
773 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774
Ville Tervob62f3282011-02-10 22:38:50 -0300775 if (hcon->type != LE_LINK)
776 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000777 (unsigned long) conn);
778
Marcel Holtmann2950f212009-02-12 14:02:50 +0100779 conn->disc_reason = 0x13;
780
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 return conn;
782}
783
Marcel Holtmann01394182006-07-03 10:02:46 +0200784static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785{
Marcel Holtmann01394182006-07-03 10:02:46 +0200786 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300787 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 struct sock *sk;
789
Marcel Holtmann01394182006-07-03 10:02:46 +0200790 if (!conn)
791 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
793 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
794
Wei Yongjun7585b972009-02-25 18:29:52 +0800795 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796
797 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300798 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300799 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300801 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 bh_unlock_sock(sk);
803 l2cap_sock_kill(sk);
804 }
805
Dave Young8e8440f2008-03-03 12:18:55 -0800806 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
807 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800808
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 hcon->l2cap_data = NULL;
810 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811}
812
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300813static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300815 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300816 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300817 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818}
819
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
822/* Find socket with psm and source bdaddr.
823 * Returns closest match.
824 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000825static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826{
827 struct sock *sk = NULL, *sk1 = NULL;
828 struct hlist_node *node;
829
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000830 read_lock(&l2cap_sk_list.lock);
831
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 sk_for_each(sk, node, &l2cap_sk_list.head) {
833 if (state && sk->sk_state != state)
834 continue;
835
836 if (l2cap_pi(sk)->psm == psm) {
837 /* Exact match. */
838 if (!bacmp(&bt_sk(sk)->src, src))
839 break;
840
841 /* Closest match */
842 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
843 sk1 = sk;
844 }
845 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000848
849 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850}
851
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200852int l2cap_do_connect(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853{
854 bdaddr_t *src = &bt_sk(sk)->src;
855 bdaddr_t *dst = &bt_sk(sk)->dst;
856 struct l2cap_conn *conn;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300857 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 struct hci_conn *hcon;
859 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200860 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200861 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100863 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
864 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300866 hdev = hci_get_route(dst, src);
867 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 return -EHOSTUNREACH;
869
870 hci_dev_lock_bh(hdev);
871
Johan Hedberg8556edd32011-01-19 12:06:50 +0530872 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200873
Ville Tervoacd7d372011-02-10 22:38:49 -0300874 if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
875 hcon = hci_connect(hdev, LE_LINK, dst,
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100876 l2cap_pi(sk)->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300877 else
878 hcon = hci_connect(hdev, ACL_LINK, dst,
879 l2cap_pi(sk)->sec_level, auth_type);
880
Ville Tervo30e76272011-02-22 16:10:53 -0300881 if (IS_ERR(hcon)) {
882 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300884 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885
886 conn = l2cap_conn_add(hcon, 0);
887 if (!conn) {
888 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300889 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 goto done;
891 }
892
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300893 chan = l2cap_chan_alloc(sk);
894 if (!chan) {
895 hci_conn_put(hcon);
896 err = -ENOMEM;
897 goto done;
898 }
899
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 /* Update source addr of the socket */
901 bacpy(src, conn->src);
902
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300903 l2cap_chan_add(conn, chan);
904
905 l2cap_pi(sk)->chan = chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906
907 sk->sk_state = BT_CONNECT;
908 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
909
910 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300911 if (sk->sk_type != SOCK_SEQPACKET &&
912 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530914 if (l2cap_check_security(sk))
915 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200916 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300917 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 }
919
Ville Tervo30e76272011-02-22 16:10:53 -0300920 err = 0;
921
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922done:
923 hci_dev_unlock_bh(hdev);
924 hci_dev_put(hdev);
925 return err;
926}
927
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200928int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300929{
930 DECLARE_WAITQUEUE(wait, current);
931 int err = 0;
932 int timeo = HZ/5;
933
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200934 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300935 while ((l2cap_pi(sk)->chan->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300936 set_current_state(TASK_INTERRUPTIBLE);
937
938 if (!timeo)
939 timeo = HZ/5;
940
941 if (signal_pending(current)) {
942 err = sock_intr_errno(timeo);
943 break;
944 }
945
946 release_sock(sk);
947 timeo = schedule_timeout(timeo);
948 lock_sock(sk);
949
950 err = sock_error(sk);
951 if (err)
952 break;
953 }
954 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200955 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300956 return err;
957}
958
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300959static void l2cap_monitor_timeout(unsigned long arg)
960{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300961 struct l2cap_chan *chan = (void *) arg;
962 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300963
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300964 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300965
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300966 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -0300967 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300968 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200969 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300970 return;
971 }
972
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300973 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300974 __mod_monitor_timer();
975
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300976 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300977 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300978}
979
980static void l2cap_retrans_timeout(unsigned long arg)
981{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300982 struct l2cap_chan *chan = (void *) arg;
983 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300984
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300985 BT_DBG("sk %p", sk);
986
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300987 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300988 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300989 __mod_monitor_timer();
990
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300991 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300992
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300993 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300994 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300995}
996
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300997static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300998{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300999 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001000 struct sk_buff *skb;
1001
Gustavo F. Padovan812e7372010-05-01 16:15:42 -03001002 while ((skb = skb_peek(TX_QUEUE(sk))) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001003 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001004 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001005 break;
1006
1007 skb = skb_dequeue(TX_QUEUE(sk));
1008 kfree_skb(skb);
1009
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001010 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001011 }
1012
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001013 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001014 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001015}
1016
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001017void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001018{
1019 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001020 struct hci_conn *hcon = pi->conn->hcon;
1021 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001022
1023 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1024
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001025 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
1026 flags = ACL_START_NO_FLUSH;
1027 else
1028 flags = ACL_START;
1029
1030 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001031}
1032
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001033void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001034{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001035 struct sock *sk = chan->sk;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001036 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001037 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001038 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001039
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001040 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
1041 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001042 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001043 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001044
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001045 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001046 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1047 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001048 }
1049
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001050 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001051
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001052 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001053 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001054}
1055
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001056static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001057{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001058 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001059 struct l2cap_pinfo *pi = l2cap_pi(sk);
1060 struct sk_buff *skb, *tx_skb;
1061 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001062
1063 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001064 if (!skb)
1065 return;
1066
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001067 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001068 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001069 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001070
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001071 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1072 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001073
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001074 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001075
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001076 if (chan->remote_max_tx &&
1077 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001078 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001079 return;
1080 }
1081
1082 tx_skb = skb_clone(skb, GFP_ATOMIC);
1083 bt_cb(skb)->retries++;
1084 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001085
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001086 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001087 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001088 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001089 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001090
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001091 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001092 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001093
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001094 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1095
1096 if (pi->fcs == L2CAP_FCS_CRC16) {
1097 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1098 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1099 }
1100
1101 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001102}
1103
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001104int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001105{
1106 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001107 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001108 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001109 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001110 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001111
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001112 if (sk->sk_state != BT_CONNECTED)
1113 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001114
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001115 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001116
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001117 if (chan->remote_max_tx &&
1118 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001119 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001120 break;
1121 }
1122
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001123 tx_skb = skb_clone(skb, GFP_ATOMIC);
1124
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001125 bt_cb(skb)->retries++;
1126
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001127 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001128 control &= L2CAP_CTRL_SAR;
1129
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001130 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001131 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001132 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001133 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001134 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1135 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001136 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1137
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001138
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001139 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001140 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1141 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1142 }
1143
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001144 l2cap_do_send(sk, tx_skb);
1145
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001146 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001147
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001148 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1149 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001150
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301151 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001152 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301153
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001154 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001155
1156 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1157 sk->sk_send_head = NULL;
1158 else
1159 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001160
1161 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001162 }
1163
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001164 return nsent;
1165}
1166
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001167static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001168{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001169 struct sock *sk = chan->sk;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001170 int ret;
1171
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001172 if (!skb_queue_empty(TX_QUEUE(sk)))
1173 sk->sk_send_head = TX_QUEUE(sk)->next;
1174
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001175 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001176 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001177 return ret;
1178}
1179
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001180static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001181{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001182 u16 control = 0;
1183
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001184 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001185
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001186 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001187 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001188 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1189 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001190 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001191 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001192
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001193 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001194 return;
1195
1196 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001197 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001198}
1199
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001200static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001201{
1202 struct srej_list *tail;
1203 u16 control;
1204
1205 control = L2CAP_SUPER_SELECT_REJECT;
1206 control |= L2CAP_CTRL_FINAL;
1207
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001208 tail = list_entry(SREJ_LIST(chan->sk)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001209 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1210
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001211 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001212}
1213
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001214static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215{
1216 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001217 struct sk_buff **frag;
1218 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001220 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001221 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222
1223 sent += count;
1224 len -= count;
1225
1226 /* Continuation fragments (no L2CAP header) */
1227 frag = &skb_shinfo(skb)->frag_list;
1228 while (len) {
1229 count = min_t(unsigned int, conn->mtu, len);
1230
1231 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1232 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001233 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001234 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1235 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236
1237 sent += count;
1238 len -= count;
1239
1240 frag = &(*frag)->next;
1241 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242
1243 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001244}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001246struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001247{
1248 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1249 struct sk_buff *skb;
1250 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1251 struct l2cap_hdr *lh;
1252
1253 BT_DBG("sk %p len %d", sk, (int)len);
1254
1255 count = min_t(unsigned int, (conn->mtu - hlen), len);
1256 skb = bt_skb_send_alloc(sk, count + hlen,
1257 msg->msg_flags & MSG_DONTWAIT, &err);
1258 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001259 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001260
1261 /* Create L2CAP header */
1262 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1263 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1264 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1265 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1266
1267 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1268 if (unlikely(err < 0)) {
1269 kfree_skb(skb);
1270 return ERR_PTR(err);
1271 }
1272 return skb;
1273}
1274
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001275struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001276{
1277 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1278 struct sk_buff *skb;
1279 int err, count, hlen = L2CAP_HDR_SIZE;
1280 struct l2cap_hdr *lh;
1281
1282 BT_DBG("sk %p len %d", sk, (int)len);
1283
1284 count = min_t(unsigned int, (conn->mtu - hlen), len);
1285 skb = bt_skb_send_alloc(sk, count + hlen,
1286 msg->msg_flags & MSG_DONTWAIT, &err);
1287 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001288 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001289
1290 /* Create L2CAP header */
1291 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1292 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1293 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1294
1295 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1296 if (unlikely(err < 0)) {
1297 kfree_skb(skb);
1298 return ERR_PTR(err);
1299 }
1300 return skb;
1301}
1302
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001303struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001304{
1305 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1306 struct sk_buff *skb;
1307 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1308 struct l2cap_hdr *lh;
1309
1310 BT_DBG("sk %p len %d", sk, (int)len);
1311
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001312 if (!conn)
1313 return ERR_PTR(-ENOTCONN);
1314
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001315 if (sdulen)
1316 hlen += 2;
1317
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001318 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1319 hlen += 2;
1320
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001321 count = min_t(unsigned int, (conn->mtu - hlen), len);
1322 skb = bt_skb_send_alloc(sk, count + hlen,
1323 msg->msg_flags & MSG_DONTWAIT, &err);
1324 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001325 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001326
1327 /* Create L2CAP header */
1328 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1329 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1330 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1331 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001332 if (sdulen)
1333 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001334
1335 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1336 if (unlikely(err < 0)) {
1337 kfree_skb(skb);
1338 return ERR_PTR(err);
1339 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001340
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001341 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1342 put_unaligned_le16(0, skb_put(skb, 2));
1343
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001344 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001345 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346}
1347
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001348int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001349{
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001350 struct sock *sk = chan->sk;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001351 struct sk_buff *skb;
1352 struct sk_buff_head sar_queue;
1353 u16 control;
1354 size_t size = 0;
1355
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001356 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001357 control = L2CAP_SDU_START;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001358 skb = l2cap_create_iframe_pdu(sk, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001359 if (IS_ERR(skb))
1360 return PTR_ERR(skb);
1361
1362 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001363 len -= chan->remote_mps;
1364 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001365
1366 while (len > 0) {
1367 size_t buflen;
1368
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001369 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001370 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001371 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001372 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001373 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001374 buflen = len;
1375 }
1376
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001377 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001378 if (IS_ERR(skb)) {
1379 skb_queue_purge(&sar_queue);
1380 return PTR_ERR(skb);
1381 }
1382
1383 __skb_queue_tail(&sar_queue, skb);
1384 len -= buflen;
1385 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001386 }
1387 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1388 if (sk->sk_send_head == NULL)
1389 sk->sk_send_head = sar_queue.next;
1390
1391 return size;
1392}
1393
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394static void l2cap_chan_ready(struct sock *sk)
1395{
1396 struct sock *parent = bt_sk(sk)->parent;
1397
1398 BT_DBG("sk %p, parent %p", sk, parent);
1399
1400 l2cap_pi(sk)->conf_state = 0;
1401 l2cap_sock_clear_timer(sk);
1402
1403 if (!parent) {
1404 /* Outgoing channel.
1405 * Wake up socket sleeping on connect.
1406 */
1407 sk->sk_state = BT_CONNECTED;
1408 sk->sk_state_change(sk);
1409 } else {
1410 /* Incoming channel.
1411 * Wake up socket sleeping on accept.
1412 */
1413 parent->sk_data_ready(parent, 0);
1414 }
1415}
1416
1417/* Copy frame to all raw sockets on that connection */
1418static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1419{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001421 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422
1423 BT_DBG("conn %p", conn);
1424
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001425 read_lock(&conn->chan_lock);
1426 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001427 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 if (sk->sk_type != SOCK_RAW)
1429 continue;
1430
1431 /* Don't send frame to the socket it came from */
1432 if (skb->sk == sk)
1433 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001434 nskb = skb_clone(skb, GFP_ATOMIC);
1435 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 continue;
1437
1438 if (sock_queue_rcv_skb(sk, nskb))
1439 kfree_skb(nskb);
1440 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001441 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442}
1443
1444/* ---- L2CAP signalling commands ---- */
1445static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1446 u8 code, u8 ident, u16 dlen, void *data)
1447{
1448 struct sk_buff *skb, **frag;
1449 struct l2cap_cmd_hdr *cmd;
1450 struct l2cap_hdr *lh;
1451 int len, count;
1452
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001453 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1454 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455
1456 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1457 count = min_t(unsigned int, conn->mtu, len);
1458
1459 skb = bt_skb_alloc(count, GFP_ATOMIC);
1460 if (!skb)
1461 return NULL;
1462
1463 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001464 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001465
1466 if (conn->hcon->type == LE_LINK)
1467 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1468 else
1469 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
1471 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1472 cmd->code = code;
1473 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001474 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475
1476 if (dlen) {
1477 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1478 memcpy(skb_put(skb, count), data, count);
1479 data += count;
1480 }
1481
1482 len -= skb->len;
1483
1484 /* Continuation fragments (no L2CAP header) */
1485 frag = &skb_shinfo(skb)->frag_list;
1486 while (len) {
1487 count = min_t(unsigned int, conn->mtu, len);
1488
1489 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1490 if (!*frag)
1491 goto fail;
1492
1493 memcpy(skb_put(*frag, count), data, count);
1494
1495 len -= count;
1496 data += count;
1497
1498 frag = &(*frag)->next;
1499 }
1500
1501 return skb;
1502
1503fail:
1504 kfree_skb(skb);
1505 return NULL;
1506}
1507
1508static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1509{
1510 struct l2cap_conf_opt *opt = *ptr;
1511 int len;
1512
1513 len = L2CAP_CONF_OPT_SIZE + opt->len;
1514 *ptr += len;
1515
1516 *type = opt->type;
1517 *olen = opt->len;
1518
1519 switch (opt->len) {
1520 case 1:
1521 *val = *((u8 *) opt->val);
1522 break;
1523
1524 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001525 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 break;
1527
1528 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001529 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 break;
1531
1532 default:
1533 *val = (unsigned long) opt->val;
1534 break;
1535 }
1536
1537 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1538 return len;
1539}
1540
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1542{
1543 struct l2cap_conf_opt *opt = *ptr;
1544
1545 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1546
1547 opt->type = type;
1548 opt->len = len;
1549
1550 switch (len) {
1551 case 1:
1552 *((u8 *) opt->val) = val;
1553 break;
1554
1555 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001556 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 break;
1558
1559 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001560 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561 break;
1562
1563 default:
1564 memcpy(opt->val, (void *) val, len);
1565 break;
1566 }
1567
1568 *ptr += L2CAP_CONF_OPT_SIZE + len;
1569}
1570
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001571static void l2cap_ack_timeout(unsigned long arg)
1572{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001573 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001574
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001575 bh_lock_sock(chan->sk);
1576 l2cap_send_ack(chan);
1577 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001578}
1579
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001580static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001581{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001582 struct sock *sk = chan->sk;
1583
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001584 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001585 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001586 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001587 chan->num_acked = 0;
1588 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001589
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001590 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1591 (unsigned long) chan);
1592 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1593 (unsigned long) chan);
1594 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001595
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001596 skb_queue_head_init(&chan->srej_q);
1597 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001598
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001599 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001600
1601 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001602}
1603
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001604static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1605{
1606 switch (mode) {
1607 case L2CAP_MODE_STREAMING:
1608 case L2CAP_MODE_ERTM:
1609 if (l2cap_mode_supported(mode, remote_feat_mask))
1610 return mode;
1611 /* fall through */
1612 default:
1613 return L2CAP_MODE_BASIC;
1614 }
1615}
1616
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001617static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001619 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 struct l2cap_pinfo *pi = l2cap_pi(sk);
1621 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001622 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623 void *ptr = req->data;
1624
1625 BT_DBG("sk %p", sk);
1626
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001627 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001628 goto done;
1629
1630 switch (pi->mode) {
1631 case L2CAP_MODE_STREAMING:
1632 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001633 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001634 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001635
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001636 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001637 default:
1638 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1639 break;
1640 }
1641
1642done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001643 if (pi->imtu != L2CAP_DEFAULT_MTU)
1644 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1645
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001646 switch (pi->mode) {
1647 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001648 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1649 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1650 break;
1651
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001652 rfc.mode = L2CAP_MODE_BASIC;
1653 rfc.txwin_size = 0;
1654 rfc.max_transmit = 0;
1655 rfc.retrans_timeout = 0;
1656 rfc.monitor_timeout = 0;
1657 rfc.max_pdu_size = 0;
1658
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001659 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1660 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001661 break;
1662
1663 case L2CAP_MODE_ERTM:
1664 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001665 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001666 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001667 rfc.retrans_timeout = 0;
1668 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001669 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001670 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001671 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001672
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001673 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1674 (unsigned long) &rfc);
1675
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001676 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1677 break;
1678
1679 if (pi->fcs == L2CAP_FCS_NONE ||
1680 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1681 pi->fcs = L2CAP_FCS_NONE;
1682 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1683 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001684 break;
1685
1686 case L2CAP_MODE_STREAMING:
1687 rfc.mode = L2CAP_MODE_STREAMING;
1688 rfc.txwin_size = 0;
1689 rfc.max_transmit = 0;
1690 rfc.retrans_timeout = 0;
1691 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001692 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001693 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001694 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001695
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001696 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1697 (unsigned long) &rfc);
1698
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001699 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1700 break;
1701
1702 if (pi->fcs == L2CAP_FCS_NONE ||
1703 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1704 pi->fcs = L2CAP_FCS_NONE;
1705 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1706 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001707 break;
1708 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001710 req->dcid = cpu_to_le16(pi->dcid);
1711 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712
1713 return ptr - data;
1714}
1715
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001716static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001718 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001719 struct l2cap_conf_rsp *rsp = data;
1720 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001721 void *req = chan->conf_req;
1722 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001723 int type, hint, olen;
1724 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001725 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001726 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001727 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001729 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001730
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001731 while (len >= L2CAP_CONF_OPT_SIZE) {
1732 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001734 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001735 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001736
1737 switch (type) {
1738 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001739 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001740 break;
1741
1742 case L2CAP_CONF_FLUSH_TO:
1743 pi->flush_to = val;
1744 break;
1745
1746 case L2CAP_CONF_QOS:
1747 break;
1748
Marcel Holtmann6464f352007-10-20 13:39:51 +02001749 case L2CAP_CONF_RFC:
1750 if (olen == sizeof(rfc))
1751 memcpy(&rfc, (void *) val, olen);
1752 break;
1753
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001754 case L2CAP_CONF_FCS:
1755 if (val == L2CAP_FCS_NONE)
1756 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1757
1758 break;
1759
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001760 default:
1761 if (hint)
1762 break;
1763
1764 result = L2CAP_CONF_UNKNOWN;
1765 *((u8 *) ptr++) = type;
1766 break;
1767 }
1768 }
1769
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001770 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001771 goto done;
1772
1773 switch (pi->mode) {
1774 case L2CAP_MODE_STREAMING:
1775 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001776 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1777 pi->mode = l2cap_select_mode(rfc.mode,
1778 pi->conn->feat_mask);
1779 break;
1780 }
1781
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001782 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001783 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001784
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001785 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001786 }
1787
1788done:
1789 if (pi->mode != rfc.mode) {
1790 result = L2CAP_CONF_UNACCEPT;
1791 rfc.mode = pi->mode;
1792
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001793 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001794 return -ECONNREFUSED;
1795
1796 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1797 sizeof(rfc), (unsigned long) &rfc);
1798 }
1799
1800
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001801 if (result == L2CAP_CONF_SUCCESS) {
1802 /* Configure output options and let the other side know
1803 * which ones we don't like. */
1804
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001805 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1806 result = L2CAP_CONF_UNACCEPT;
1807 else {
1808 pi->omtu = mtu;
1809 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1810 }
1811 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001812
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001813 switch (rfc.mode) {
1814 case L2CAP_MODE_BASIC:
1815 pi->fcs = L2CAP_FCS_NONE;
1816 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1817 break;
1818
1819 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001820 chan->remote_tx_win = rfc.txwin_size;
1821 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001822
1823 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1824 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001825
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001826 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001827
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001828 rfc.retrans_timeout =
1829 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1830 rfc.monitor_timeout =
1831 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001832
1833 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001834
1835 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1836 sizeof(rfc), (unsigned long) &rfc);
1837
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001838 break;
1839
1840 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001841 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1842 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001843
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001844 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001845
1846 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001847
1848 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1849 sizeof(rfc), (unsigned long) &rfc);
1850
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001851 break;
1852
1853 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001854 result = L2CAP_CONF_UNACCEPT;
1855
1856 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001857 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001858 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001859
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001860 if (result == L2CAP_CONF_SUCCESS)
1861 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1862 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001863 rsp->scid = cpu_to_le16(pi->dcid);
1864 rsp->result = cpu_to_le16(result);
1865 rsp->flags = cpu_to_le16(0x0000);
1866
1867 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868}
1869
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001870static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1871{
1872 struct l2cap_pinfo *pi = l2cap_pi(sk);
1873 struct l2cap_conf_req *req = data;
1874 void *ptr = req->data;
1875 int type, olen;
1876 unsigned long val;
1877 struct l2cap_conf_rfc rfc;
1878
1879 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1880
1881 while (len >= L2CAP_CONF_OPT_SIZE) {
1882 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1883
1884 switch (type) {
1885 case L2CAP_CONF_MTU:
1886 if (val < L2CAP_DEFAULT_MIN_MTU) {
1887 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001888 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001889 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001890 pi->imtu = val;
1891 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001892 break;
1893
1894 case L2CAP_CONF_FLUSH_TO:
1895 pi->flush_to = val;
1896 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1897 2, pi->flush_to);
1898 break;
1899
1900 case L2CAP_CONF_RFC:
1901 if (olen == sizeof(rfc))
1902 memcpy(&rfc, (void *)val, olen);
1903
1904 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1905 rfc.mode != pi->mode)
1906 return -ECONNREFUSED;
1907
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001908 pi->fcs = 0;
1909
1910 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1911 sizeof(rfc), (unsigned long) &rfc);
1912 break;
1913 }
1914 }
1915
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001916 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1917 return -ECONNREFUSED;
1918
1919 pi->mode = rfc.mode;
1920
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001921 if (*result == L2CAP_CONF_SUCCESS) {
1922 switch (rfc.mode) {
1923 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001924 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1925 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001926 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001927 break;
1928 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001929 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001930 }
1931 }
1932
1933 req->dcid = cpu_to_le16(pi->dcid);
1934 req->flags = cpu_to_le16(0x0000);
1935
1936 return ptr - data;
1937}
1938
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001939static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940{
1941 struct l2cap_conf_rsp *rsp = data;
1942 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001944 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001946 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001947 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001948 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949
1950 return ptr - data;
1951}
1952
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001953void __l2cap_connect_rsp_defer(struct sock *sk)
1954{
1955 struct l2cap_conn_rsp rsp;
1956 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1957 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
1958 u8 buf[128];
1959
1960 sk->sk_state = BT_CONFIG;
1961
1962 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1963 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1964 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1965 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1966 l2cap_send_cmd(conn, chan->ident,
1967 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1968
1969 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
1970 return;
1971
1972 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
1973 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1974 l2cap_build_conf_req(chan, buf), buf);
1975 chan->num_conf_req++;
1976}
1977
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001978static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1979{
1980 struct l2cap_pinfo *pi = l2cap_pi(sk);
1981 int type, olen;
1982 unsigned long val;
1983 struct l2cap_conf_rfc rfc;
1984
1985 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1986
1987 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1988 return;
1989
1990 while (len >= L2CAP_CONF_OPT_SIZE) {
1991 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1992
1993 switch (type) {
1994 case L2CAP_CONF_RFC:
1995 if (olen == sizeof(rfc))
1996 memcpy(&rfc, (void *)val, olen);
1997 goto done;
1998 }
1999 }
2000
2001done:
2002 switch (rfc.mode) {
2003 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002004 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2005 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002006 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2007 break;
2008 case L2CAP_MODE_STREAMING:
2009 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2010 }
2011}
2012
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002013static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2014{
2015 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2016
2017 if (rej->reason != 0x0000)
2018 return 0;
2019
2020 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2021 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002022 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002023
2024 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002025 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002026
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002027 l2cap_conn_start(conn);
2028 }
2029
2030 return 0;
2031}
2032
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2034{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2036 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002037 struct l2cap_chan *chan = NULL;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002038 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002039 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040
2041 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002042 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043
2044 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2045
2046 /* Check if we have socket listening on psm */
2047 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2048 if (!parent) {
2049 result = L2CAP_CR_BAD_PSM;
2050 goto sendresp;
2051 }
2052
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002053 bh_lock_sock(parent);
2054
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002055 /* Check if the ACL is secure enough (if not SDP) */
2056 if (psm != cpu_to_le16(0x0001) &&
2057 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002058 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002059 result = L2CAP_CR_SEC_BLOCK;
2060 goto response;
2061 }
2062
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 result = L2CAP_CR_NO_MEM;
2064
2065 /* Check for backlog size */
2066 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002067 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 goto response;
2069 }
2070
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002071 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 if (!sk)
2073 goto response;
2074
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002075 chan = l2cap_chan_alloc(sk);
2076 if (!chan) {
2077 l2cap_sock_kill(sk);
2078 goto response;
2079 }
2080
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002081 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082
2083 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002084 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2085 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086 sock_set_flag(sk, SOCK_ZAPPED);
2087 l2cap_sock_kill(sk);
2088 goto response;
2089 }
2090
2091 hci_conn_hold(conn->hcon);
2092
2093 l2cap_sock_init(sk, parent);
2094 bacpy(&bt_sk(sk)->src, conn->src);
2095 bacpy(&bt_sk(sk)->dst, conn->dst);
2096 l2cap_pi(sk)->psm = psm;
2097 l2cap_pi(sk)->dcid = scid;
2098
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002099 bt_accept_enqueue(parent, sk);
2100
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002101 __l2cap_chan_add(conn, chan);
2102
2103 l2cap_pi(sk)->chan = chan;
2104
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 dcid = l2cap_pi(sk)->scid;
2106
2107 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2108
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002109 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110
Marcel Holtmann984947d2009-02-06 23:35:19 +01002111 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002112 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002113 if (bt_sk(sk)->defer_setup) {
2114 sk->sk_state = BT_CONNECT2;
2115 result = L2CAP_CR_PEND;
2116 status = L2CAP_CS_AUTHOR_PEND;
2117 parent->sk_data_ready(parent, 0);
2118 } else {
2119 sk->sk_state = BT_CONFIG;
2120 result = L2CAP_CR_SUCCESS;
2121 status = L2CAP_CS_NO_INFO;
2122 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002123 } else {
2124 sk->sk_state = BT_CONNECT2;
2125 result = L2CAP_CR_PEND;
2126 status = L2CAP_CS_AUTHEN_PEND;
2127 }
2128 } else {
2129 sk->sk_state = BT_CONNECT2;
2130 result = L2CAP_CR_PEND;
2131 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132 }
2133
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002134 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135
2136response:
2137 bh_unlock_sock(parent);
2138
2139sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002140 rsp.scid = cpu_to_le16(scid);
2141 rsp.dcid = cpu_to_le16(dcid);
2142 rsp.result = cpu_to_le16(result);
2143 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002145
2146 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2147 struct l2cap_info_req info;
2148 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2149
2150 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2151 conn->info_ident = l2cap_get_ident(conn);
2152
2153 mod_timer(&conn->info_timer, jiffies +
2154 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2155
2156 l2cap_send_cmd(conn, conn->info_ident,
2157 L2CAP_INFO_REQ, sizeof(info), &info);
2158 }
2159
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002160 if (chan && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002161 result == L2CAP_CR_SUCCESS) {
2162 u8 buf[128];
2163 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2164 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002165 l2cap_build_conf_req(chan, buf), buf);
2166 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002167 }
2168
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 return 0;
2170}
2171
2172static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2173{
2174 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2175 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002176 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 struct sock *sk;
2178 u8 req[128];
2179
2180 scid = __le16_to_cpu(rsp->scid);
2181 dcid = __le16_to_cpu(rsp->dcid);
2182 result = __le16_to_cpu(rsp->result);
2183 status = __le16_to_cpu(rsp->status);
2184
2185 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2186
2187 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002188 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002189 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002190 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002192 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002193 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002194 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 }
2196
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002197 sk = chan->sk;
2198
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199 switch (result) {
2200 case L2CAP_CR_SUCCESS:
2201 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002202 chan->ident = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002204 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2205
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002206 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2207 break;
2208
2209 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2210
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002212 l2cap_build_conf_req(chan, req), req);
2213 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 break;
2215
2216 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002217 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218 break;
2219
2220 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002221 /* don't delete l2cap channel if sk is owned by user */
2222 if (sock_owned_by_user(sk)) {
2223 sk->sk_state = BT_DISCONN;
2224 l2cap_sock_clear_timer(sk);
2225 l2cap_sock_set_timer(sk, HZ / 5);
2226 break;
2227 }
2228
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002229 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 break;
2231 }
2232
2233 bh_unlock_sock(sk);
2234 return 0;
2235}
2236
Mat Martineau8c462b62010-08-24 15:35:42 -07002237static inline void set_default_fcs(struct l2cap_pinfo *pi)
2238{
2239 /* FCS is enabled only in ERTM or streaming mode, if one or both
2240 * sides request it.
2241 */
2242 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2243 pi->fcs = L2CAP_FCS_NONE;
2244 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2245 pi->fcs = L2CAP_FCS_CRC16;
2246}
2247
Al Viro88219a02007-07-29 00:17:25 -07002248static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249{
2250 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2251 u16 dcid, flags;
2252 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002253 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002255 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256
2257 dcid = __le16_to_cpu(req->dcid);
2258 flags = __le16_to_cpu(req->flags);
2259
2260 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2261
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002262 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002263 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264 return -ENOENT;
2265
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002266 sk = chan->sk;
2267
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002268 if (sk->sk_state != BT_CONFIG) {
2269 struct l2cap_cmd_rej rej;
2270
2271 rej.reason = cpu_to_le16(0x0002);
2272 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2273 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002274 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002275 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002276
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002277 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002278 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002279 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002280 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2281 l2cap_build_conf_rsp(sk, rsp,
2282 L2CAP_CONF_REJECT, flags), rsp);
2283 goto unlock;
2284 }
2285
2286 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002287 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2288 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289
2290 if (flags & 0x0001) {
2291 /* Incomplete config. Send empty response. */
2292 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002293 l2cap_build_conf_rsp(sk, rsp,
2294 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 goto unlock;
2296 }
2297
2298 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002299 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002300 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002301 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002303 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002305 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002306 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002307
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002308 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002309 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002310
Marcel Holtmann876d9482007-10-20 13:35:42 +02002311 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2312 goto unlock;
2313
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002315 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002316
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002318
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002319 chan->next_tx_seq = 0;
2320 chan->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002321 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002322 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002323 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002324
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002326 goto unlock;
2327 }
2328
2329 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002330 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002331 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002333 l2cap_build_conf_req(chan, buf), buf);
2334 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 }
2336
2337unlock:
2338 bh_unlock_sock(sk);
2339 return 0;
2340}
2341
2342static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2343{
2344 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2345 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002346 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002348 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349
2350 scid = __le16_to_cpu(rsp->scid);
2351 flags = __le16_to_cpu(rsp->flags);
2352 result = __le16_to_cpu(rsp->result);
2353
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002354 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2355 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002357 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002358 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 return 0;
2360
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002361 sk = chan->sk;
2362
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 switch (result) {
2364 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002365 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 break;
2367
2368 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002369 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002370 char req[64];
2371
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002372 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002373 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002374 goto done;
2375 }
2376
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002377 /* throw out any old stored conf requests */
2378 result = L2CAP_CONF_SUCCESS;
2379 len = l2cap_parse_conf_rsp(sk, rsp->data,
2380 len, req, &result);
2381 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002382 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002383 goto done;
2384 }
2385
2386 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2387 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002388 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002389 if (result != L2CAP_CONF_SUCCESS)
2390 goto done;
2391 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392 }
2393
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002394 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002395 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002397 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 goto done;
2399 }
2400
2401 if (flags & 0x01)
2402 goto done;
2403
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2405
2406 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002407 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002408
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002410 chan->next_tx_seq = 0;
2411 chan->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002412 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002413 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002414 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002415
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416 l2cap_chan_ready(sk);
2417 }
2418
2419done:
2420 bh_unlock_sock(sk);
2421 return 0;
2422}
2423
2424static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2425{
2426 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2427 struct l2cap_disconn_rsp rsp;
2428 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002429 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 struct sock *sk;
2431
2432 scid = __le16_to_cpu(req->scid);
2433 dcid = __le16_to_cpu(req->dcid);
2434
2435 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2436
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002437 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002438 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439 return 0;
2440
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002441 sk = chan->sk;
2442
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002443 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2444 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2446
2447 sk->sk_shutdown = SHUTDOWN_MASK;
2448
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002449 /* don't delete l2cap channel if sk is owned by user */
2450 if (sock_owned_by_user(sk)) {
2451 sk->sk_state = BT_DISCONN;
2452 l2cap_sock_clear_timer(sk);
2453 l2cap_sock_set_timer(sk, HZ / 5);
2454 bh_unlock_sock(sk);
2455 return 0;
2456 }
2457
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002458 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459 bh_unlock_sock(sk);
2460
2461 l2cap_sock_kill(sk);
2462 return 0;
2463}
2464
2465static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2466{
2467 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2468 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002469 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 struct sock *sk;
2471
2472 scid = __le16_to_cpu(rsp->scid);
2473 dcid = __le16_to_cpu(rsp->dcid);
2474
2475 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2476
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002477 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002478 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 return 0;
2480
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002481 sk = chan->sk;
2482
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002483 /* don't delete l2cap channel if sk is owned by user */
2484 if (sock_owned_by_user(sk)) {
2485 sk->sk_state = BT_DISCONN;
2486 l2cap_sock_clear_timer(sk);
2487 l2cap_sock_set_timer(sk, HZ / 5);
2488 bh_unlock_sock(sk);
2489 return 0;
2490 }
2491
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002492 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493 bh_unlock_sock(sk);
2494
2495 l2cap_sock_kill(sk);
2496 return 0;
2497}
2498
2499static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2500{
2501 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502 u16 type;
2503
2504 type = __le16_to_cpu(req->type);
2505
2506 BT_DBG("type 0x%4.4x", type);
2507
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002508 if (type == L2CAP_IT_FEAT_MASK) {
2509 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002510 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002511 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2512 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2513 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002514 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002515 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2516 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002517 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002518 l2cap_send_cmd(conn, cmd->ident,
2519 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002520 } else if (type == L2CAP_IT_FIXED_CHAN) {
2521 u8 buf[12];
2522 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2523 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2524 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2525 memcpy(buf + 4, l2cap_fixed_chan, 8);
2526 l2cap_send_cmd(conn, cmd->ident,
2527 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002528 } else {
2529 struct l2cap_info_rsp rsp;
2530 rsp.type = cpu_to_le16(type);
2531 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2532 l2cap_send_cmd(conn, cmd->ident,
2533 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2534 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535
2536 return 0;
2537}
2538
2539static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2540{
2541 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2542 u16 type, result;
2543
2544 type = __le16_to_cpu(rsp->type);
2545 result = __le16_to_cpu(rsp->result);
2546
2547 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2548
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002549 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2550 if (cmd->ident != conn->info_ident ||
2551 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2552 return 0;
2553
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002554 del_timer(&conn->info_timer);
2555
Ville Tervoadb08ed2010-08-04 09:43:33 +03002556 if (result != L2CAP_IR_SUCCESS) {
2557 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2558 conn->info_ident = 0;
2559
2560 l2cap_conn_start(conn);
2561
2562 return 0;
2563 }
2564
Marcel Holtmann984947d2009-02-06 23:35:19 +01002565 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002566 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002567
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002568 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002569 struct l2cap_info_req req;
2570 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2571
2572 conn->info_ident = l2cap_get_ident(conn);
2573
2574 l2cap_send_cmd(conn, conn->info_ident,
2575 L2CAP_INFO_REQ, sizeof(req), &req);
2576 } else {
2577 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2578 conn->info_ident = 0;
2579
2580 l2cap_conn_start(conn);
2581 }
2582 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002583 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002584 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002585
2586 l2cap_conn_start(conn);
2587 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002588
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589 return 0;
2590}
2591
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002592static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002593 u16 to_multiplier)
2594{
2595 u16 max_latency;
2596
2597 if (min > max || min < 6 || max > 3200)
2598 return -EINVAL;
2599
2600 if (to_multiplier < 10 || to_multiplier > 3200)
2601 return -EINVAL;
2602
2603 if (max >= to_multiplier * 8)
2604 return -EINVAL;
2605
2606 max_latency = (to_multiplier * 8 / max) - 1;
2607 if (latency > 499 || latency > max_latency)
2608 return -EINVAL;
2609
2610 return 0;
2611}
2612
2613static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2614 struct l2cap_cmd_hdr *cmd, u8 *data)
2615{
2616 struct hci_conn *hcon = conn->hcon;
2617 struct l2cap_conn_param_update_req *req;
2618 struct l2cap_conn_param_update_rsp rsp;
2619 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002620 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002621
2622 if (!(hcon->link_mode & HCI_LM_MASTER))
2623 return -EINVAL;
2624
2625 cmd_len = __le16_to_cpu(cmd->len);
2626 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2627 return -EPROTO;
2628
2629 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002630 min = __le16_to_cpu(req->min);
2631 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002632 latency = __le16_to_cpu(req->latency);
2633 to_multiplier = __le16_to_cpu(req->to_multiplier);
2634
2635 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2636 min, max, latency, to_multiplier);
2637
2638 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002639
2640 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2641 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002642 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2643 else
2644 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2645
2646 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2647 sizeof(rsp), &rsp);
2648
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002649 if (!err)
2650 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2651
Claudio Takahaside731152011-02-11 19:28:55 -02002652 return 0;
2653}
2654
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002655static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2656 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2657{
2658 int err = 0;
2659
2660 switch (cmd->code) {
2661 case L2CAP_COMMAND_REJ:
2662 l2cap_command_rej(conn, cmd, data);
2663 break;
2664
2665 case L2CAP_CONN_REQ:
2666 err = l2cap_connect_req(conn, cmd, data);
2667 break;
2668
2669 case L2CAP_CONN_RSP:
2670 err = l2cap_connect_rsp(conn, cmd, data);
2671 break;
2672
2673 case L2CAP_CONF_REQ:
2674 err = l2cap_config_req(conn, cmd, cmd_len, data);
2675 break;
2676
2677 case L2CAP_CONF_RSP:
2678 err = l2cap_config_rsp(conn, cmd, data);
2679 break;
2680
2681 case L2CAP_DISCONN_REQ:
2682 err = l2cap_disconnect_req(conn, cmd, data);
2683 break;
2684
2685 case L2CAP_DISCONN_RSP:
2686 err = l2cap_disconnect_rsp(conn, cmd, data);
2687 break;
2688
2689 case L2CAP_ECHO_REQ:
2690 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2691 break;
2692
2693 case L2CAP_ECHO_RSP:
2694 break;
2695
2696 case L2CAP_INFO_REQ:
2697 err = l2cap_information_req(conn, cmd, data);
2698 break;
2699
2700 case L2CAP_INFO_RSP:
2701 err = l2cap_information_rsp(conn, cmd, data);
2702 break;
2703
2704 default:
2705 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2706 err = -EINVAL;
2707 break;
2708 }
2709
2710 return err;
2711}
2712
2713static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2714 struct l2cap_cmd_hdr *cmd, u8 *data)
2715{
2716 switch (cmd->code) {
2717 case L2CAP_COMMAND_REJ:
2718 return 0;
2719
2720 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002721 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002722
2723 case L2CAP_CONN_PARAM_UPDATE_RSP:
2724 return 0;
2725
2726 default:
2727 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2728 return -EINVAL;
2729 }
2730}
2731
2732static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2733 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734{
2735 u8 *data = skb->data;
2736 int len = skb->len;
2737 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002738 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739
2740 l2cap_raw_recv(conn, skb);
2741
2742 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002743 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2745 data += L2CAP_CMD_HDR_SIZE;
2746 len -= L2CAP_CMD_HDR_SIZE;
2747
Al Viro88219a02007-07-29 00:17:25 -07002748 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749
Al Viro88219a02007-07-29 00:17:25 -07002750 BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751
Al Viro88219a02007-07-29 00:17:25 -07002752 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753 BT_DBG("corrupted command");
2754 break;
2755 }
2756
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002757 if (conn->hcon->type == LE_LINK)
2758 err = l2cap_le_sig_cmd(conn, &cmd, data);
2759 else
2760 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761
2762 if (err) {
2763 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002764
2765 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766
2767 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002768 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2770 }
2771
Al Viro88219a02007-07-29 00:17:25 -07002772 data += cmd_len;
2773 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774 }
2775
2776 kfree_skb(skb);
2777}
2778
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002779static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2780{
2781 u16 our_fcs, rcv_fcs;
2782 int hdr_size = L2CAP_HDR_SIZE + 2;
2783
2784 if (pi->fcs == L2CAP_FCS_CRC16) {
2785 skb_trim(skb, skb->len - 2);
2786 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2787 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2788
2789 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002790 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002791 }
2792 return 0;
2793}
2794
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002795static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002796{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002797 u16 control = 0;
2798
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002799 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002800
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002801 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002802
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002803 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002804 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002805 l2cap_send_sframe(chan, control);
2806 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002807 }
2808
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002809 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
2810 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002811
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002812 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002813
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002814 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002815 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002816 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002817 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002818 }
2819}
2820
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002821static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u8 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002822{
2823 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002824 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002825
2826 bt_cb(skb)->tx_seq = tx_seq;
2827 bt_cb(skb)->sar = sar;
2828
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002829 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002830 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002831 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002832 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002833 }
2834
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002835 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002836 if (tx_seq_offset < 0)
2837 tx_seq_offset += 64;
2838
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002839 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002840 if (bt_cb(next_skb)->tx_seq == tx_seq)
2841 return -EINVAL;
2842
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002843 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002844 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002845 if (next_tx_seq_offset < 0)
2846 next_tx_seq_offset += 64;
2847
2848 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002849 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002850 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002851 }
2852
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002853 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002854 break;
2855
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002856 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002857
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002858 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002859
2860 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002861}
2862
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002863static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002864{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002865 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002866 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002867 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002868
2869 switch (control & L2CAP_CTRL_SAR) {
2870 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002871 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002872 goto drop;
2873
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002874 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002875 if (!err)
2876 return err;
2877
2878 break;
2879
2880 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002881 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002882 goto drop;
2883
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002884 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002885
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002886 if (chan->sdu_len > pi->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002887 goto disconnect;
2888
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002889 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
2890 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002891 return -ENOMEM;
2892
2893 /* pull sdu_len bytes only after alloc, because of Local Busy
2894 * condition we have to be sure that this will be executed
2895 * only once, i.e., when alloc does not fail */
2896 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002897
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002898 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002899
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002900 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002901 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002902 break;
2903
2904 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002905 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002906 goto disconnect;
2907
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002908 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002909 goto disconnect;
2910
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002911 chan->partial_sdu_len += skb->len;
2912 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002913 goto drop;
2914
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002915 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002916
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002917 break;
2918
2919 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002920 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002921 goto disconnect;
2922
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002923 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002924 goto disconnect;
2925
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002926 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002927 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002928
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002929 if (chan->partial_sdu_len > pi->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002930 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002931
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002932 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002933 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002934
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002935 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002936 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002937
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002938 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002939 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002940 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002941 return -ENOMEM;
2942 }
2943
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002944 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002945 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002946 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002947 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002948 return err;
2949 }
2950
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002951 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2952 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002953
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002954 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002955 break;
2956 }
2957
2958 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002959 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002960
2961drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002962 kfree_skb(chan->sdu);
2963 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002964
2965disconnect:
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002966 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002967 kfree_skb(skb);
2968 return 0;
2969}
2970
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002971static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002972{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002973 struct sock *sk = chan->sk;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002974 struct sk_buff *skb;
2975 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002976 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002977
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002978 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002979 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002980 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002981 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002982 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002983 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002984 }
2985
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002986 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002987 }
2988
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002989 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002990 goto done;
2991
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002992 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002993 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002994 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002995 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002996
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002997 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002998 __mod_monitor_timer();
2999
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003000 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003001
3002done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003003 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3004 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003005
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003006 BT_DBG("sk %p, Exit local busy", sk);
3007
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003008 return 0;
3009}
3010
3011static void l2cap_busy_work(struct work_struct *work)
3012{
3013 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003014 struct l2cap_chan *chan =
3015 container_of(work, struct l2cap_chan, busy_work);
3016 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003017 int n_tries = 0, timeo = HZ/5, err;
3018 struct sk_buff *skb;
3019
3020 lock_sock(sk);
3021
3022 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003023 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003024 set_current_state(TASK_INTERRUPTIBLE);
3025
3026 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3027 err = -EBUSY;
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003028 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003029 break;
3030 }
3031
3032 if (!timeo)
3033 timeo = HZ/5;
3034
3035 if (signal_pending(current)) {
3036 err = sock_intr_errno(timeo);
3037 break;
3038 }
3039
3040 release_sock(sk);
3041 timeo = schedule_timeout(timeo);
3042 lock_sock(sk);
3043
3044 err = sock_error(sk);
3045 if (err)
3046 break;
3047
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003048 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003049 break;
3050 }
3051
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003052 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003053 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003054
3055 release_sock(sk);
3056}
3057
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003058static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003059{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003060 int sctrl, err;
3061
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003062 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003063 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003064 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003065 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003066
3067
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003068 }
3069
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003070 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003071 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003072 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003073 return err;
3074 }
3075
3076 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003077 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003078
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003079 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003080 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003081 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003082
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003083 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003084 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003085 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003086
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003087 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003088
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003089 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003090
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003091 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003092
3093 return err;
3094}
3095
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003096static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003097{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003098 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003099 struct sk_buff *_skb;
3100 int err = -EINVAL;
3101
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003102 /*
3103 * TODO: We have to notify the userland if some data is lost with the
3104 * Streaming Mode.
3105 */
3106
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003107 switch (control & L2CAP_CTRL_SAR) {
3108 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003109 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003110 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003111 break;
3112 }
3113
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003114 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003115 if (!err)
3116 return 0;
3117
3118 break;
3119
3120 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003121 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003122 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003123 break;
3124 }
3125
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003126 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003127 skb_pull(skb, 2);
3128
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003129 if (chan->sdu_len > pi->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003130 err = -EMSGSIZE;
3131 break;
3132 }
3133
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003134 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3135 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003136 err = -ENOMEM;
3137 break;
3138 }
3139
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003140 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003141
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003142 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003143 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003144 err = 0;
3145 break;
3146
3147 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003148 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003149 break;
3150
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003151 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003152
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003153 chan->partial_sdu_len += skb->len;
3154 if (chan->partial_sdu_len > chan->sdu_len)
3155 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003156 else
3157 err = 0;
3158
3159 break;
3160
3161 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003162 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003163 break;
3164
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003165 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003166
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003167 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003168 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003169
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003170 if (chan->partial_sdu_len > pi->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003171 goto drop;
3172
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003173 if (chan->partial_sdu_len == chan->sdu_len) {
3174 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003175 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003176 if (err < 0)
3177 kfree_skb(_skb);
3178 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003179 err = 0;
3180
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003181drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003182 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003183 break;
3184 }
3185
3186 kfree_skb(skb);
3187 return err;
3188}
3189
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003190static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003191{
3192 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003193 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003194
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003195 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003196 if (bt_cb(skb)->tx_seq != tx_seq)
3197 break;
3198
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003199 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003200 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003201 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003202 chan->buffer_seq_srej =
3203 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003204 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003205 }
3206}
3207
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003208static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003209{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003210 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003211 struct srej_list *l, *tmp;
3212 u16 control;
3213
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003214 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003215 if (l->tx_seq == tx_seq) {
3216 list_del(&l->list);
3217 kfree(l);
3218 return;
3219 }
3220 control = L2CAP_SUPER_SELECT_REJECT;
3221 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003222 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003223 list_del(&l->list);
3224 list_add_tail(&l->list, SREJ_LIST(sk));
3225 }
3226}
3227
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003228static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003229{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003230 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003231 struct srej_list *new;
3232 u16 control;
3233
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003234 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003235 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003236 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003237 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003238
3239 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003240 new->tx_seq = chan->expected_tx_seq;
3241 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003242 list_add_tail(&new->list, SREJ_LIST(sk));
3243 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003244 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003245}
3246
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003247static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003248{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003249 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003250 struct l2cap_pinfo *pi = l2cap_pi(sk);
3251 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003252 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003253 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003254 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003255 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003256 int err = 0;
3257
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003258 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3259 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003260
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003261 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003262 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003263 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003264 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003265 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003266 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003267 }
3268
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003269 chan->expected_ack_seq = req_seq;
3270 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003271
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003272 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003273 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003274
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003275 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003276 if (tx_seq_offset < 0)
3277 tx_seq_offset += 64;
3278
3279 /* invalid tx_seq */
3280 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003281 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003282 goto drop;
3283 }
3284
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003285 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003286 goto drop;
3287
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003288 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003289 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003290
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003291 first = list_first_entry(SREJ_LIST(sk),
3292 struct srej_list, list);
3293 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003294 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003295 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003296
3297 list_del(&first->list);
3298 kfree(first);
3299
3300 if (list_empty(SREJ_LIST(sk))) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003301 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003302 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3303 l2cap_send_ack(chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003304 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003305 }
3306 } else {
3307 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003308
3309 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003310 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003311 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003312
3313 list_for_each_entry(l, SREJ_LIST(sk), list) {
3314 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003315 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003316 return 0;
3317 }
3318 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003319 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003320 }
3321 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003322 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003323 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003324 if (expected_tx_seq_offset < 0)
3325 expected_tx_seq_offset += 64;
3326
3327 /* duplicated tx_seq */
3328 if (tx_seq_offset < expected_tx_seq_offset)
3329 goto drop;
3330
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003331 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003332
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003333 BT_DBG("sk %p, Enter SREJ", sk);
3334
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003335 INIT_LIST_HEAD(SREJ_LIST(sk));
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003336 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003337
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003338 __skb_queue_head_init(&chan->srej_q);
3339 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003340 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003341
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003342 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003343
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003344 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003345
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003346 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003347 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003348 return 0;
3349
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003350expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003351 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003352
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003353 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003354 bt_cb(skb)->tx_seq = tx_seq;
3355 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003356 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003357 return 0;
3358 }
3359
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003360 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003361 if (err < 0)
3362 return 0;
3363
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003364 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003365 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3366 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003367 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003368 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003369 }
3370
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003371 __mod_ack_timer();
3372
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003373 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3374 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003375 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003376
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003377 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003378
3379drop:
3380 kfree_skb(skb);
3381 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003382}
3383
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003384static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003385{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003386 struct sock *sk = chan->sk;
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003387
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003388 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
3389 rx_control);
3390
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003391 chan->expected_ack_seq = __get_reqseq(rx_control);
3392 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003393
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003394 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003395 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3396 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3397 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003398 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003399 __mod_retrans_timer();
3400
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003401 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3402 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003403 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003404 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003405 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003406
3407 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003408 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003409
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003410 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3411 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003412 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003413 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003414
3415 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003416 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003417 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003418 __mod_retrans_timer();
3419
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003420 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3421 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3422 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003423 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003424 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003425 }
3426}
3427
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003428static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003429{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003430 u8 tx_seq = __get_reqseq(rx_control);
3431
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003432 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003433
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003434 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003435
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003436 chan->expected_ack_seq = tx_seq;
3437 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003438
3439 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003440 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3441 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003442 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003443 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003444 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003445 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003446
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003447 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3448 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003449 }
3450}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003451static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003452{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003453 u8 tx_seq = __get_reqseq(rx_control);
3454
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003455 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003456
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003457 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003458
3459 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003460 chan->expected_ack_seq = tx_seq;
3461 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003462
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003463 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3464 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003465
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003466 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003467
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003468 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003469 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003470 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003471 }
3472 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003473 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003474 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003475 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003476 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003477 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003478 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003479 l2cap_retransmit_one_frame(chan, tx_seq);
3480 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003481 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003482 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003483 }
3484 }
3485}
3486
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003487static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003488{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003489 u8 tx_seq = __get_reqseq(rx_control);
3490
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003491 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003492
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003493 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003494 chan->expected_ack_seq = tx_seq;
3495 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003496
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003497 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003498 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003499
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003500 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003501 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003502 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003503 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003504 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003505 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003506
3507 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003508 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003509 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003510 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003511}
3512
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003513static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003514{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003515 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003516
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003517 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003518 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003519 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003520 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003521 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003522 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003523 }
3524
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003525 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3526 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003527 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003528 break;
3529
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003530 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003531 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003532 break;
3533
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003534 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003535 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003536 break;
3537
3538 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003539 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003540 break;
3541 }
3542
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003543 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003544 return 0;
3545}
3546
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003547static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3548{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003549 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003550 struct l2cap_pinfo *pi = l2cap_pi(sk);
3551 u16 control;
3552 u8 req_seq;
3553 int len, next_tx_seq_offset, req_seq_offset;
3554
3555 control = get_unaligned_le16(skb->data);
3556 skb_pull(skb, 2);
3557 len = skb->len;
3558
3559 /*
3560 * We can just drop the corrupted I-frame here.
3561 * Receiver will miss it and start proper recovery
3562 * procedures and ask retransmission.
3563 */
3564 if (l2cap_check_fcs(pi, skb))
3565 goto drop;
3566
3567 if (__is_sar_start(control) && __is_iframe(control))
3568 len -= 2;
3569
3570 if (pi->fcs == L2CAP_FCS_CRC16)
3571 len -= 2;
3572
3573 if (len > pi->mps) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003574 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003575 goto drop;
3576 }
3577
3578 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003579 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003580 if (req_seq_offset < 0)
3581 req_seq_offset += 64;
3582
3583 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003584 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003585 if (next_tx_seq_offset < 0)
3586 next_tx_seq_offset += 64;
3587
3588 /* check for invalid req-seq */
3589 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003590 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003591 goto drop;
3592 }
3593
3594 if (__is_iframe(control)) {
3595 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003596 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003597 goto drop;
3598 }
3599
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003600 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003601 } else {
3602 if (len != 0) {
3603 BT_ERR("%d", len);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003604 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003605 goto drop;
3606 }
3607
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003608 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003609 }
3610
3611 return 0;
3612
3613drop:
3614 kfree_skb(skb);
3615 return 0;
3616}
3617
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3619{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003620 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003622 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003623 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003624 u8 tx_seq;
3625 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003627 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003628 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629 BT_DBG("unknown cid 0x%4.4x", cid);
3630 goto drop;
3631 }
3632
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003633 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003634 pi = l2cap_pi(sk);
3635
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636 BT_DBG("sk %p, len %d", sk, skb->len);
3637
3638 if (sk->sk_state != BT_CONNECTED)
3639 goto drop;
3640
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003641 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003642 case L2CAP_MODE_BASIC:
3643 /* If socket recv buffers overflows we drop data here
3644 * which is *bad* because L2CAP has to be reliable.
3645 * But we don't have any other choice. L2CAP doesn't
3646 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003648 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003649 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003650
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003651 if (!sock_queue_rcv_skb(sk, skb))
3652 goto done;
3653 break;
3654
3655 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003656 if (!sock_owned_by_user(sk)) {
3657 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003658 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003659 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003660 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003661 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003662
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003663 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003664
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003665 case L2CAP_MODE_STREAMING:
3666 control = get_unaligned_le16(skb->data);
3667 skb_pull(skb, 2);
3668 len = skb->len;
3669
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003670 if (l2cap_check_fcs(pi, skb))
3671 goto drop;
3672
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003673 if (__is_sar_start(control))
3674 len -= 2;
3675
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003676 if (pi->fcs == L2CAP_FCS_CRC16)
3677 len -= 2;
3678
Nathan Holstein51893f82010-06-09 15:46:25 -04003679 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003680 goto drop;
3681
3682 tx_seq = __get_txseq(control);
3683
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003684 if (chan->expected_tx_seq == tx_seq)
3685 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003686 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003687 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003688
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003689 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003690
3691 goto done;
3692
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003693 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003694 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003695 break;
3696 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697
3698drop:
3699 kfree_skb(skb);
3700
3701done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003702 if (sk)
3703 bh_unlock_sock(sk);
3704
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705 return 0;
3706}
3707
Al Viro8e036fc2007-07-29 00:16:36 -07003708static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709{
3710 struct sock *sk;
3711
3712 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3713 if (!sk)
3714 goto drop;
3715
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003716 bh_lock_sock(sk);
3717
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718 BT_DBG("sk %p, len %d", sk, skb->len);
3719
3720 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3721 goto drop;
3722
3723 if (l2cap_pi(sk)->imtu < skb->len)
3724 goto drop;
3725
3726 if (!sock_queue_rcv_skb(sk, skb))
3727 goto done;
3728
3729drop:
3730 kfree_skb(skb);
3731
3732done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003733 if (sk)
3734 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735 return 0;
3736}
3737
3738static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3739{
3740 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003741 u16 cid, len;
3742 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743
3744 skb_pull(skb, L2CAP_HDR_SIZE);
3745 cid = __le16_to_cpu(lh->cid);
3746 len = __le16_to_cpu(lh->len);
3747
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003748 if (len != skb->len) {
3749 kfree_skb(skb);
3750 return;
3751 }
3752
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3754
3755 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003756 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003757 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758 l2cap_sig_channel(conn, skb);
3759 break;
3760
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003761 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003762 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763 skb_pull(skb, 2);
3764 l2cap_conless_channel(conn, psm, skb);
3765 break;
3766
3767 default:
3768 l2cap_data_channel(conn, cid, skb);
3769 break;
3770 }
3771}
3772
3773/* ---- L2CAP interface with lower layer (HCI) ---- */
3774
3775static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3776{
3777 int exact = 0, lm1 = 0, lm2 = 0;
3778 register struct sock *sk;
3779 struct hlist_node *node;
3780
3781 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003782 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003783
3784 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3785
3786 /* Find listening sockets and check their link_mode */
3787 read_lock(&l2cap_sk_list.lock);
3788 sk_for_each(sk, node, &l2cap_sk_list.head) {
3789 if (sk->sk_state != BT_LISTEN)
3790 continue;
3791
3792 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003793 lm1 |= HCI_LM_ACCEPT;
3794 if (l2cap_pi(sk)->role_switch)
3795 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003797 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3798 lm2 |= HCI_LM_ACCEPT;
3799 if (l2cap_pi(sk)->role_switch)
3800 lm2 |= HCI_LM_MASTER;
3801 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802 }
3803 read_unlock(&l2cap_sk_list.lock);
3804
3805 return exact ? lm1 : lm2;
3806}
3807
3808static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3809{
Marcel Holtmann01394182006-07-03 10:02:46 +02003810 struct l2cap_conn *conn;
3811
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3813
Ville Tervoacd7d372011-02-10 22:38:49 -03003814 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003815 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816
3817 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003818 conn = l2cap_conn_add(hcon, status);
3819 if (conn)
3820 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003821 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822 l2cap_conn_del(hcon, bt_err(status));
3823
3824 return 0;
3825}
3826
Marcel Holtmann2950f212009-02-12 14:02:50 +01003827static int l2cap_disconn_ind(struct hci_conn *hcon)
3828{
3829 struct l2cap_conn *conn = hcon->l2cap_data;
3830
3831 BT_DBG("hcon %p", hcon);
3832
3833 if (hcon->type != ACL_LINK || !conn)
3834 return 0x13;
3835
3836 return conn->disc_reason;
3837}
3838
3839static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840{
3841 BT_DBG("hcon %p reason %d", hcon, reason);
3842
Ville Tervoacd7d372011-02-10 22:38:49 -03003843 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003844 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845
3846 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003847
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848 return 0;
3849}
3850
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003851static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3852{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003853 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003854 return;
3855
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003856 if (encrypt == 0x00) {
3857 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3858 l2cap_sock_clear_timer(sk);
3859 l2cap_sock_set_timer(sk, HZ * 5);
3860 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3861 __l2cap_sock_close(sk, ECONNREFUSED);
3862 } else {
3863 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3864 l2cap_sock_clear_timer(sk);
3865 }
3866}
3867
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003868static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003870 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003871 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872
Marcel Holtmann01394182006-07-03 10:02:46 +02003873 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003875
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876 BT_DBG("conn %p", conn);
3877
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003878 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003879
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003880 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003881 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003882
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883 bh_lock_sock(sk);
3884
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003885 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3886 bh_unlock_sock(sk);
3887 continue;
3888 }
3889
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003890 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003891 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003892 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003893 bh_unlock_sock(sk);
3894 continue;
3895 }
3896
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003897 if (sk->sk_state == BT_CONNECT) {
3898 if (!status) {
3899 struct l2cap_conn_req req;
3900 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3901 req.psm = l2cap_pi(sk)->psm;
3902
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003903 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003904 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003905
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003906 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003907 L2CAP_CONN_REQ, sizeof(req), &req);
3908 } else {
3909 l2cap_sock_clear_timer(sk);
3910 l2cap_sock_set_timer(sk, HZ / 10);
3911 }
3912 } else if (sk->sk_state == BT_CONNECT2) {
3913 struct l2cap_conn_rsp rsp;
3914 __u16 result;
3915
3916 if (!status) {
3917 sk->sk_state = BT_CONFIG;
3918 result = L2CAP_CR_SUCCESS;
3919 } else {
3920 sk->sk_state = BT_DISCONN;
3921 l2cap_sock_set_timer(sk, HZ / 10);
3922 result = L2CAP_CR_SEC_BLOCK;
3923 }
3924
3925 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3926 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3927 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003928 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003929 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
3930 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931 }
3932
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933 bh_unlock_sock(sk);
3934 }
3935
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003936 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003937
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938 return 0;
3939}
3940
3941static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3942{
3943 struct l2cap_conn *conn = hcon->l2cap_data;
3944
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003945 if (!conn)
3946 conn = l2cap_conn_add(hcon, 0);
3947
3948 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949 goto drop;
3950
3951 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3952
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003953 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003955 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003956 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957 int len;
3958
3959 if (conn->rx_len) {
3960 BT_ERR("Unexpected start frame (len %d)", skb->len);
3961 kfree_skb(conn->rx_skb);
3962 conn->rx_skb = NULL;
3963 conn->rx_len = 0;
3964 l2cap_conn_unreliable(conn, ECOMM);
3965 }
3966
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003967 /* Start fragment always begin with Basic L2CAP header */
3968 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969 BT_ERR("Frame is too short (len %d)", skb->len);
3970 l2cap_conn_unreliable(conn, ECOMM);
3971 goto drop;
3972 }
3973
3974 hdr = (struct l2cap_hdr *) skb->data;
3975 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003976 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977
3978 if (len == skb->len) {
3979 /* Complete frame received */
3980 l2cap_recv_frame(conn, skb);
3981 return 0;
3982 }
3983
3984 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3985
3986 if (skb->len > len) {
3987 BT_ERR("Frame is too long (len %d, expected len %d)",
3988 skb->len, len);
3989 l2cap_conn_unreliable(conn, ECOMM);
3990 goto drop;
3991 }
3992
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003993 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003994
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003995 if (chan && chan->sk) {
3996 struct sock *sk = chan->sk;
3997
3998 if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
3999 BT_ERR("Frame exceeding recv MTU (len %d, "
4000 "MTU %d)", len,
4001 l2cap_pi(sk)->imtu);
4002 bh_unlock_sock(sk);
4003 l2cap_conn_unreliable(conn, ECOMM);
4004 goto drop;
4005 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004006 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004007 }
4008
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004010 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4011 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004012 goto drop;
4013
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004014 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004015 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016 conn->rx_len = len - skb->len;
4017 } else {
4018 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4019
4020 if (!conn->rx_len) {
4021 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4022 l2cap_conn_unreliable(conn, ECOMM);
4023 goto drop;
4024 }
4025
4026 if (skb->len > conn->rx_len) {
4027 BT_ERR("Fragment is too long (len %d, expected %d)",
4028 skb->len, conn->rx_len);
4029 kfree_skb(conn->rx_skb);
4030 conn->rx_skb = NULL;
4031 conn->rx_len = 0;
4032 l2cap_conn_unreliable(conn, ECOMM);
4033 goto drop;
4034 }
4035
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004036 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004037 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004038 conn->rx_len -= skb->len;
4039
4040 if (!conn->rx_len) {
4041 /* Complete frame received */
4042 l2cap_recv_frame(conn, conn->rx_skb);
4043 conn->rx_skb = NULL;
4044 }
4045 }
4046
4047drop:
4048 kfree_skb(skb);
4049 return 0;
4050}
4051
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004052static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053{
4054 struct sock *sk;
4055 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056
4057 read_lock_bh(&l2cap_sk_list.lock);
4058
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004059 sk_for_each(sk, node, &l2cap_sk_list.head) {
4060 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004062 seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004063 batostr(&bt_sk(sk)->src),
4064 batostr(&bt_sk(sk)->dst),
4065 sk->sk_state, __le16_to_cpu(pi->psm),
4066 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004067 pi->imtu, pi->omtu, pi->sec_level,
4068 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004069 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004070
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004072
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004073 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074}
4075
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004076static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4077{
4078 return single_open(file, l2cap_debugfs_show, inode->i_private);
4079}
4080
4081static const struct file_operations l2cap_debugfs_fops = {
4082 .open = l2cap_debugfs_open,
4083 .read = seq_read,
4084 .llseek = seq_lseek,
4085 .release = single_release,
4086};
4087
4088static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090static struct hci_proto l2cap_hci_proto = {
4091 .name = "L2CAP",
4092 .id = HCI_PROTO_L2CAP,
4093 .connect_ind = l2cap_connect_ind,
4094 .connect_cfm = l2cap_connect_cfm,
4095 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004096 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004097 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098 .recv_acldata = l2cap_recv_acldata
4099};
4100
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004101int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102{
4103 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004104
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004105 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106 if (err < 0)
4107 return err;
4108
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004109 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004110 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004111 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112 goto error;
4113 }
4114
4115 err = hci_register_proto(&l2cap_hci_proto);
4116 if (err < 0) {
4117 BT_ERR("L2CAP protocol registration failed");
4118 bt_sock_unregister(BTPROTO_L2CAP);
4119 goto error;
4120 }
4121
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004122 if (bt_debugfs) {
4123 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4124 bt_debugfs, NULL, &l2cap_debugfs_fops);
4125 if (!l2cap_debugfs)
4126 BT_ERR("Failed to create L2CAP debug file");
4127 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129 return 0;
4130
4131error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004132 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004133 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134 return err;
4135}
4136
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004137void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004139 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004140
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004141 flush_workqueue(_busy_wq);
4142 destroy_workqueue(_busy_wq);
4143
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4145 BT_ERR("L2CAP protocol unregistration failed");
4146
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004147 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148}
4149
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004150module_param(disable_ertm, bool, 0644);
4151MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");