blob: 9e3f64f05d49d25931243475d00f2e11c8167aa5 [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) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030083 if (c->dcid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030084 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020085 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030086 return NULL;
87
Marcel Holtmann01394182006-07-03 10:02:46 +020088}
89
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030090static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020091{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030092 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030093
94 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030095 if (c->scid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030096 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020097 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030098 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +020099}
100
101/* Find channel with given SCID.
102 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300103static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200104{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300105 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300106
107 read_lock(&conn->chan_lock);
108 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300109 if (c)
110 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300111 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300112 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200113}
114
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300115static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200116{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300117 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300118
119 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300120 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300121 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200122 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300123 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200124}
125
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300126static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200127{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300128 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300129
130 read_lock(&conn->chan_lock);
131 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300132 if (c)
133 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300134 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300135 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200136}
137
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300138static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300139{
140 struct sock *sk;
141 struct hlist_node *node;
142 sk_for_each(sk, node, &l2cap_sk_list.head) {
143 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
144
145 if (chan->sport == psm && !bacmp(&bt_sk(sk)->src, src))
146 goto found;
147 }
148
149 sk = NULL;
150found:
151 return sk;
152}
153
154int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
155{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300156 int err;
157
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300158 write_lock_bh(&l2cap_sk_list.lock);
159
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300160 if (psm && __l2cap_get_sock_by_addr(psm, src)) {
161 err = -EADDRINUSE;
162 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300163 }
164
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300165 if (psm) {
166 chan->psm = psm;
167 chan->sport = psm;
168 err = 0;
169 } else {
170 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300171
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300172 err = -EINVAL;
173 for (p = 0x1001; p < 0x1100; p += 2)
174 if (!__l2cap_get_sock_by_addr(cpu_to_le16(p), src)) {
175 chan->psm = cpu_to_le16(p);
176 chan->sport = cpu_to_le16(p);
177 err = 0;
178 break;
179 }
180 }
181
182done:
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300183 write_unlock_bh(&l2cap_sk_list.lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300184 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300185}
186
187int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
188{
189 write_lock_bh(&l2cap_sk_list.lock);
190
191 chan->scid = scid;
192
193 write_unlock_bh(&l2cap_sk_list.lock);
194
195 return 0;
196}
197
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300198static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200199{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300200 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200201
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300202 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300203 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200204 return cid;
205 }
206
207 return 0;
208}
209
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300210struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200211{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300212 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200213
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300214 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
215 if (!chan)
216 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200217
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300218 chan->sk = sk;
219
220 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200221}
222
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300223void l2cap_chan_free(struct l2cap_chan *chan)
224{
225 kfree(chan);
226}
227
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300228static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200229{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300230 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200231
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300232 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300233 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200234
Marcel Holtmann2950f212009-02-12 14:02:50 +0100235 conn->disc_reason = 0x13;
236
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300237 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200238
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300239 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Ville Tervob62f3282011-02-10 22:38:50 -0300240 if (conn->hcon->type == LE_LINK) {
241 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300242 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300243 chan->scid = L2CAP_CID_LE_DATA;
244 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300245 } else {
246 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300247 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300248 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300249 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200250 } else if (sk->sk_type == SOCK_DGRAM) {
251 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300252 chan->scid = L2CAP_CID_CONN_LESS;
253 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300254 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200255 } else {
256 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300257 chan->scid = L2CAP_CID_SIGNALING;
258 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300259 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200260 }
261
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300262 sock_hold(sk);
263
264 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200265}
266
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900267/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200268 * Must be called on the locked socket. */
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300269void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200270{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300271 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300272 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200273 struct sock *parent = bt_sk(sk)->parent;
274
275 l2cap_sock_clear_timer(sk);
276
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300277 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200278
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900279 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300280 /* Delete from channel list */
281 write_lock_bh(&conn->chan_lock);
282 list_del(&chan->list);
283 write_unlock_bh(&conn->chan_lock);
284 __sock_put(sk);
285
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300286 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200287 hci_conn_put(conn->hcon);
288 }
289
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200290 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200291 sock_set_flag(sk, SOCK_ZAPPED);
292
293 if (err)
294 sk->sk_err = err;
295
296 if (parent) {
297 bt_accept_unlink(sk);
298 parent->sk_data_ready(parent, 0);
299 } else
300 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300301
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300302 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE &&
303 chan->conf_state & L2CAP_CONF_INPUT_DONE))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300304 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300305
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300306 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300307
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300308 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300309 struct srej_list *l, *tmp;
310
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300311 del_timer(&chan->retrans_timer);
312 del_timer(&chan->monitor_timer);
313 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300314
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300315 skb_queue_purge(&chan->srej_q);
316 skb_queue_purge(&chan->busy_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300317
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300318 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300319 list_del(&l->list);
320 kfree(l);
321 }
322 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200323}
324
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300325static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530326{
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300327 struct sock *sk = chan->sk;
328
Johan Hedberg8556edd32011-01-19 12:06:50 +0530329 if (sk->sk_type == SOCK_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300330 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530331 case BT_SECURITY_HIGH:
332 return HCI_AT_DEDICATED_BONDING_MITM;
333 case BT_SECURITY_MEDIUM:
334 return HCI_AT_DEDICATED_BONDING;
335 default:
336 return HCI_AT_NO_BONDING;
337 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300338 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300339 if (chan->sec_level == BT_SECURITY_LOW)
340 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530341
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300342 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530343 return HCI_AT_NO_BONDING_MITM;
344 else
345 return HCI_AT_NO_BONDING;
346 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300347 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530348 case BT_SECURITY_HIGH:
349 return HCI_AT_GENERAL_BONDING_MITM;
350 case BT_SECURITY_MEDIUM:
351 return HCI_AT_GENERAL_BONDING;
352 default:
353 return HCI_AT_NO_BONDING;
354 }
355 }
356}
357
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200358/* Service level security */
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300359static inline int l2cap_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200360{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300361 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100362 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200363
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300364 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100365
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300366 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200367}
368
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200369u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200370{
371 u8 id;
372
373 /* Get next available identificator.
374 * 1 - 128 are used by kernel.
375 * 129 - 199 are reserved.
376 * 200 - 254 are used by utilities like l2ping, etc.
377 */
378
379 spin_lock_bh(&conn->lock);
380
381 if (++conn->tx_ident > 128)
382 conn->tx_ident = 1;
383
384 id = conn->tx_ident;
385
386 spin_unlock_bh(&conn->lock);
387
388 return id;
389}
390
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200391void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200392{
393 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200394 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200395
396 BT_DBG("code 0x%2.2x", code);
397
398 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300399 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200400
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200401 if (lmp_no_flush_capable(conn->hcon->hdev))
402 flags = ACL_START_NO_FLUSH;
403 else
404 flags = ACL_START;
405
406 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200407}
408
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300409static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300410{
411 struct sk_buff *skb;
412 struct l2cap_hdr *lh;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300413 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300414 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300415 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300416 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200417 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300418
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300419 if (sk->sk_state != BT_CONNECTED)
420 return;
421
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300422 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300423 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300424
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300425 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300426
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300427 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300428 control |= L2CAP_CTRL_FRAME_TYPE;
429
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300430 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300431 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300432 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300433 }
434
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300435 if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300436 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300437 chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300438 }
439
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300440 skb = bt_skb_alloc(count, GFP_ATOMIC);
441 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300442 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300443
444 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300445 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300446 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300447 put_unaligned_le16(control, skb_put(skb, 2));
448
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300449 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300450 u16 fcs = crc16(0, (u8 *)lh, count - 2);
451 put_unaligned_le16(fcs, skb_put(skb, 2));
452 }
453
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200454 if (lmp_no_flush_capable(conn->hcon->hdev))
455 flags = ACL_START_NO_FLUSH;
456 else
457 flags = ACL_START;
458
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300459 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300460}
461
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300462static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300463{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300464 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300465 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300466 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300467 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300468 control |= L2CAP_SUPER_RCV_READY;
469
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300470 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300471
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300472 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300473}
474
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300475static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300476{
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300477 return !(chan->conf_state & L2CAP_CONF_CONNECT_PEND);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300478}
479
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300480static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200481{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300482 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200483
484 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100485 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
486 return;
487
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300488 if (l2cap_check_security(chan) &&
489 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200490 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300491 req.scid = cpu_to_le16(chan->scid);
492 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200493
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300494 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300495 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200496
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300497 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
498 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200499 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200500 } else {
501 struct l2cap_info_req req;
502 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
503
504 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
505 conn->info_ident = l2cap_get_ident(conn);
506
507 mod_timer(&conn->info_timer, jiffies +
508 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
509
510 l2cap_send_cmd(conn, conn->info_ident,
511 L2CAP_INFO_REQ, sizeof(req), &req);
512 }
513}
514
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300515static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
516{
517 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300518 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300519 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
520
521 switch (mode) {
522 case L2CAP_MODE_ERTM:
523 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
524 case L2CAP_MODE_STREAMING:
525 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
526 default:
527 return 0x00;
528 }
529}
530
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300531void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300532{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300533 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300534 struct l2cap_disconn_req req;
535
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300536 if (!conn)
537 return;
538
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300539 sk = chan->sk;
540
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300541 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300542 del_timer(&chan->retrans_timer);
543 del_timer(&chan->monitor_timer);
544 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300545 }
546
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300547 req.dcid = cpu_to_le16(chan->dcid);
548 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300549 l2cap_send_cmd(conn, l2cap_get_ident(conn),
550 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300551
552 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300553 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300554}
555
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200557static void l2cap_conn_start(struct l2cap_conn *conn)
558{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300559 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200560
561 BT_DBG("conn %p", conn);
562
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300563 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200564
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300565 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300566 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300567
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200568 bh_lock_sock(sk);
569
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300570 if (sk->sk_type != SOCK_SEQPACKET &&
571 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200572 bh_unlock_sock(sk);
573 continue;
574 }
575
576 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300577 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300578
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300579 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300580 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300581 bh_unlock_sock(sk);
582 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200583 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300584
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300585 if (!l2cap_mode_supported(chan->mode,
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300586 conn->feat_mask)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300587 && chan->conf_state &
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300588 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300589 /* __l2cap_sock_close() calls list_del(chan)
590 * so release the lock */
591 read_unlock_bh(&conn->chan_lock);
592 __l2cap_sock_close(sk, ECONNRESET);
593 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300594 bh_unlock_sock(sk);
595 continue;
596 }
597
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300598 req.scid = cpu_to_le16(chan->scid);
599 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300600
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300601 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300602 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300603
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300604 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
605 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300606
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200607 } else if (sk->sk_state == BT_CONNECT2) {
608 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300609 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300610 rsp.scid = cpu_to_le16(chan->dcid);
611 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200612
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300613 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100614 if (bt_sk(sk)->defer_setup) {
615 struct sock *parent = bt_sk(sk)->parent;
616 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
617 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
618 parent->sk_data_ready(parent, 0);
619
620 } else {
621 sk->sk_state = BT_CONFIG;
622 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
623 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
624 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200625 } else {
626 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
627 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
628 }
629
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300630 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
631 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300632
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300633 if (chan->conf_state & L2CAP_CONF_REQ_SENT ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300634 rsp.result != L2CAP_CR_SUCCESS) {
635 bh_unlock_sock(sk);
636 continue;
637 }
638
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300639 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300640 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300641 l2cap_build_conf_req(chan, buf), buf);
642 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200643 }
644
645 bh_unlock_sock(sk);
646 }
647
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300648 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200649}
650
Ville Tervob62f3282011-02-10 22:38:50 -0300651/* Find socket with cid and source bdaddr.
652 * Returns closest match, locked.
653 */
654static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
655{
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300656 struct sock *sk = NULL, *sk1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300657 struct hlist_node *node;
658
659 read_lock(&l2cap_sk_list.lock);
660
661 sk_for_each(sk, node, &l2cap_sk_list.head) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300662 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
663
Ville Tervob62f3282011-02-10 22:38:50 -0300664 if (state && sk->sk_state != state)
665 continue;
666
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300667 if (chan->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300668 /* Exact match. */
669 if (!bacmp(&bt_sk(sk)->src, src))
670 break;
671
672 /* Closest match */
673 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
674 sk1 = sk;
675 }
676 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300677
Ville Tervob62f3282011-02-10 22:38:50 -0300678 read_unlock(&l2cap_sk_list.lock);
679
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300680 return node ? sk : sk1;
Ville Tervob62f3282011-02-10 22:38:50 -0300681}
682
683static void l2cap_le_conn_ready(struct l2cap_conn *conn)
684{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300685 struct sock *parent, *sk;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300686 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300687
688 BT_DBG("");
689
690 /* Check if we have socket listening on cid */
691 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
692 conn->src);
693 if (!parent)
694 return;
695
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300696 bh_lock_sock(parent);
697
Ville Tervob62f3282011-02-10 22:38:50 -0300698 /* Check for backlog size */
699 if (sk_acceptq_is_full(parent)) {
700 BT_DBG("backlog full %d", parent->sk_ack_backlog);
701 goto clean;
702 }
703
704 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
705 if (!sk)
706 goto clean;
707
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300708 chan = l2cap_chan_alloc(sk);
709 if (!chan) {
710 l2cap_sock_kill(sk);
711 goto clean;
712 }
713
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300714 l2cap_pi(sk)->chan = chan;
715
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300716 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300717
718 hci_conn_hold(conn->hcon);
719
720 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300721
Ville Tervob62f3282011-02-10 22:38:50 -0300722 bacpy(&bt_sk(sk)->src, conn->src);
723 bacpy(&bt_sk(sk)->dst, conn->dst);
724
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300725 bt_accept_enqueue(parent, sk);
726
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300727 __l2cap_chan_add(conn, chan);
728
Ville Tervob62f3282011-02-10 22:38:50 -0300729 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
730
731 sk->sk_state = BT_CONNECTED;
732 parent->sk_data_ready(parent, 0);
733
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300734 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300735
736clean:
737 bh_unlock_sock(parent);
738}
739
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200740static void l2cap_conn_ready(struct l2cap_conn *conn)
741{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300742 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200743
744 BT_DBG("conn %p", conn);
745
Ville Tervob62f3282011-02-10 22:38:50 -0300746 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
747 l2cap_le_conn_ready(conn);
748
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300749 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200750
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300751 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300752 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300753
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200754 bh_lock_sock(sk);
755
Ville Tervoacd7d372011-02-10 22:38:49 -0300756 if (conn->hcon->type == LE_LINK) {
757 l2cap_sock_clear_timer(sk);
758 sk->sk_state = BT_CONNECTED;
759 sk->sk_state_change(sk);
760 }
761
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300762 if (sk->sk_type != SOCK_SEQPACKET &&
763 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200764 l2cap_sock_clear_timer(sk);
765 sk->sk_state = BT_CONNECTED;
766 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200767 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300768 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200769
770 bh_unlock_sock(sk);
771 }
772
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300773 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200774}
775
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200776/* Notify sockets that we cannot guaranty reliability anymore */
777static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
778{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300779 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200780
781 BT_DBG("conn %p", conn);
782
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300783 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200784
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300785 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300786 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300787
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300788 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200789 sk->sk_err = err;
790 }
791
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300792 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200793}
794
795static void l2cap_info_timeout(unsigned long arg)
796{
797 struct l2cap_conn *conn = (void *) arg;
798
Marcel Holtmann984947d2009-02-06 23:35:19 +0100799 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100800 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100801
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200802 l2cap_conn_start(conn);
803}
804
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
806{
Marcel Holtmann01394182006-07-03 10:02:46 +0200807 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808
Marcel Holtmann01394182006-07-03 10:02:46 +0200809 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 return conn;
811
Marcel Holtmann01394182006-07-03 10:02:46 +0200812 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
813 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815
816 hcon->l2cap_data = conn;
817 conn->hcon = hcon;
818
Marcel Holtmann01394182006-07-03 10:02:46 +0200819 BT_DBG("hcon %p conn %p", hcon, conn);
820
Ville Tervoacd7d372011-02-10 22:38:49 -0300821 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
822 conn->mtu = hcon->hdev->le_mtu;
823 else
824 conn->mtu = hcon->hdev->acl_mtu;
825
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 conn->src = &hcon->hdev->bdaddr;
827 conn->dst = &hcon->dst;
828
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200829 conn->feat_mask = 0;
830
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300832 rwlock_init(&conn->chan_lock);
833
834 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835
Ville Tervob62f3282011-02-10 22:38:50 -0300836 if (hcon->type != LE_LINK)
837 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000838 (unsigned long) conn);
839
Marcel Holtmann2950f212009-02-12 14:02:50 +0100840 conn->disc_reason = 0x13;
841
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 return conn;
843}
844
Marcel Holtmann01394182006-07-03 10:02:46 +0200845static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846{
Marcel Holtmann01394182006-07-03 10:02:46 +0200847 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300848 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 struct sock *sk;
850
Marcel Holtmann01394182006-07-03 10:02:46 +0200851 if (!conn)
852 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853
854 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
855
Wei Yongjun7585b972009-02-25 18:29:52 +0800856 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857
858 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300859 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300860 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300862 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 bh_unlock_sock(sk);
864 l2cap_sock_kill(sk);
865 }
866
Dave Young8e8440f2008-03-03 12:18:55 -0800867 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
868 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800869
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 hcon->l2cap_data = NULL;
871 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872}
873
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300874static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300876 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300877 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300878 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879}
880
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882
883/* Find socket with psm and source bdaddr.
884 * Returns closest match.
885 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000886static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887{
888 struct sock *sk = NULL, *sk1 = NULL;
889 struct hlist_node *node;
890
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000891 read_lock(&l2cap_sk_list.lock);
892
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 sk_for_each(sk, node, &l2cap_sk_list.head) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300894 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
895
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 if (state && sk->sk_state != state)
897 continue;
898
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300899 if (chan->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 /* Exact match. */
901 if (!bacmp(&bt_sk(sk)->src, src))
902 break;
903
904 /* Closest match */
905 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
906 sk1 = sk;
907 }
908 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000911
912 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913}
914
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -0300915int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300917 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 bdaddr_t *src = &bt_sk(sk)->src;
919 bdaddr_t *dst = &bt_sk(sk)->dst;
920 struct l2cap_conn *conn;
921 struct hci_conn *hcon;
922 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200923 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200924 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100926 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300927 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300929 hdev = hci_get_route(dst, src);
930 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 return -EHOSTUNREACH;
932
933 hci_dev_lock_bh(hdev);
934
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300935 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200936
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300937 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -0300938 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300939 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300940 else
941 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300942 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300943
Ville Tervo30e76272011-02-22 16:10:53 -0300944 if (IS_ERR(hcon)) {
945 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300947 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948
949 conn = l2cap_conn_add(hcon, 0);
950 if (!conn) {
951 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300952 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 goto done;
954 }
955
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 /* Update source addr of the socket */
957 bacpy(src, conn->src);
958
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300959 l2cap_chan_add(conn, chan);
960
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 sk->sk_state = BT_CONNECT;
962 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
963
964 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300965 if (sk->sk_type != SOCK_SEQPACKET &&
966 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 l2cap_sock_clear_timer(sk);
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300968 if (l2cap_check_security(chan))
Johan Hedbergd00ef242011-01-19 12:06:51 +0530969 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200970 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300971 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 }
973
Ville Tervo30e76272011-02-22 16:10:53 -0300974 err = 0;
975
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976done:
977 hci_dev_unlock_bh(hdev);
978 hci_dev_put(hdev);
979 return err;
980}
981
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200982int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300983{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300984 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300985 DECLARE_WAITQUEUE(wait, current);
986 int err = 0;
987 int timeo = HZ/5;
988
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200989 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300990 while ((chan->unacked_frames > 0 && chan->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300991 set_current_state(TASK_INTERRUPTIBLE);
992
993 if (!timeo)
994 timeo = HZ/5;
995
996 if (signal_pending(current)) {
997 err = sock_intr_errno(timeo);
998 break;
999 }
1000
1001 release_sock(sk);
1002 timeo = schedule_timeout(timeo);
1003 lock_sock(sk);
1004
1005 err = sock_error(sk);
1006 if (err)
1007 break;
1008 }
1009 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001010 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001011 return err;
1012}
1013
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001014static void l2cap_monitor_timeout(unsigned long arg)
1015{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001016 struct l2cap_chan *chan = (void *) arg;
1017 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001018
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001019 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001020
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001021 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001022 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001023 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001024 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001025 return;
1026 }
1027
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001028 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001029 __mod_monitor_timer();
1030
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001031 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001032 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001033}
1034
1035static void l2cap_retrans_timeout(unsigned long arg)
1036{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001037 struct l2cap_chan *chan = (void *) arg;
1038 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001039
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001040 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001041
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001042 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001043 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001044 __mod_monitor_timer();
1045
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001046 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001047
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001048 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001049 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001050}
1051
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001052static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001053{
1054 struct sk_buff *skb;
1055
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001056 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001057 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001058 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001059 break;
1060
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001061 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001062 kfree_skb(skb);
1063
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001064 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001065 }
1066
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001067 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001068 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001069}
1070
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001071void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001072{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001073 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001074 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001075
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001076 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001077
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001078 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001079 flags = ACL_START_NO_FLUSH;
1080 else
1081 flags = ACL_START;
1082
1083 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001084}
1085
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001086void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001087{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001088 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001089 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001090
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001091 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001092 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001093 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001094 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001095
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001096 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001097 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1098 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001099 }
1100
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001101 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001102
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001103 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001104 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001105}
1106
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001107static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001108{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001109 struct sk_buff *skb, *tx_skb;
1110 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001111
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001112 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001113 if (!skb)
1114 return;
1115
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001116 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001117 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001118 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001119
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001120 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001121 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001122
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001123 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001124
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001125 if (chan->remote_max_tx &&
1126 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001127 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001128 return;
1129 }
1130
1131 tx_skb = skb_clone(skb, GFP_ATOMIC);
1132 bt_cb(skb)->retries++;
1133 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001134 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001135
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001136 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001137 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001138 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001139 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001140
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001141 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001142 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001143
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001144 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1145
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001146 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001147 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1148 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1149 }
1150
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001151 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001152}
1153
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001154int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001155{
1156 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001157 struct sock *sk = chan->sk;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001158 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001159 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001160
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001161 if (sk->sk_state != BT_CONNECTED)
1162 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001163
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001164 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001165
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001166 if (chan->remote_max_tx &&
1167 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001168 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001169 break;
1170 }
1171
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001172 tx_skb = skb_clone(skb, GFP_ATOMIC);
1173
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001174 bt_cb(skb)->retries++;
1175
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001176 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001177 control &= L2CAP_CTRL_SAR;
1178
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001179 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001180 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001181 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001182 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001183 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1184 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001185 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1186
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001187
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001188 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001189 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1190 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1191 }
1192
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001193 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001194
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001195 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001196
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001197 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1198 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001199
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301200 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001201 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301202
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001203 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001204
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001205 if (skb_queue_is_last(&chan->tx_q, skb))
1206 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001207 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001208 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001209
1210 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001211 }
1212
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001213 return nsent;
1214}
1215
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001216static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001217{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001218 int ret;
1219
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001220 if (!skb_queue_empty(&chan->tx_q))
1221 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001222
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001223 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001224 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001225 return ret;
1226}
1227
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001228static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001229{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001230 u16 control = 0;
1231
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001232 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001233
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001234 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001235 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001236 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1237 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001238 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001239 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001240
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001241 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001242 return;
1243
1244 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001245 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001246}
1247
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001248static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001249{
1250 struct srej_list *tail;
1251 u16 control;
1252
1253 control = L2CAP_SUPER_SELECT_REJECT;
1254 control |= L2CAP_CTRL_FINAL;
1255
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001256 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001257 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1258
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001259 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001260}
1261
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001262static 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 -07001263{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001264 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001265 struct sk_buff **frag;
1266 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001268 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001269 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270
1271 sent += count;
1272 len -= count;
1273
1274 /* Continuation fragments (no L2CAP header) */
1275 frag = &skb_shinfo(skb)->frag_list;
1276 while (len) {
1277 count = min_t(unsigned int, conn->mtu, len);
1278
1279 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1280 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001281 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001282 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1283 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284
1285 sent += count;
1286 len -= count;
1287
1288 frag = &(*frag)->next;
1289 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290
1291 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001292}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001294struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001295{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001296 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001297 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001298 struct sk_buff *skb;
1299 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1300 struct l2cap_hdr *lh;
1301
1302 BT_DBG("sk %p len %d", sk, (int)len);
1303
1304 count = min_t(unsigned int, (conn->mtu - hlen), len);
1305 skb = bt_skb_send_alloc(sk, count + hlen,
1306 msg->msg_flags & MSG_DONTWAIT, &err);
1307 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001308 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001309
1310 /* Create L2CAP header */
1311 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001312 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001313 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001314 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001315
1316 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1317 if (unlikely(err < 0)) {
1318 kfree_skb(skb);
1319 return ERR_PTR(err);
1320 }
1321 return skb;
1322}
1323
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001324struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001325{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001326 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001327 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001328 struct sk_buff *skb;
1329 int err, count, hlen = L2CAP_HDR_SIZE;
1330 struct l2cap_hdr *lh;
1331
1332 BT_DBG("sk %p len %d", sk, (int)len);
1333
1334 count = min_t(unsigned int, (conn->mtu - hlen), len);
1335 skb = bt_skb_send_alloc(sk, count + hlen,
1336 msg->msg_flags & MSG_DONTWAIT, &err);
1337 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001338 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001339
1340 /* Create L2CAP header */
1341 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001342 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001343 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1344
1345 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1346 if (unlikely(err < 0)) {
1347 kfree_skb(skb);
1348 return ERR_PTR(err);
1349 }
1350 return skb;
1351}
1352
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001353struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001354{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001355 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001356 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001357 struct sk_buff *skb;
1358 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1359 struct l2cap_hdr *lh;
1360
1361 BT_DBG("sk %p len %d", sk, (int)len);
1362
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001363 if (!conn)
1364 return ERR_PTR(-ENOTCONN);
1365
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001366 if (sdulen)
1367 hlen += 2;
1368
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001369 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001370 hlen += 2;
1371
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001372 count = min_t(unsigned int, (conn->mtu - hlen), len);
1373 skb = bt_skb_send_alloc(sk, count + hlen,
1374 msg->msg_flags & MSG_DONTWAIT, &err);
1375 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001376 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001377
1378 /* Create L2CAP header */
1379 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001380 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001381 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1382 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001383 if (sdulen)
1384 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001385
1386 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1387 if (unlikely(err < 0)) {
1388 kfree_skb(skb);
1389 return ERR_PTR(err);
1390 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001391
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001392 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001393 put_unaligned_le16(0, skb_put(skb, 2));
1394
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001395 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001396 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397}
1398
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001399int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001400{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001401 struct sk_buff *skb;
1402 struct sk_buff_head sar_queue;
1403 u16 control;
1404 size_t size = 0;
1405
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001406 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001407 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001408 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001409 if (IS_ERR(skb))
1410 return PTR_ERR(skb);
1411
1412 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001413 len -= chan->remote_mps;
1414 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001415
1416 while (len > 0) {
1417 size_t buflen;
1418
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001419 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001420 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001421 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001422 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001423 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001424 buflen = len;
1425 }
1426
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001427 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001428 if (IS_ERR(skb)) {
1429 skb_queue_purge(&sar_queue);
1430 return PTR_ERR(skb);
1431 }
1432
1433 __skb_queue_tail(&sar_queue, skb);
1434 len -= buflen;
1435 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001436 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001437 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1438 if (chan->tx_send_head == NULL)
1439 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001440
1441 return size;
1442}
1443
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444static void l2cap_chan_ready(struct sock *sk)
1445{
1446 struct sock *parent = bt_sk(sk)->parent;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001447 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448
1449 BT_DBG("sk %p, parent %p", sk, parent);
1450
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001451 chan->conf_state = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 l2cap_sock_clear_timer(sk);
1453
1454 if (!parent) {
1455 /* Outgoing channel.
1456 * Wake up socket sleeping on connect.
1457 */
1458 sk->sk_state = BT_CONNECTED;
1459 sk->sk_state_change(sk);
1460 } else {
1461 /* Incoming channel.
1462 * Wake up socket sleeping on accept.
1463 */
1464 parent->sk_data_ready(parent, 0);
1465 }
1466}
1467
1468/* Copy frame to all raw sockets on that connection */
1469static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1470{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001472 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473
1474 BT_DBG("conn %p", conn);
1475
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001476 read_lock(&conn->chan_lock);
1477 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001478 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 if (sk->sk_type != SOCK_RAW)
1480 continue;
1481
1482 /* Don't send frame to the socket it came from */
1483 if (skb->sk == sk)
1484 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001485 nskb = skb_clone(skb, GFP_ATOMIC);
1486 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 continue;
1488
1489 if (sock_queue_rcv_skb(sk, nskb))
1490 kfree_skb(nskb);
1491 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001492 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493}
1494
1495/* ---- L2CAP signalling commands ---- */
1496static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1497 u8 code, u8 ident, u16 dlen, void *data)
1498{
1499 struct sk_buff *skb, **frag;
1500 struct l2cap_cmd_hdr *cmd;
1501 struct l2cap_hdr *lh;
1502 int len, count;
1503
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001504 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1505 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506
1507 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1508 count = min_t(unsigned int, conn->mtu, len);
1509
1510 skb = bt_skb_alloc(count, GFP_ATOMIC);
1511 if (!skb)
1512 return NULL;
1513
1514 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001515 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001516
1517 if (conn->hcon->type == LE_LINK)
1518 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1519 else
1520 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521
1522 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1523 cmd->code = code;
1524 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001525 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526
1527 if (dlen) {
1528 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1529 memcpy(skb_put(skb, count), data, count);
1530 data += count;
1531 }
1532
1533 len -= skb->len;
1534
1535 /* Continuation fragments (no L2CAP header) */
1536 frag = &skb_shinfo(skb)->frag_list;
1537 while (len) {
1538 count = min_t(unsigned int, conn->mtu, len);
1539
1540 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1541 if (!*frag)
1542 goto fail;
1543
1544 memcpy(skb_put(*frag, count), data, count);
1545
1546 len -= count;
1547 data += count;
1548
1549 frag = &(*frag)->next;
1550 }
1551
1552 return skb;
1553
1554fail:
1555 kfree_skb(skb);
1556 return NULL;
1557}
1558
1559static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1560{
1561 struct l2cap_conf_opt *opt = *ptr;
1562 int len;
1563
1564 len = L2CAP_CONF_OPT_SIZE + opt->len;
1565 *ptr += len;
1566
1567 *type = opt->type;
1568 *olen = opt->len;
1569
1570 switch (opt->len) {
1571 case 1:
1572 *val = *((u8 *) opt->val);
1573 break;
1574
1575 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001576 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 break;
1578
1579 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001580 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 break;
1582
1583 default:
1584 *val = (unsigned long) opt->val;
1585 break;
1586 }
1587
1588 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1589 return len;
1590}
1591
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1593{
1594 struct l2cap_conf_opt *opt = *ptr;
1595
1596 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1597
1598 opt->type = type;
1599 opt->len = len;
1600
1601 switch (len) {
1602 case 1:
1603 *((u8 *) opt->val) = val;
1604 break;
1605
1606 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001607 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 break;
1609
1610 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001611 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 break;
1613
1614 default:
1615 memcpy(opt->val, (void *) val, len);
1616 break;
1617 }
1618
1619 *ptr += L2CAP_CONF_OPT_SIZE + len;
1620}
1621
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001622static void l2cap_ack_timeout(unsigned long arg)
1623{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001624 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001625
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001626 bh_lock_sock(chan->sk);
1627 l2cap_send_ack(chan);
1628 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001629}
1630
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001631static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001632{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001633 struct sock *sk = chan->sk;
1634
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001635 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001636 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001637 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001638 chan->num_acked = 0;
1639 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001640
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001641 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1642 (unsigned long) chan);
1643 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1644 (unsigned long) chan);
1645 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001646
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001647 skb_queue_head_init(&chan->srej_q);
1648 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001649
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001650 INIT_LIST_HEAD(&chan->srej_l);
1651
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001652 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001653
1654 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001655}
1656
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001657static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1658{
1659 switch (mode) {
1660 case L2CAP_MODE_STREAMING:
1661 case L2CAP_MODE_ERTM:
1662 if (l2cap_mode_supported(mode, remote_feat_mask))
1663 return mode;
1664 /* fall through */
1665 default:
1666 return L2CAP_MODE_BASIC;
1667 }
1668}
1669
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001670static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001673 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 void *ptr = req->data;
1675
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001676 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001678 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001679 goto done;
1680
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001681 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001682 case L2CAP_MODE_STREAMING:
1683 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001684 if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001685 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001686
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001687 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001688 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001689 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001690 break;
1691 }
1692
1693done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001694 if (chan->imtu != L2CAP_DEFAULT_MTU)
1695 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001696
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001697 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001698 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001699 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1700 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001701 break;
1702
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001703 rfc.mode = L2CAP_MODE_BASIC;
1704 rfc.txwin_size = 0;
1705 rfc.max_transmit = 0;
1706 rfc.retrans_timeout = 0;
1707 rfc.monitor_timeout = 0;
1708 rfc.max_pdu_size = 0;
1709
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001710 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1711 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001712 break;
1713
1714 case L2CAP_MODE_ERTM:
1715 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001716 rfc.txwin_size = chan->tx_win;
1717 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001718 rfc.retrans_timeout = 0;
1719 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001720 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001721 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1722 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001723
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001724 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1725 (unsigned long) &rfc);
1726
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001727 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001728 break;
1729
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001730 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001731 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001732 chan->fcs = L2CAP_FCS_NONE;
1733 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001734 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001735 break;
1736
1737 case L2CAP_MODE_STREAMING:
1738 rfc.mode = L2CAP_MODE_STREAMING;
1739 rfc.txwin_size = 0;
1740 rfc.max_transmit = 0;
1741 rfc.retrans_timeout = 0;
1742 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001743 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001744 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1745 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001746
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001747 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1748 (unsigned long) &rfc);
1749
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001750 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001751 break;
1752
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001753 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001754 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001755 chan->fcs = L2CAP_FCS_NONE;
1756 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001757 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001758 break;
1759 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001761 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001762 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763
1764 return ptr - data;
1765}
1766
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001767static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001769 struct l2cap_conf_rsp *rsp = data;
1770 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001771 void *req = chan->conf_req;
1772 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001773 int type, hint, olen;
1774 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001775 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001776 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001777 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001779 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001780
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001781 while (len >= L2CAP_CONF_OPT_SIZE) {
1782 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001784 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001785 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001786
1787 switch (type) {
1788 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001789 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001790 break;
1791
1792 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001793 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001794 break;
1795
1796 case L2CAP_CONF_QOS:
1797 break;
1798
Marcel Holtmann6464f352007-10-20 13:39:51 +02001799 case L2CAP_CONF_RFC:
1800 if (olen == sizeof(rfc))
1801 memcpy(&rfc, (void *) val, olen);
1802 break;
1803
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001804 case L2CAP_CONF_FCS:
1805 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001806 chan->conf_state |= L2CAP_CONF_NO_FCS_RECV;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001807
1808 break;
1809
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001810 default:
1811 if (hint)
1812 break;
1813
1814 result = L2CAP_CONF_UNKNOWN;
1815 *((u8 *) ptr++) = type;
1816 break;
1817 }
1818 }
1819
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001820 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001821 goto done;
1822
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001823 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001824 case L2CAP_MODE_STREAMING:
1825 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001826 if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001827 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001828 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001829 break;
1830 }
1831
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001832 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001833 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001834
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001835 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001836 }
1837
1838done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001839 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001840 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001841 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001842
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001843 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001844 return -ECONNREFUSED;
1845
1846 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1847 sizeof(rfc), (unsigned long) &rfc);
1848 }
1849
1850
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001851 if (result == L2CAP_CONF_SUCCESS) {
1852 /* Configure output options and let the other side know
1853 * which ones we don't like. */
1854
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001855 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1856 result = L2CAP_CONF_UNACCEPT;
1857 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001858 chan->omtu = mtu;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001859 chan->conf_state |= L2CAP_CONF_MTU_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001860 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001861 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001862
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001863 switch (rfc.mode) {
1864 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001865 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001866 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001867 break;
1868
1869 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001870 chan->remote_tx_win = rfc.txwin_size;
1871 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001872
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001873 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
1874 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001875
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001876 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001877
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001878 rfc.retrans_timeout =
1879 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1880 rfc.monitor_timeout =
1881 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001882
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001883 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001884
1885 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1886 sizeof(rfc), (unsigned long) &rfc);
1887
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001888 break;
1889
1890 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001891 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
1892 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001893
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001894 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001895
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001896 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001897
1898 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1899 sizeof(rfc), (unsigned long) &rfc);
1900
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001901 break;
1902
1903 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001904 result = L2CAP_CONF_UNACCEPT;
1905
1906 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001907 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001908 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001909
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001910 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001911 chan->conf_state |= L2CAP_CONF_OUTPUT_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001912 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001913 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001914 rsp->result = cpu_to_le16(result);
1915 rsp->flags = cpu_to_le16(0x0000);
1916
1917 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918}
1919
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001920static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001921{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001922 struct l2cap_conf_req *req = data;
1923 void *ptr = req->data;
1924 int type, olen;
1925 unsigned long val;
1926 struct l2cap_conf_rfc rfc;
1927
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001928 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001929
1930 while (len >= L2CAP_CONF_OPT_SIZE) {
1931 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1932
1933 switch (type) {
1934 case L2CAP_CONF_MTU:
1935 if (val < L2CAP_DEFAULT_MIN_MTU) {
1936 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001937 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001938 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001939 chan->imtu = val;
1940 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001941 break;
1942
1943 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001944 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001945 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001946 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001947 break;
1948
1949 case L2CAP_CONF_RFC:
1950 if (olen == sizeof(rfc))
1951 memcpy(&rfc, (void *)val, olen);
1952
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001953 if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001954 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001955 return -ECONNREFUSED;
1956
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001957 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001958
1959 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1960 sizeof(rfc), (unsigned long) &rfc);
1961 break;
1962 }
1963 }
1964
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001965 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001966 return -ECONNREFUSED;
1967
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001968 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001969
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001970 if (*result == L2CAP_CONF_SUCCESS) {
1971 switch (rfc.mode) {
1972 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001973 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1974 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
1975 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001976 break;
1977 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001978 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001979 }
1980 }
1981
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001982 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001983 req->flags = cpu_to_le16(0x0000);
1984
1985 return ptr - data;
1986}
1987
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001988static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989{
1990 struct l2cap_conf_rsp *rsp = data;
1991 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001993 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001995 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001996 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001997 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998
1999 return ptr - data;
2000}
2001
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002002void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002003{
2004 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002005 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002006 u8 buf[128];
2007
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002008 rsp.scid = cpu_to_le16(chan->dcid);
2009 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002010 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2011 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2012 l2cap_send_cmd(conn, chan->ident,
2013 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2014
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002015 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002016 return;
2017
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002018 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002019 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2020 l2cap_build_conf_req(chan, buf), buf);
2021 chan->num_conf_req++;
2022}
2023
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002024static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002025{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002026 int type, olen;
2027 unsigned long val;
2028 struct l2cap_conf_rfc rfc;
2029
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002030 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002031
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002032 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002033 return;
2034
2035 while (len >= L2CAP_CONF_OPT_SIZE) {
2036 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2037
2038 switch (type) {
2039 case L2CAP_CONF_RFC:
2040 if (olen == sizeof(rfc))
2041 memcpy(&rfc, (void *)val, olen);
2042 goto done;
2043 }
2044 }
2045
2046done:
2047 switch (rfc.mode) {
2048 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002049 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2050 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2051 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002052 break;
2053 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002054 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002055 }
2056}
2057
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002058static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2059{
2060 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2061
2062 if (rej->reason != 0x0000)
2063 return 0;
2064
2065 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2066 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002067 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002068
2069 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002070 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002071
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002072 l2cap_conn_start(conn);
2073 }
2074
2075 return 0;
2076}
2077
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2079{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2081 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002082 struct l2cap_chan *chan = NULL;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002083 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002084 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085
2086 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002087 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088
2089 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2090
2091 /* Check if we have socket listening on psm */
2092 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2093 if (!parent) {
2094 result = L2CAP_CR_BAD_PSM;
2095 goto sendresp;
2096 }
2097
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002098 bh_lock_sock(parent);
2099
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002100 /* Check if the ACL is secure enough (if not SDP) */
2101 if (psm != cpu_to_le16(0x0001) &&
2102 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002103 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002104 result = L2CAP_CR_SEC_BLOCK;
2105 goto response;
2106 }
2107
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 result = L2CAP_CR_NO_MEM;
2109
2110 /* Check for backlog size */
2111 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002112 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113 goto response;
2114 }
2115
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002116 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 if (!sk)
2118 goto response;
2119
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002120 chan = l2cap_chan_alloc(sk);
2121 if (!chan) {
2122 l2cap_sock_kill(sk);
2123 goto response;
2124 }
2125
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03002126 l2cap_pi(sk)->chan = chan;
2127
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002128 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129
2130 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002131 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2132 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 sock_set_flag(sk, SOCK_ZAPPED);
2134 l2cap_sock_kill(sk);
2135 goto response;
2136 }
2137
2138 hci_conn_hold(conn->hcon);
2139
2140 l2cap_sock_init(sk, parent);
2141 bacpy(&bt_sk(sk)->src, conn->src);
2142 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002143 chan->psm = psm;
2144 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002146 bt_accept_enqueue(parent, sk);
2147
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002148 __l2cap_chan_add(conn, chan);
2149
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002150 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151
2152 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2153
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002154 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155
Marcel Holtmann984947d2009-02-06 23:35:19 +01002156 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002157 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002158 if (bt_sk(sk)->defer_setup) {
2159 sk->sk_state = BT_CONNECT2;
2160 result = L2CAP_CR_PEND;
2161 status = L2CAP_CS_AUTHOR_PEND;
2162 parent->sk_data_ready(parent, 0);
2163 } else {
2164 sk->sk_state = BT_CONFIG;
2165 result = L2CAP_CR_SUCCESS;
2166 status = L2CAP_CS_NO_INFO;
2167 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002168 } else {
2169 sk->sk_state = BT_CONNECT2;
2170 result = L2CAP_CR_PEND;
2171 status = L2CAP_CS_AUTHEN_PEND;
2172 }
2173 } else {
2174 sk->sk_state = BT_CONNECT2;
2175 result = L2CAP_CR_PEND;
2176 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 }
2178
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002179 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180
2181response:
2182 bh_unlock_sock(parent);
2183
2184sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002185 rsp.scid = cpu_to_le16(scid);
2186 rsp.dcid = cpu_to_le16(dcid);
2187 rsp.result = cpu_to_le16(result);
2188 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002190
2191 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2192 struct l2cap_info_req info;
2193 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2194
2195 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2196 conn->info_ident = l2cap_get_ident(conn);
2197
2198 mod_timer(&conn->info_timer, jiffies +
2199 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2200
2201 l2cap_send_cmd(conn, conn->info_ident,
2202 L2CAP_INFO_REQ, sizeof(info), &info);
2203 }
2204
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002205 if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002206 result == L2CAP_CR_SUCCESS) {
2207 u8 buf[128];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002208 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002209 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002210 l2cap_build_conf_req(chan, buf), buf);
2211 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002212 }
2213
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 return 0;
2215}
2216
2217static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2218{
2219 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2220 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002221 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222 struct sock *sk;
2223 u8 req[128];
2224
2225 scid = __le16_to_cpu(rsp->scid);
2226 dcid = __le16_to_cpu(rsp->dcid);
2227 result = __le16_to_cpu(rsp->result);
2228 status = __le16_to_cpu(rsp->status);
2229
2230 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2231
2232 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002233 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002234 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002235 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002237 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002238 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002239 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240 }
2241
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002242 sk = chan->sk;
2243
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244 switch (result) {
2245 case L2CAP_CR_SUCCESS:
2246 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002247 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002248 chan->dcid = dcid;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002249 chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002250
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002251 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002252 break;
2253
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002254 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002255
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002257 l2cap_build_conf_req(chan, req), req);
2258 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259 break;
2260
2261 case L2CAP_CR_PEND:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002262 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 break;
2264
2265 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002266 /* don't delete l2cap channel if sk is owned by user */
2267 if (sock_owned_by_user(sk)) {
2268 sk->sk_state = BT_DISCONN;
2269 l2cap_sock_clear_timer(sk);
2270 l2cap_sock_set_timer(sk, HZ / 5);
2271 break;
2272 }
2273
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002274 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 break;
2276 }
2277
2278 bh_unlock_sock(sk);
2279 return 0;
2280}
2281
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002282static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002283{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002284 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
2285
Mat Martineau8c462b62010-08-24 15:35:42 -07002286 /* FCS is enabled only in ERTM or streaming mode, if one or both
2287 * sides request it.
2288 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002289 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002290 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002291 else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002292 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002293}
2294
Al Viro88219a02007-07-29 00:17:25 -07002295static 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 -07002296{
2297 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2298 u16 dcid, flags;
2299 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002300 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002302 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303
2304 dcid = __le16_to_cpu(req->dcid);
2305 flags = __le16_to_cpu(req->flags);
2306
2307 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2308
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002309 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002310 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 return -ENOENT;
2312
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002313 sk = chan->sk;
2314
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002315 if (sk->sk_state != BT_CONFIG) {
2316 struct l2cap_cmd_rej rej;
2317
2318 rej.reason = cpu_to_le16(0x0002);
2319 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2320 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002321 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002322 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002323
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002324 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002325 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002326 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002327 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002328 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002329 L2CAP_CONF_REJECT, flags), rsp);
2330 goto unlock;
2331 }
2332
2333 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002334 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2335 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336
2337 if (flags & 0x0001) {
2338 /* Incomplete config. Send empty response. */
2339 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002340 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002341 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342 goto unlock;
2343 }
2344
2345 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002346 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002347 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002348 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002350 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002352 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002353 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002354
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002355 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002356 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002357
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002358 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002359 goto unlock;
2360
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002361 if (chan->conf_state & L2CAP_CONF_INPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002362 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002363
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002365
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002366 chan->next_tx_seq = 0;
2367 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002368 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002369 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002370 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002371
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002373 goto unlock;
2374 }
2375
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002376 if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002377 u8 buf[64];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002378 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002380 l2cap_build_conf_req(chan, buf), buf);
2381 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382 }
2383
2384unlock:
2385 bh_unlock_sock(sk);
2386 return 0;
2387}
2388
2389static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2390{
2391 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2392 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002393 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002395 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396
2397 scid = __le16_to_cpu(rsp->scid);
2398 flags = __le16_to_cpu(rsp->flags);
2399 result = __le16_to_cpu(rsp->result);
2400
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002401 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2402 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002404 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002405 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406 return 0;
2407
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002408 sk = chan->sk;
2409
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 switch (result) {
2411 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002412 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 break;
2414
2415 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002416 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002417 char req[64];
2418
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002419 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002420 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002421 goto done;
2422 }
2423
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002424 /* throw out any old stored conf requests */
2425 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002426 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2427 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002428 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002429 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002430 goto done;
2431 }
2432
2433 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2434 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002435 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002436 if (result != L2CAP_CONF_SUCCESS)
2437 goto done;
2438 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439 }
2440
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002441 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002442 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002444 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 goto done;
2446 }
2447
2448 if (flags & 0x01)
2449 goto done;
2450
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002451 chan->conf_state |= L2CAP_CONF_INPUT_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002453 if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002454 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002455
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002457 chan->next_tx_seq = 0;
2458 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002459 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002460 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002461 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002462
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 l2cap_chan_ready(sk);
2464 }
2465
2466done:
2467 bh_unlock_sock(sk);
2468 return 0;
2469}
2470
2471static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2472{
2473 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2474 struct l2cap_disconn_rsp rsp;
2475 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002476 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 struct sock *sk;
2478
2479 scid = __le16_to_cpu(req->scid);
2480 dcid = __le16_to_cpu(req->dcid);
2481
2482 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2483
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002484 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002485 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486 return 0;
2487
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002488 sk = chan->sk;
2489
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002490 rsp.dcid = cpu_to_le16(chan->scid);
2491 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2493
2494 sk->sk_shutdown = SHUTDOWN_MASK;
2495
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002496 /* don't delete l2cap channel if sk is owned by user */
2497 if (sock_owned_by_user(sk)) {
2498 sk->sk_state = BT_DISCONN;
2499 l2cap_sock_clear_timer(sk);
2500 l2cap_sock_set_timer(sk, HZ / 5);
2501 bh_unlock_sock(sk);
2502 return 0;
2503 }
2504
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002505 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506 bh_unlock_sock(sk);
2507
2508 l2cap_sock_kill(sk);
2509 return 0;
2510}
2511
2512static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2513{
2514 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2515 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002516 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 struct sock *sk;
2518
2519 scid = __le16_to_cpu(rsp->scid);
2520 dcid = __le16_to_cpu(rsp->dcid);
2521
2522 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2523
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002524 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002525 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526 return 0;
2527
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002528 sk = chan->sk;
2529
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002530 /* don't delete l2cap channel if sk is owned by user */
2531 if (sock_owned_by_user(sk)) {
2532 sk->sk_state = BT_DISCONN;
2533 l2cap_sock_clear_timer(sk);
2534 l2cap_sock_set_timer(sk, HZ / 5);
2535 bh_unlock_sock(sk);
2536 return 0;
2537 }
2538
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002539 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 bh_unlock_sock(sk);
2541
2542 l2cap_sock_kill(sk);
2543 return 0;
2544}
2545
2546static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2547{
2548 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549 u16 type;
2550
2551 type = __le16_to_cpu(req->type);
2552
2553 BT_DBG("type 0x%4.4x", type);
2554
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002555 if (type == L2CAP_IT_FEAT_MASK) {
2556 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002557 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002558 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2559 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2560 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002561 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002562 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2563 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002564 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002565 l2cap_send_cmd(conn, cmd->ident,
2566 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002567 } else if (type == L2CAP_IT_FIXED_CHAN) {
2568 u8 buf[12];
2569 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2570 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2571 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2572 memcpy(buf + 4, l2cap_fixed_chan, 8);
2573 l2cap_send_cmd(conn, cmd->ident,
2574 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002575 } else {
2576 struct l2cap_info_rsp rsp;
2577 rsp.type = cpu_to_le16(type);
2578 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2579 l2cap_send_cmd(conn, cmd->ident,
2580 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2581 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582
2583 return 0;
2584}
2585
2586static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2587{
2588 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2589 u16 type, result;
2590
2591 type = __le16_to_cpu(rsp->type);
2592 result = __le16_to_cpu(rsp->result);
2593
2594 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2595
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002596 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2597 if (cmd->ident != conn->info_ident ||
2598 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2599 return 0;
2600
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002601 del_timer(&conn->info_timer);
2602
Ville Tervoadb08ed2010-08-04 09:43:33 +03002603 if (result != L2CAP_IR_SUCCESS) {
2604 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2605 conn->info_ident = 0;
2606
2607 l2cap_conn_start(conn);
2608
2609 return 0;
2610 }
2611
Marcel Holtmann984947d2009-02-06 23:35:19 +01002612 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002613 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002614
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002615 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002616 struct l2cap_info_req req;
2617 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2618
2619 conn->info_ident = l2cap_get_ident(conn);
2620
2621 l2cap_send_cmd(conn, conn->info_ident,
2622 L2CAP_INFO_REQ, sizeof(req), &req);
2623 } else {
2624 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2625 conn->info_ident = 0;
2626
2627 l2cap_conn_start(conn);
2628 }
2629 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002630 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002631 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002632
2633 l2cap_conn_start(conn);
2634 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002635
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 return 0;
2637}
2638
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002639static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002640 u16 to_multiplier)
2641{
2642 u16 max_latency;
2643
2644 if (min > max || min < 6 || max > 3200)
2645 return -EINVAL;
2646
2647 if (to_multiplier < 10 || to_multiplier > 3200)
2648 return -EINVAL;
2649
2650 if (max >= to_multiplier * 8)
2651 return -EINVAL;
2652
2653 max_latency = (to_multiplier * 8 / max) - 1;
2654 if (latency > 499 || latency > max_latency)
2655 return -EINVAL;
2656
2657 return 0;
2658}
2659
2660static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2661 struct l2cap_cmd_hdr *cmd, u8 *data)
2662{
2663 struct hci_conn *hcon = conn->hcon;
2664 struct l2cap_conn_param_update_req *req;
2665 struct l2cap_conn_param_update_rsp rsp;
2666 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002667 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002668
2669 if (!(hcon->link_mode & HCI_LM_MASTER))
2670 return -EINVAL;
2671
2672 cmd_len = __le16_to_cpu(cmd->len);
2673 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2674 return -EPROTO;
2675
2676 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002677 min = __le16_to_cpu(req->min);
2678 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002679 latency = __le16_to_cpu(req->latency);
2680 to_multiplier = __le16_to_cpu(req->to_multiplier);
2681
2682 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2683 min, max, latency, to_multiplier);
2684
2685 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002686
2687 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2688 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002689 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2690 else
2691 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2692
2693 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2694 sizeof(rsp), &rsp);
2695
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002696 if (!err)
2697 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2698
Claudio Takahaside731152011-02-11 19:28:55 -02002699 return 0;
2700}
2701
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002702static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2703 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2704{
2705 int err = 0;
2706
2707 switch (cmd->code) {
2708 case L2CAP_COMMAND_REJ:
2709 l2cap_command_rej(conn, cmd, data);
2710 break;
2711
2712 case L2CAP_CONN_REQ:
2713 err = l2cap_connect_req(conn, cmd, data);
2714 break;
2715
2716 case L2CAP_CONN_RSP:
2717 err = l2cap_connect_rsp(conn, cmd, data);
2718 break;
2719
2720 case L2CAP_CONF_REQ:
2721 err = l2cap_config_req(conn, cmd, cmd_len, data);
2722 break;
2723
2724 case L2CAP_CONF_RSP:
2725 err = l2cap_config_rsp(conn, cmd, data);
2726 break;
2727
2728 case L2CAP_DISCONN_REQ:
2729 err = l2cap_disconnect_req(conn, cmd, data);
2730 break;
2731
2732 case L2CAP_DISCONN_RSP:
2733 err = l2cap_disconnect_rsp(conn, cmd, data);
2734 break;
2735
2736 case L2CAP_ECHO_REQ:
2737 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2738 break;
2739
2740 case L2CAP_ECHO_RSP:
2741 break;
2742
2743 case L2CAP_INFO_REQ:
2744 err = l2cap_information_req(conn, cmd, data);
2745 break;
2746
2747 case L2CAP_INFO_RSP:
2748 err = l2cap_information_rsp(conn, cmd, data);
2749 break;
2750
2751 default:
2752 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2753 err = -EINVAL;
2754 break;
2755 }
2756
2757 return err;
2758}
2759
2760static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2761 struct l2cap_cmd_hdr *cmd, u8 *data)
2762{
2763 switch (cmd->code) {
2764 case L2CAP_COMMAND_REJ:
2765 return 0;
2766
2767 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002768 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002769
2770 case L2CAP_CONN_PARAM_UPDATE_RSP:
2771 return 0;
2772
2773 default:
2774 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2775 return -EINVAL;
2776 }
2777}
2778
2779static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2780 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781{
2782 u8 *data = skb->data;
2783 int len = skb->len;
2784 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002785 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786
2787 l2cap_raw_recv(conn, skb);
2788
2789 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002790 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2792 data += L2CAP_CMD_HDR_SIZE;
2793 len -= L2CAP_CMD_HDR_SIZE;
2794
Al Viro88219a02007-07-29 00:17:25 -07002795 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796
Al Viro88219a02007-07-29 00:17:25 -07002797 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 -07002798
Al Viro88219a02007-07-29 00:17:25 -07002799 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800 BT_DBG("corrupted command");
2801 break;
2802 }
2803
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002804 if (conn->hcon->type == LE_LINK)
2805 err = l2cap_le_sig_cmd(conn, &cmd, data);
2806 else
2807 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808
2809 if (err) {
2810 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002811
2812 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813
2814 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002815 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2817 }
2818
Al Viro88219a02007-07-29 00:17:25 -07002819 data += cmd_len;
2820 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821 }
2822
2823 kfree_skb(skb);
2824}
2825
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002826static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002827{
2828 u16 our_fcs, rcv_fcs;
2829 int hdr_size = L2CAP_HDR_SIZE + 2;
2830
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002831 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002832 skb_trim(skb, skb->len - 2);
2833 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2834 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2835
2836 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002837 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002838 }
2839 return 0;
2840}
2841
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002842static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002843{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002844 u16 control = 0;
2845
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002846 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002847
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002848 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002849
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002850 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002851 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002852 l2cap_send_sframe(chan, control);
2853 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002854 }
2855
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002856 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
2857 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002858
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002859 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002860
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002861 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002862 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002863 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002864 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002865 }
2866}
2867
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002868static 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 -03002869{
2870 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002871 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002872
2873 bt_cb(skb)->tx_seq = tx_seq;
2874 bt_cb(skb)->sar = sar;
2875
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002876 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002877 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002878 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002879 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002880 }
2881
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002882 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002883 if (tx_seq_offset < 0)
2884 tx_seq_offset += 64;
2885
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002886 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002887 if (bt_cb(next_skb)->tx_seq == tx_seq)
2888 return -EINVAL;
2889
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002890 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002891 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002892 if (next_tx_seq_offset < 0)
2893 next_tx_seq_offset += 64;
2894
2895 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002896 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002897 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002898 }
2899
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002900 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002901 break;
2902
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002903 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002904
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002905 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002906
2907 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002908}
2909
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002910static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002911{
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002912 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002913 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002914
2915 switch (control & L2CAP_CTRL_SAR) {
2916 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002917 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002918 goto drop;
2919
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002920 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002921 if (!err)
2922 return err;
2923
2924 break;
2925
2926 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002927 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002928 goto drop;
2929
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002930 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002931
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002932 if (chan->sdu_len > chan->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002933 goto disconnect;
2934
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002935 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
2936 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002937 return -ENOMEM;
2938
2939 /* pull sdu_len bytes only after alloc, because of Local Busy
2940 * condition we have to be sure that this will be executed
2941 * only once, i.e., when alloc does not fail */
2942 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002943
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002944 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002945
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002946 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002947 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002948 break;
2949
2950 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002951 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002952 goto disconnect;
2953
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002954 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002955 goto disconnect;
2956
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002957 chan->partial_sdu_len += skb->len;
2958 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002959 goto drop;
2960
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002961 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002962
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002963 break;
2964
2965 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002966 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002967 goto disconnect;
2968
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002969 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002970 goto disconnect;
2971
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002972 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002973 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002974
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002975 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002976 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002977
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002978 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002979 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002980
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002981 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002982 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002983
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002984 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002985 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002986 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002987 return -ENOMEM;
2988 }
2989
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002990 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002991 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002992 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002993 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002994 return err;
2995 }
2996
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002997 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2998 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002999
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003000 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003001 break;
3002 }
3003
3004 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003005 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003006
3007drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003008 kfree_skb(chan->sdu);
3009 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003010
3011disconnect:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003012 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003013 kfree_skb(skb);
3014 return 0;
3015}
3016
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003017static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003018{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003019 struct sk_buff *skb;
3020 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003021 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003022
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003023 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003024 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003025 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003026 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003027 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003028 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003029 }
3030
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003031 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003032 }
3033
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003034 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003035 goto done;
3036
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003037 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003038 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003039 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003040 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003041
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003042 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003043 __mod_monitor_timer();
3044
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003045 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003046
3047done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003048 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3049 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003050
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003051 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003052
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003053 return 0;
3054}
3055
3056static void l2cap_busy_work(struct work_struct *work)
3057{
3058 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003059 struct l2cap_chan *chan =
3060 container_of(work, struct l2cap_chan, busy_work);
3061 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003062 int n_tries = 0, timeo = HZ/5, err;
3063 struct sk_buff *skb;
3064
3065 lock_sock(sk);
3066
3067 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003068 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003069 set_current_state(TASK_INTERRUPTIBLE);
3070
3071 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3072 err = -EBUSY;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003073 l2cap_send_disconn_req(chan->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003074 break;
3075 }
3076
3077 if (!timeo)
3078 timeo = HZ/5;
3079
3080 if (signal_pending(current)) {
3081 err = sock_intr_errno(timeo);
3082 break;
3083 }
3084
3085 release_sock(sk);
3086 timeo = schedule_timeout(timeo);
3087 lock_sock(sk);
3088
3089 err = sock_error(sk);
3090 if (err)
3091 break;
3092
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003093 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003094 break;
3095 }
3096
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003097 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003098 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003099
3100 release_sock(sk);
3101}
3102
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003103static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003104{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003105 int sctrl, err;
3106
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003107 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003108 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003109 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003110 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003111
3112
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003113 }
3114
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003115 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003116 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003117 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003118 return err;
3119 }
3120
3121 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003122 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003123
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003124 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003125 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003126 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003127
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003128 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003129 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003130 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003131
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003132 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003133
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003134 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003135
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003136 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003137
3138 return err;
3139}
3140
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003141static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003142{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003143 struct sk_buff *_skb;
3144 int err = -EINVAL;
3145
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003146 /*
3147 * TODO: We have to notify the userland if some data is lost with the
3148 * Streaming Mode.
3149 */
3150
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003151 switch (control & L2CAP_CTRL_SAR) {
3152 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003153 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003154 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003155 break;
3156 }
3157
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003158 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003159 if (!err)
3160 return 0;
3161
3162 break;
3163
3164 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003165 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003166 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003167 break;
3168 }
3169
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003170 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003171 skb_pull(skb, 2);
3172
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003173 if (chan->sdu_len > chan->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003174 err = -EMSGSIZE;
3175 break;
3176 }
3177
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003178 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3179 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003180 err = -ENOMEM;
3181 break;
3182 }
3183
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003184 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003185
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003186 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003187 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003188 err = 0;
3189 break;
3190
3191 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003192 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003193 break;
3194
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003195 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003196
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003197 chan->partial_sdu_len += skb->len;
3198 if (chan->partial_sdu_len > chan->sdu_len)
3199 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003200 else
3201 err = 0;
3202
3203 break;
3204
3205 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003206 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003207 break;
3208
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003209 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003210
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003211 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003212 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003213
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003214 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003215 goto drop;
3216
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003217 if (chan->partial_sdu_len == chan->sdu_len) {
3218 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003219 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003220 if (err < 0)
3221 kfree_skb(_skb);
3222 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003223 err = 0;
3224
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003225drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003226 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003227 break;
3228 }
3229
3230 kfree_skb(skb);
3231 return err;
3232}
3233
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003234static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003235{
3236 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003237 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003238
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003239 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003240 if (bt_cb(skb)->tx_seq != tx_seq)
3241 break;
3242
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003243 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003244 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003245 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003246 chan->buffer_seq_srej =
3247 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003248 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003249 }
3250}
3251
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003252static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003253{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003254 struct srej_list *l, *tmp;
3255 u16 control;
3256
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003257 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003258 if (l->tx_seq == tx_seq) {
3259 list_del(&l->list);
3260 kfree(l);
3261 return;
3262 }
3263 control = L2CAP_SUPER_SELECT_REJECT;
3264 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003265 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003266 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003267 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003268 }
3269}
3270
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003271static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003272{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003273 struct srej_list *new;
3274 u16 control;
3275
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003276 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003277 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003278 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003279 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003280
3281 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003282 new->tx_seq = chan->expected_tx_seq;
3283 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003284 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003285 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003286 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003287}
3288
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003289static 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 -03003290{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003291 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003292 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003293 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003294 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003295 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003296 int err = 0;
3297
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003298 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3299 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003300
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003301 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003302 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003303 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003304 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003305 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003306 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003307 }
3308
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003309 chan->expected_ack_seq = req_seq;
3310 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003311
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003312 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003313 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003314
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003315 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003316 if (tx_seq_offset < 0)
3317 tx_seq_offset += 64;
3318
3319 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003320 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003321 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003322 goto drop;
3323 }
3324
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003325 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003326 goto drop;
3327
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003328 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003329 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003330
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003331 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003332 struct srej_list, list);
3333 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003334 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003335 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003336
3337 list_del(&first->list);
3338 kfree(first);
3339
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003340 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003341 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003342 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3343 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003344 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003345 }
3346 } else {
3347 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003348
3349 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003350 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003351 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003352
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003353 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003354 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003355 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003356 return 0;
3357 }
3358 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003359 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003360 }
3361 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003362 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003363 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003364 if (expected_tx_seq_offset < 0)
3365 expected_tx_seq_offset += 64;
3366
3367 /* duplicated tx_seq */
3368 if (tx_seq_offset < expected_tx_seq_offset)
3369 goto drop;
3370
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003371 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003372
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003373 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003374
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003375 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003376 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003377
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003378 __skb_queue_head_init(&chan->srej_q);
3379 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003380 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003381
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003382 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003383
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003384 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003385
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003386 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003387 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003388 return 0;
3389
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003390expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003391 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003392
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003393 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003394 bt_cb(skb)->tx_seq = tx_seq;
3395 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003396 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003397 return 0;
3398 }
3399
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003400 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003401 if (err < 0)
3402 return 0;
3403
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003404 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003405 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3406 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003407 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003408 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003409 }
3410
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003411 __mod_ack_timer();
3412
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003413 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3414 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003415 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003416
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003417 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003418
3419drop:
3420 kfree_skb(skb);
3421 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003422}
3423
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003424static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003425{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003426 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003427 rx_control);
3428
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003429 chan->expected_ack_seq = __get_reqseq(rx_control);
3430 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003431
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003432 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003433 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3434 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3435 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003436 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003437 __mod_retrans_timer();
3438
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003439 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3440 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003441 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003442 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003443 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003444
3445 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003446 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003447
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003448 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3449 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003450 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003451 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003452
3453 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003454 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003455 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003456 __mod_retrans_timer();
3457
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003458 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3459 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3460 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003461 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003462 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003463 }
3464}
3465
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003466static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003467{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003468 u8 tx_seq = __get_reqseq(rx_control);
3469
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003470 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003471
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003472 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003473
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003474 chan->expected_ack_seq = tx_seq;
3475 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003476
3477 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003478 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3479 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003480 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003481 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003482 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003483 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003484
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003485 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3486 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003487 }
3488}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003489static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003490{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003491 u8 tx_seq = __get_reqseq(rx_control);
3492
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003493 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003494
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003495 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003496
3497 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003498 chan->expected_ack_seq = tx_seq;
3499 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003500
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003501 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3502 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003503
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003504 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003505
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003506 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003507 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003508 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003509 }
3510 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003511 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003512 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003513 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003514 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003515 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003516 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003517 l2cap_retransmit_one_frame(chan, tx_seq);
3518 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003519 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003520 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003521 }
3522 }
3523}
3524
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003525static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003526{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003527 u8 tx_seq = __get_reqseq(rx_control);
3528
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003529 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003530
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003531 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003532 chan->expected_ack_seq = tx_seq;
3533 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003534
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003535 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003536 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003537
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003538 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003539 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003540 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003541 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003542 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003543 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003544
3545 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003546 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003547 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003548 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003549}
3550
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003551static 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 -03003552{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003553 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003554
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003555 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003556 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003557 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003558 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003559 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003560 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003561 }
3562
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003563 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3564 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003565 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003566 break;
3567
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003568 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003569 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003570 break;
3571
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003572 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003573 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003574 break;
3575
3576 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003577 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003578 break;
3579 }
3580
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003581 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003582 return 0;
3583}
3584
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003585static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3586{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003587 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003588 u16 control;
3589 u8 req_seq;
3590 int len, next_tx_seq_offset, req_seq_offset;
3591
3592 control = get_unaligned_le16(skb->data);
3593 skb_pull(skb, 2);
3594 len = skb->len;
3595
3596 /*
3597 * We can just drop the corrupted I-frame here.
3598 * Receiver will miss it and start proper recovery
3599 * procedures and ask retransmission.
3600 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003601 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003602 goto drop;
3603
3604 if (__is_sar_start(control) && __is_iframe(control))
3605 len -= 2;
3606
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003607 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003608 len -= 2;
3609
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003610 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003611 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003612 goto drop;
3613 }
3614
3615 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003616 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003617 if (req_seq_offset < 0)
3618 req_seq_offset += 64;
3619
3620 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003621 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003622 if (next_tx_seq_offset < 0)
3623 next_tx_seq_offset += 64;
3624
3625 /* check for invalid req-seq */
3626 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003627 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003628 goto drop;
3629 }
3630
3631 if (__is_iframe(control)) {
3632 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003633 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003634 goto drop;
3635 }
3636
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003637 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003638 } else {
3639 if (len != 0) {
3640 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003641 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003642 goto drop;
3643 }
3644
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003645 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003646 }
3647
3648 return 0;
3649
3650drop:
3651 kfree_skb(skb);
3652 return 0;
3653}
3654
Linus Torvalds1da177e2005-04-16 15:20:36 -07003655static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3656{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003657 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003658 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003659 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003660 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003661 u8 tx_seq;
3662 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003663
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003664 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003665 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003666 BT_DBG("unknown cid 0x%4.4x", cid);
3667 goto drop;
3668 }
3669
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003670 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003671 pi = l2cap_pi(sk);
3672
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003673 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674
3675 if (sk->sk_state != BT_CONNECTED)
3676 goto drop;
3677
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003678 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003679 case L2CAP_MODE_BASIC:
3680 /* If socket recv buffers overflows we drop data here
3681 * which is *bad* because L2CAP has to be reliable.
3682 * But we don't have any other choice. L2CAP doesn't
3683 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003685 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003686 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003688 if (!sock_queue_rcv_skb(sk, skb))
3689 goto done;
3690 break;
3691
3692 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003693 if (!sock_owned_by_user(sk)) {
3694 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003695 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003696 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003697 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003698 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003699
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003700 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003701
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003702 case L2CAP_MODE_STREAMING:
3703 control = get_unaligned_le16(skb->data);
3704 skb_pull(skb, 2);
3705 len = skb->len;
3706
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003707 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003708 goto drop;
3709
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003710 if (__is_sar_start(control))
3711 len -= 2;
3712
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003713 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003714 len -= 2;
3715
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003716 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003717 goto drop;
3718
3719 tx_seq = __get_txseq(control);
3720
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003721 if (chan->expected_tx_seq == tx_seq)
3722 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003723 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003724 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003725
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003726 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003727
3728 goto done;
3729
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003730 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003731 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003732 break;
3733 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003734
3735drop:
3736 kfree_skb(skb);
3737
3738done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003739 if (sk)
3740 bh_unlock_sock(sk);
3741
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742 return 0;
3743}
3744
Al Viro8e036fc2007-07-29 00:16:36 -07003745static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003746{
3747 struct sock *sk;
3748
3749 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3750 if (!sk)
3751 goto drop;
3752
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003753 bh_lock_sock(sk);
3754
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755 BT_DBG("sk %p, len %d", sk, skb->len);
3756
3757 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3758 goto drop;
3759
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003760 if (l2cap_pi(sk)->chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003761 goto drop;
3762
3763 if (!sock_queue_rcv_skb(sk, skb))
3764 goto done;
3765
3766drop:
3767 kfree_skb(skb);
3768
3769done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003770 if (sk)
3771 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772 return 0;
3773}
3774
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003775static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3776{
3777 struct sock *sk;
3778
3779 sk = l2cap_get_sock_by_scid(0, cid, conn->src);
3780 if (!sk)
3781 goto drop;
3782
3783 bh_lock_sock(sk);
3784
3785 BT_DBG("sk %p, len %d", sk, skb->len);
3786
3787 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3788 goto drop;
3789
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003790 if (l2cap_pi(sk)->chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003791 goto drop;
3792
3793 if (!sock_queue_rcv_skb(sk, skb))
3794 goto done;
3795
3796drop:
3797 kfree_skb(skb);
3798
3799done:
3800 if (sk)
3801 bh_unlock_sock(sk);
3802 return 0;
3803}
3804
Linus Torvalds1da177e2005-04-16 15:20:36 -07003805static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3806{
3807 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003808 u16 cid, len;
3809 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810
3811 skb_pull(skb, L2CAP_HDR_SIZE);
3812 cid = __le16_to_cpu(lh->cid);
3813 len = __le16_to_cpu(lh->len);
3814
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003815 if (len != skb->len) {
3816 kfree_skb(skb);
3817 return;
3818 }
3819
Linus Torvalds1da177e2005-04-16 15:20:36 -07003820 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3821
3822 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003823 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003824 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003825 l2cap_sig_channel(conn, skb);
3826 break;
3827
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003828 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003829 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830 skb_pull(skb, 2);
3831 l2cap_conless_channel(conn, psm, skb);
3832 break;
3833
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003834 case L2CAP_CID_LE_DATA:
3835 l2cap_att_channel(conn, cid, skb);
3836 break;
3837
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838 default:
3839 l2cap_data_channel(conn, cid, skb);
3840 break;
3841 }
3842}
3843
3844/* ---- L2CAP interface with lower layer (HCI) ---- */
3845
3846static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3847{
3848 int exact = 0, lm1 = 0, lm2 = 0;
3849 register struct sock *sk;
3850 struct hlist_node *node;
3851
3852 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003853 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854
3855 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3856
3857 /* Find listening sockets and check their link_mode */
3858 read_lock(&l2cap_sk_list.lock);
3859 sk_for_each(sk, node, &l2cap_sk_list.head) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003860 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
3861
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862 if (sk->sk_state != BT_LISTEN)
3863 continue;
3864
3865 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003866 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003867 if (chan->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003868 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003870 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3871 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003872 if (chan->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003873 lm2 |= HCI_LM_MASTER;
3874 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875 }
3876 read_unlock(&l2cap_sk_list.lock);
3877
3878 return exact ? lm1 : lm2;
3879}
3880
3881static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3882{
Marcel Holtmann01394182006-07-03 10:02:46 +02003883 struct l2cap_conn *conn;
3884
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3886
Ville Tervoacd7d372011-02-10 22:38:49 -03003887 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003888 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889
3890 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891 conn = l2cap_conn_add(hcon, status);
3892 if (conn)
3893 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003894 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895 l2cap_conn_del(hcon, bt_err(status));
3896
3897 return 0;
3898}
3899
Marcel Holtmann2950f212009-02-12 14:02:50 +01003900static int l2cap_disconn_ind(struct hci_conn *hcon)
3901{
3902 struct l2cap_conn *conn = hcon->l2cap_data;
3903
3904 BT_DBG("hcon %p", hcon);
3905
3906 if (hcon->type != ACL_LINK || !conn)
3907 return 0x13;
3908
3909 return conn->disc_reason;
3910}
3911
3912static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913{
3914 BT_DBG("hcon %p reason %d", hcon, reason);
3915
Ville Tervoacd7d372011-02-10 22:38:49 -03003916 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003917 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918
3919 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003920
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921 return 0;
3922}
3923
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003924static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003925{
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003926 struct sock *sk = chan->sk;
3927
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003928 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003929 return;
3930
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003931 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003932 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003933 l2cap_sock_clear_timer(sk);
3934 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003935 } else if (chan->sec_level == BT_SECURITY_HIGH)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003936 __l2cap_sock_close(sk, ECONNREFUSED);
3937 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003938 if (chan->sec_level == BT_SECURITY_MEDIUM)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003939 l2cap_sock_clear_timer(sk);
3940 }
3941}
3942
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003943static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003945 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003946 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003947
Marcel Holtmann01394182006-07-03 10:02:46 +02003948 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003950
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951 BT_DBG("conn %p", conn);
3952
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003953 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003955 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003956 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003957
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 bh_lock_sock(sk);
3959
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003960 if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003961 bh_unlock_sock(sk);
3962 continue;
3963 }
3964
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003965 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003966 sk->sk_state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003967 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003968 bh_unlock_sock(sk);
3969 continue;
3970 }
3971
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003972 if (sk->sk_state == BT_CONNECT) {
3973 if (!status) {
3974 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003975 req.scid = cpu_to_le16(chan->scid);
3976 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003977
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003978 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003979 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003980
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003981 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003982 L2CAP_CONN_REQ, sizeof(req), &req);
3983 } else {
3984 l2cap_sock_clear_timer(sk);
3985 l2cap_sock_set_timer(sk, HZ / 10);
3986 }
3987 } else if (sk->sk_state == BT_CONNECT2) {
3988 struct l2cap_conn_rsp rsp;
3989 __u16 result;
3990
3991 if (!status) {
3992 sk->sk_state = BT_CONFIG;
3993 result = L2CAP_CR_SUCCESS;
3994 } else {
3995 sk->sk_state = BT_DISCONN;
3996 l2cap_sock_set_timer(sk, HZ / 10);
3997 result = L2CAP_CR_SEC_BLOCK;
3998 }
3999
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004000 rsp.scid = cpu_to_le16(chan->dcid);
4001 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004002 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02004003 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004004 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4005 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006 }
4007
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008 bh_unlock_sock(sk);
4009 }
4010
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004011 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004012
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013 return 0;
4014}
4015
4016static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4017{
4018 struct l2cap_conn *conn = hcon->l2cap_data;
4019
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004020 if (!conn)
4021 conn = l2cap_conn_add(hcon, 0);
4022
4023 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024 goto drop;
4025
4026 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4027
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004028 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004030 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004031 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032 int len;
4033
4034 if (conn->rx_len) {
4035 BT_ERR("Unexpected start frame (len %d)", skb->len);
4036 kfree_skb(conn->rx_skb);
4037 conn->rx_skb = NULL;
4038 conn->rx_len = 0;
4039 l2cap_conn_unreliable(conn, ECOMM);
4040 }
4041
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004042 /* Start fragment always begin with Basic L2CAP header */
4043 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044 BT_ERR("Frame is too short (len %d)", skb->len);
4045 l2cap_conn_unreliable(conn, ECOMM);
4046 goto drop;
4047 }
4048
4049 hdr = (struct l2cap_hdr *) skb->data;
4050 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004051 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052
4053 if (len == skb->len) {
4054 /* Complete frame received */
4055 l2cap_recv_frame(conn, skb);
4056 return 0;
4057 }
4058
4059 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4060
4061 if (skb->len > len) {
4062 BT_ERR("Frame is too long (len %d, expected len %d)",
4063 skb->len, len);
4064 l2cap_conn_unreliable(conn, ECOMM);
4065 goto drop;
4066 }
4067
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004068 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004069
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004070 if (chan && chan->sk) {
4071 struct sock *sk = chan->sk;
4072
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004073 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004074 BT_ERR("Frame exceeding recv MTU (len %d, "
4075 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004076 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004077 bh_unlock_sock(sk);
4078 l2cap_conn_unreliable(conn, ECOMM);
4079 goto drop;
4080 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004081 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004082 }
4083
Linus Torvalds1da177e2005-04-16 15:20:36 -07004084 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004085 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4086 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087 goto drop;
4088
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004089 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004090 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091 conn->rx_len = len - skb->len;
4092 } else {
4093 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4094
4095 if (!conn->rx_len) {
4096 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4097 l2cap_conn_unreliable(conn, ECOMM);
4098 goto drop;
4099 }
4100
4101 if (skb->len > conn->rx_len) {
4102 BT_ERR("Fragment is too long (len %d, expected %d)",
4103 skb->len, conn->rx_len);
4104 kfree_skb(conn->rx_skb);
4105 conn->rx_skb = NULL;
4106 conn->rx_len = 0;
4107 l2cap_conn_unreliable(conn, ECOMM);
4108 goto drop;
4109 }
4110
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004111 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004112 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113 conn->rx_len -= skb->len;
4114
4115 if (!conn->rx_len) {
4116 /* Complete frame received */
4117 l2cap_recv_frame(conn, conn->rx_skb);
4118 conn->rx_skb = NULL;
4119 }
4120 }
4121
4122drop:
4123 kfree_skb(skb);
4124 return 0;
4125}
4126
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004127static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128{
4129 struct sock *sk;
4130 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131
4132 read_lock_bh(&l2cap_sk_list.lock);
4133
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004134 sk_for_each(sk, node, &l2cap_sk_list.head) {
4135 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004136 struct l2cap_chan *chan = pi->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004138 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 +01004139 batostr(&bt_sk(sk)->src),
4140 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004141 sk->sk_state, __le16_to_cpu(chan->psm),
4142 chan->scid, chan->dcid,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004143 chan->imtu, chan->omtu, chan->sec_level,
4144 chan->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004145 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004148
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004149 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150}
4151
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004152static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4153{
4154 return single_open(file, l2cap_debugfs_show, inode->i_private);
4155}
4156
4157static const struct file_operations l2cap_debugfs_fops = {
4158 .open = l2cap_debugfs_open,
4159 .read = seq_read,
4160 .llseek = seq_lseek,
4161 .release = single_release,
4162};
4163
4164static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004165
Linus Torvalds1da177e2005-04-16 15:20:36 -07004166static struct hci_proto l2cap_hci_proto = {
4167 .name = "L2CAP",
4168 .id = HCI_PROTO_L2CAP,
4169 .connect_ind = l2cap_connect_ind,
4170 .connect_cfm = l2cap_connect_cfm,
4171 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004172 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004173 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004174 .recv_acldata = l2cap_recv_acldata
4175};
4176
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004177int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004178{
4179 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004180
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004181 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182 if (err < 0)
4183 return err;
4184
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004185 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004186 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004187 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188 goto error;
4189 }
4190
4191 err = hci_register_proto(&l2cap_hci_proto);
4192 if (err < 0) {
4193 BT_ERR("L2CAP protocol registration failed");
4194 bt_sock_unregister(BTPROTO_L2CAP);
4195 goto error;
4196 }
4197
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004198 if (bt_debugfs) {
4199 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4200 bt_debugfs, NULL, &l2cap_debugfs_fops);
4201 if (!l2cap_debugfs)
4202 BT_ERR("Failed to create L2CAP debug file");
4203 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205 return 0;
4206
4207error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004208 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004209 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004210 return err;
4211}
4212
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004213void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004215 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004216
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004217 flush_workqueue(_busy_wq);
4218 destroy_workqueue(_busy_wq);
4219
Linus Torvalds1da177e2005-04-16 15:20:36 -07004220 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4221 BT_ERR("L2CAP protocol unregistration failed");
4222
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004223 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004224}
4225
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004226module_param(disable_ertm, bool, 0644);
4227MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");