blob: b727cd97c5a28253a63cdb53b7f659602d8df4f9 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 RFCOMM implementation for Linux Bluetooth stack (BlueZ).
3 Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
4 Copyright (C) 2002 Marcel Holtmann <marcel@holtmann.org>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 as
8 published by the Free Software Foundation;
9
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
11 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
13 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090014 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
15 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090019 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
20 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 SOFTWARE IS DISCLAIMED.
22*/
23
Linus Torvalds1da177e2005-04-16 15:20:36 -070024/*
25 * Bluetooth RFCOMM core.
Linus Torvalds1da177e2005-04-16 15:20:36 -070026 */
27
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/module.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010029#include <linux/debugfs.h>
Marcel Holtmanna524ecc2007-10-20 21:37:20 +020030#include <linux/kthread.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <asm/unaligned.h>
32
33#include <net/bluetooth/bluetooth.h>
34#include <net/bluetooth/hci_core.h>
35#include <net/bluetooth/l2cap.h>
36#include <net/bluetooth/rfcomm.h>
37
Marcel Holtmann5f9018a2009-01-16 10:09:50 +010038#define VERSION "1.11"
Marcel Holtmann56f3a402006-02-13 11:39:57 +010039
Rusty Russelleb939922011-12-19 14:08:01 +000040static bool disable_cfc;
41static bool l2cap_ertm;
Marcel Holtmann98bcd082006-07-14 11:42:12 +020042static int channel_mtu = -1;
Marcel Holtmann56f3a402006-02-13 11:39:57 +010043static unsigned int l2cap_mtu = RFCOMM_MAX_L2CAP_MTU;
44
Linus Torvalds1da177e2005-04-16 15:20:36 -070045static struct task_struct *rfcomm_thread;
46
Arjan van de Ven4a3e2f72006-03-20 22:33:17 -080047static DEFINE_MUTEX(rfcomm_mutex);
48#define rfcomm_lock() mutex_lock(&rfcomm_mutex)
49#define rfcomm_unlock() mutex_unlock(&rfcomm_mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
52static LIST_HEAD(session_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
Gustavo F. Padovan54365382011-12-20 16:30:44 -020054static int rfcomm_send_frame(struct rfcomm_session *s, u8 *data, int len);
Linus Torvalds1da177e2005-04-16 15:20:36 -070055static int rfcomm_send_sabm(struct rfcomm_session *s, u8 dlci);
56static int rfcomm_send_disc(struct rfcomm_session *s, u8 dlci);
57static int rfcomm_queue_disc(struct rfcomm_dlc *d);
58static int rfcomm_send_nsc(struct rfcomm_session *s, int cr, u8 type);
59static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d);
60static int rfcomm_send_msc(struct rfcomm_session *s, int cr, u8 dlci, u8 v24_sig);
61static int rfcomm_send_test(struct rfcomm_session *s, int cr, u8 *pattern, int len);
62static int rfcomm_send_credits(struct rfcomm_session *s, u8 addr, u8 credits);
63static void rfcomm_make_uih(struct sk_buff *skb, u8 addr);
64
65static void rfcomm_process_connect(struct rfcomm_session *s);
66
Luiz Augusto von Dentz63ce0902010-08-19 14:06:10 +030067static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
68 bdaddr_t *dst,
69 u8 sec_level,
70 int *err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070071static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst);
Dean Jenkins8ff52f72013-02-28 14:21:55 +000072static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s);
Linus Torvalds1da177e2005-04-16 15:20:36 -070073
74/* ---- RFCOMM frame parsing macros ---- */
75#define __get_dlci(b) ((b & 0xfc) >> 2)
76#define __get_channel(b) ((b & 0xf8) >> 3)
77#define __get_dir(b) ((b & 0x04) >> 2)
78#define __get_type(b) ((b & 0xef))
79
80#define __test_ea(b) ((b & 0x01))
81#define __test_cr(b) ((b & 0x02))
82#define __test_pf(b) ((b & 0x10))
83
84#define __addr(cr, dlci) (((dlci & 0x3f) << 2) | (cr << 1) | 0x01)
85#define __ctrl(type, pf) (((type & 0xef) | (pf << 4)))
86#define __dlci(dir, chn) (((chn & 0x1f) << 1) | dir)
87#define __srv_channel(dlci) (dlci >> 1)
88#define __dir(dlci) (dlci & 0x01)
89
90#define __len8(len) (((len) << 1) | 1)
91#define __len16(len) ((len) << 1)
92
93/* MCC macros */
94#define __mcc_type(cr, type) (((type << 2) | (cr << 1) | 0x01))
95#define __get_mcc_type(b) ((b & 0xfc) >> 2)
96#define __get_mcc_len(b) ((b & 0xfe) >> 1)
97
98/* RPN macros */
J. Suter3a5e9032005-08-09 20:28:46 -070099#define __rpn_line_settings(data, stop, parity) ((data & 0x3) | ((stop & 0x1) << 2) | ((parity & 0x7) << 3))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100#define __get_rpn_data_bits(line) ((line) & 0x3)
101#define __get_rpn_stop_bits(line) (((line) >> 2) & 0x1)
J. Suter3a5e9032005-08-09 20:28:46 -0700102#define __get_rpn_parity(line) (((line) >> 3) & 0x7)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Gustavo Padovan6039aa732012-05-23 04:04:18 -0300104static void rfcomm_schedule(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105{
106 if (!rfcomm_thread)
107 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 wake_up_process(rfcomm_thread);
109}
110
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111/* ---- RFCOMM FCS computation ---- */
112
Marcel Holtmann408c1ce2005-10-28 19:20:36 +0200113/* reversed, 8-bit, poly=0x07 */
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900114static unsigned char rfcomm_crc_table[256] = {
Marcel Holtmann408c1ce2005-10-28 19:20:36 +0200115 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
116 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
117 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
118 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
119
120 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
121 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
122 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
123 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
124
125 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
126 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
127 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
128 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
129
130 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
131 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
132 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
133 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
134
135 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
136 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
137 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
138 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
139
140 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
141 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
142 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
143 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
144
145 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
146 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
147 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
148 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
149
150 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
151 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
152 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
153 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
154};
155
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156/* CRC on 2 bytes */
157#define __crc(data) (rfcomm_crc_table[rfcomm_crc_table[0xff ^ data[0]] ^ data[1]])
158
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900159/* FCS on 2 bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160static inline u8 __fcs(u8 *data)
161{
Eric Dumazeta02cec22010-09-22 20:43:57 +0000162 return 0xff - __crc(data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163}
164
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900165/* FCS on 3 bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166static inline u8 __fcs2(u8 *data)
167{
Eric Dumazeta02cec22010-09-22 20:43:57 +0000168 return 0xff - rfcomm_crc_table[__crc(data) ^ data[2]];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169}
170
171/* Check FCS */
172static inline int __check_fcs(u8 *data, int type, u8 fcs)
173{
174 u8 f = __crc(data);
175
176 if (type != RFCOMM_UIH)
177 f = rfcomm_crc_table[f ^ data[2]];
178
179 return rfcomm_crc_table[f ^ fcs] != 0xcf;
180}
181
182/* ---- L2CAP callbacks ---- */
183static void rfcomm_l2state_change(struct sock *sk)
184{
185 BT_DBG("%p state %d", sk, sk->sk_state);
Andrei Emeltchenko534c92f2010-10-01 12:05:11 +0300186 rfcomm_schedule();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187}
188
189static void rfcomm_l2data_ready(struct sock *sk, int bytes)
190{
191 BT_DBG("%p bytes %d", sk, bytes);
Andrei Emeltchenko534c92f2010-10-01 12:05:11 +0300192 rfcomm_schedule();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193}
194
195static int rfcomm_l2sock_create(struct socket **sock)
196{
197 int err;
198
199 BT_DBG("");
200
201 err = sock_create_kern(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP, sock);
202 if (!err) {
203 struct sock *sk = (*sock)->sk;
204 sk->sk_data_ready = rfcomm_l2data_ready;
205 sk->sk_state_change = rfcomm_l2state_change;
206 }
207 return err;
208}
209
Gustavo Padovan6039aa732012-05-23 04:04:18 -0300210static int rfcomm_check_security(struct rfcomm_dlc *d)
Marcel Holtmann77db1982008-07-14 20:13:45 +0200211{
212 struct sock *sk = d->session->sock->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300213 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
214
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100215 __u8 auth_type;
Marcel Holtmann77db1982008-07-14 20:13:45 +0200216
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100217 switch (d->sec_level) {
218 case BT_SECURITY_HIGH:
Marcel Holtmann2c068e02014-01-15 22:37:41 -0800219 case BT_SECURITY_FIPS:
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100220 auth_type = HCI_AT_GENERAL_BONDING_MITM;
221 break;
222 case BT_SECURITY_MEDIUM:
223 auth_type = HCI_AT_GENERAL_BONDING;
224 break;
225 default:
226 auth_type = HCI_AT_NO_BONDING;
227 break;
228 }
229
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300230 return hci_conn_security(conn->hcon, d->sec_level, auth_type);
Marcel Holtmann77db1982008-07-14 20:13:45 +0200231}
232
Luiz Augusto von Dentz9e726b12009-07-15 13:50:58 -0300233static void rfcomm_session_timeout(unsigned long arg)
234{
235 struct rfcomm_session *s = (void *) arg;
236
237 BT_DBG("session %p state %ld", s, s->state);
238
239 set_bit(RFCOMM_TIMED_OUT, &s->flags);
Andrei Emeltchenko534c92f2010-10-01 12:05:11 +0300240 rfcomm_schedule();
Luiz Augusto von Dentz9e726b12009-07-15 13:50:58 -0300241}
242
243static void rfcomm_session_set_timer(struct rfcomm_session *s, long timeout)
244{
245 BT_DBG("session %p state %ld timeout %ld", s, s->state, timeout);
246
Dean Jenkins08c30ac2013-02-28 14:21:56 +0000247 mod_timer(&s->timer, jiffies + timeout);
Luiz Augusto von Dentz9e726b12009-07-15 13:50:58 -0300248}
249
250static void rfcomm_session_clear_timer(struct rfcomm_session *s)
251{
252 BT_DBG("session %p state %ld", s, s->state);
253
Dean Jenkins08c30ac2013-02-28 14:21:56 +0000254 del_timer_sync(&s->timer);
Luiz Augusto von Dentz9e726b12009-07-15 13:50:58 -0300255}
256
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257/* ---- RFCOMM DLCs ---- */
258static void rfcomm_dlc_timeout(unsigned long arg)
259{
260 struct rfcomm_dlc *d = (void *) arg;
261
262 BT_DBG("dlc %p state %ld", d, d->state);
263
264 set_bit(RFCOMM_TIMED_OUT, &d->flags);
265 rfcomm_dlc_put(d);
Andrei Emeltchenko534c92f2010-10-01 12:05:11 +0300266 rfcomm_schedule();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267}
268
269static void rfcomm_dlc_set_timer(struct rfcomm_dlc *d, long timeout)
270{
271 BT_DBG("dlc %p state %ld timeout %ld", d, d->state, timeout);
272
273 if (!mod_timer(&d->timer, jiffies + timeout))
274 rfcomm_dlc_hold(d);
275}
276
277static void rfcomm_dlc_clear_timer(struct rfcomm_dlc *d)
278{
279 BT_DBG("dlc %p state %ld", d, d->state);
280
Ying Xue25cc4ae2013-02-03 20:32:57 +0000281 if (del_timer(&d->timer))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 rfcomm_dlc_put(d);
283}
284
285static void rfcomm_dlc_clear_state(struct rfcomm_dlc *d)
286{
287 BT_DBG("%p", d);
288
289 d->state = BT_OPEN;
290 d->flags = 0;
291 d->mscex = 0;
Johan Hedberg183f7322010-12-06 15:56:17 +0200292 d->sec_level = BT_SECURITY_LOW;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 d->mtu = RFCOMM_DEFAULT_MTU;
294 d->v24_sig = RFCOMM_V24_RTC | RFCOMM_V24_RTR | RFCOMM_V24_DV;
295
296 d->cfc = RFCOMM_CFC_DISABLED;
297 d->rx_credits = RFCOMM_DEFAULT_CREDITS;
298}
299
Al Virodd0fc662005-10-07 07:46:04 +0100300struct rfcomm_dlc *rfcomm_dlc_alloc(gfp_t prio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301{
Marcel Holtmann25ea6db2006-07-06 15:40:09 +0200302 struct rfcomm_dlc *d = kzalloc(sizeof(*d), prio);
303
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 if (!d)
305 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800307 setup_timer(&d->timer, rfcomm_dlc_timeout, (unsigned long)d);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
309 skb_queue_head_init(&d->tx_queue);
310 spin_lock_init(&d->lock);
311 atomic_set(&d->refcnt, 1);
312
313 rfcomm_dlc_clear_state(d);
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900314
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 BT_DBG("%p", d);
Marcel Holtmann25ea6db2006-07-06 15:40:09 +0200316
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 return d;
318}
319
320void rfcomm_dlc_free(struct rfcomm_dlc *d)
321{
322 BT_DBG("%p", d);
323
324 skb_queue_purge(&d->tx_queue);
325 kfree(d);
326}
327
328static void rfcomm_dlc_link(struct rfcomm_session *s, struct rfcomm_dlc *d)
329{
330 BT_DBG("dlc %p session %p", d, s);
331
Luiz Augusto von Dentz9e726b12009-07-15 13:50:58 -0300332 rfcomm_session_clear_timer(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 rfcomm_dlc_hold(d);
334 list_add(&d->list, &s->dlcs);
335 d->session = s;
336}
337
338static void rfcomm_dlc_unlink(struct rfcomm_dlc *d)
339{
340 struct rfcomm_session *s = d->session;
341
342 BT_DBG("dlc %p refcnt %d session %p", d, atomic_read(&d->refcnt), s);
343
344 list_del(&d->list);
345 d->session = NULL;
346 rfcomm_dlc_put(d);
347
Luiz Augusto von Dentz9e726b12009-07-15 13:50:58 -0300348 if (list_empty(&s->dlcs))
349 rfcomm_session_set_timer(s, RFCOMM_IDLE_TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350}
351
352static struct rfcomm_dlc *rfcomm_dlc_get(struct rfcomm_session *s, u8 dlci)
353{
354 struct rfcomm_dlc *d;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200356 list_for_each_entry(d, &s->dlcs, list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 if (d->dlci == dlci)
358 return d;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200359
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 return NULL;
361}
362
Peter Hurleyc10a8482014-02-09 20:59:10 -0500363static int rfcomm_check_channel(u8 channel)
364{
365 return channel < 1 || channel > 30;
366}
367
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel)
369{
370 struct rfcomm_session *s;
371 int err = 0;
372 u8 dlci;
373
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +0300374 BT_DBG("dlc %p state %ld %pMR -> %pMR channel %d",
375 d, d->state, src, dst, channel);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376
Peter Hurleyc10a8482014-02-09 20:59:10 -0500377 if (rfcomm_check_channel(channel))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 return -EINVAL;
379
380 if (d->state != BT_OPEN && d->state != BT_CLOSED)
381 return 0;
382
383 s = rfcomm_session_get(src, dst);
384 if (!s) {
Luiz Augusto von Dentz63ce0902010-08-19 14:06:10 +0300385 s = rfcomm_session_create(src, dst, d->sec_level, &err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 if (!s)
387 return err;
388 }
389
390 dlci = __dlci(!s->initiator, channel);
391
392 /* Check if DLCI already exists */
393 if (rfcomm_dlc_get(s, dlci))
394 return -EBUSY;
395
396 rfcomm_dlc_clear_state(d);
397
398 d->dlci = dlci;
399 d->addr = __addr(s->initiator, dlci);
400 d->priority = 7;
401
Marcel Holtmann77db1982008-07-14 20:13:45 +0200402 d->state = BT_CONFIG;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 rfcomm_dlc_link(s, d);
404
Marcel Holtmann77db1982008-07-14 20:13:45 +0200405 d->out = 1;
406
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 d->mtu = s->mtu;
408 d->cfc = (s->cfc == RFCOMM_CFC_UNKNOWN) ? 0 : s->cfc;
409
Marcel Holtmann77db1982008-07-14 20:13:45 +0200410 if (s->state == BT_CONNECTED) {
Marcel Holtmann9f2c8a02009-01-15 21:58:40 +0100411 if (rfcomm_check_security(d))
Marcel Holtmann77db1982008-07-14 20:13:45 +0200412 rfcomm_send_pn(s, 1, d);
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100413 else
414 set_bit(RFCOMM_AUTH_PENDING, &d->flags);
Marcel Holtmann77db1982008-07-14 20:13:45 +0200415 }
416
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 rfcomm_dlc_set_timer(d, RFCOMM_CONN_TIMEOUT);
Marcel Holtmann77db1982008-07-14 20:13:45 +0200418
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 return 0;
420}
421
422int rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel)
423{
424 int r;
425
426 rfcomm_lock();
427
428 r = __rfcomm_dlc_open(d, src, dst, channel);
429
430 rfcomm_unlock();
431 return r;
432}
433
Peter Hurleyf6223572014-02-09 20:59:13 -0500434static void __rfcomm_dlc_disconn(struct rfcomm_dlc *d)
435{
436 struct rfcomm_session *s = d->session;
437
438 d->state = BT_DISCONN;
439 if (skb_queue_empty(&d->tx_queue)) {
440 rfcomm_send_disc(s, d->dlci);
441 rfcomm_dlc_set_timer(d, RFCOMM_DISC_TIMEOUT);
442 } else {
443 rfcomm_queue_disc(d);
444 rfcomm_dlc_set_timer(d, RFCOMM_DISC_TIMEOUT * 2);
445 }
446}
447
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
449{
450 struct rfcomm_session *s = d->session;
451 if (!s)
452 return 0;
453
454 BT_DBG("dlc %p state %ld dlci %d err %d session %p",
455 d, d->state, d->dlci, err, s);
456
457 switch (d->state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 case BT_CONNECT:
Marcel Holtmannbb23c0a2009-01-15 21:56:48 +0100459 case BT_CONFIG:
Peter Hurley5998e042014-02-09 20:59:12 -0500460 case BT_OPEN:
461 case BT_CONNECT2:
Marcel Holtmannbb23c0a2009-01-15 21:56:48 +0100462 if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
463 set_bit(RFCOMM_AUTH_REJECT, &d->flags);
Andrei Emeltchenko534c92f2010-10-01 12:05:11 +0300464 rfcomm_schedule();
Peter Hurley5998e042014-02-09 20:59:12 -0500465 return 0;
Marcel Holtmannbb23c0a2009-01-15 21:56:48 +0100466 }
Peter Hurley5998e042014-02-09 20:59:12 -0500467 }
468
469 switch (d->state) {
470 case BT_CONNECT:
Marcel Holtmannbb23c0a2009-01-15 21:56:48 +0100471 case BT_CONNECTED:
Peter Hurleyf6223572014-02-09 20:59:13 -0500472 __rfcomm_dlc_disconn(d);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 break;
474
Peter Hurleyc4fd3182014-02-09 20:59:14 -0500475 case BT_CONFIG:
476 if (s->state != BT_BOUND) {
477 __rfcomm_dlc_disconn(d);
478 break;
479 }
480 /* if closing a dlc in a session that hasn't been started,
481 * just close and unlink the dlc
482 */
483
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 default:
485 rfcomm_dlc_clear_timer(d);
486
487 rfcomm_dlc_lock(d);
488 d->state = BT_CLOSED;
Dave Young1905f6c2008-04-01 23:59:06 -0700489 d->state_change(d, err);
Arjan van de Ven4c8411f2008-05-29 01:32:47 -0700490 rfcomm_dlc_unlock(d);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491
492 skb_queue_purge(&d->tx_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 rfcomm_dlc_unlink(d);
494 }
495
496 return 0;
497}
498
499int rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
500{
Dean Jenkinsc06f7d52013-02-28 14:21:54 +0000501 int r = 0;
502 struct rfcomm_dlc *d_list;
503 struct rfcomm_session *s, *s_list;
504
505 BT_DBG("dlc %p state %ld dlci %d err %d", d, d->state, d->dlci, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
507 rfcomm_lock();
508
Dean Jenkinsc06f7d52013-02-28 14:21:54 +0000509 s = d->session;
510 if (!s)
511 goto no_session;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
Dean Jenkinsc06f7d52013-02-28 14:21:54 +0000513 /* after waiting on the mutex check the session still exists
514 * then check the dlc still exists
515 */
516 list_for_each_entry(s_list, &session_list, list) {
517 if (s_list == s) {
518 list_for_each_entry(d_list, &s->dlcs, list) {
519 if (d_list == d) {
520 r = __rfcomm_dlc_close(d, err);
521 break;
522 }
523 }
524 break;
525 }
526 }
527
528no_session:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 rfcomm_unlock();
530 return r;
531}
532
Peter Hurleyc10a8482014-02-09 20:59:10 -0500533struct rfcomm_dlc *rfcomm_dlc_exists(bdaddr_t *src, bdaddr_t *dst, u8 channel)
534{
535 struct rfcomm_session *s;
536 struct rfcomm_dlc *dlc = NULL;
537 u8 dlci;
538
539 if (rfcomm_check_channel(channel))
540 return ERR_PTR(-EINVAL);
541
542 rfcomm_lock();
543 s = rfcomm_session_get(src, dst);
544 if (s) {
545 dlci = __dlci(!s->initiator, channel);
546 dlc = rfcomm_dlc_get(s, dlci);
547 }
548 rfcomm_unlock();
549 return dlc;
550}
551
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb)
553{
554 int len = skb->len;
555
556 if (d->state != BT_CONNECTED)
557 return -ENOTCONN;
558
559 BT_DBG("dlc %p mtu %d len %d", d, d->mtu, len);
560
561 if (len > d->mtu)
562 return -EINVAL;
563
564 rfcomm_make_uih(skb, d->addr);
565 skb_queue_tail(&d->tx_queue, skb);
566
567 if (!test_bit(RFCOMM_TX_THROTTLED, &d->flags))
Andrei Emeltchenko534c92f2010-10-01 12:05:11 +0300568 rfcomm_schedule();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 return len;
570}
571
Harvey Harrisonb5606c22008-02-13 15:03:16 -0800572void __rfcomm_dlc_throttle(struct rfcomm_dlc *d)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573{
574 BT_DBG("dlc %p state %ld", d, d->state);
575
576 if (!d->cfc) {
577 d->v24_sig |= RFCOMM_V24_FC;
578 set_bit(RFCOMM_MSC_PENDING, &d->flags);
579 }
Andrei Emeltchenko534c92f2010-10-01 12:05:11 +0300580 rfcomm_schedule();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581}
582
Harvey Harrisonb5606c22008-02-13 15:03:16 -0800583void __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584{
585 BT_DBG("dlc %p state %ld", d, d->state);
586
587 if (!d->cfc) {
588 d->v24_sig &= ~RFCOMM_V24_FC;
589 set_bit(RFCOMM_MSC_PENDING, &d->flags);
590 }
Andrei Emeltchenko534c92f2010-10-01 12:05:11 +0300591 rfcomm_schedule();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592}
593
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900594/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 Set/get modem status functions use _local_ status i.e. what we report
596 to the other side.
597 Remote status is provided by dlc->modem_status() callback.
598 */
599int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig)
600{
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900601 BT_DBG("dlc %p state %ld v24_sig 0x%x",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 d, d->state, v24_sig);
603
604 if (test_bit(RFCOMM_RX_THROTTLED, &d->flags))
605 v24_sig |= RFCOMM_V24_FC;
606 else
607 v24_sig &= ~RFCOMM_V24_FC;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900608
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 d->v24_sig = v24_sig;
610
611 if (!test_and_set_bit(RFCOMM_MSC_PENDING, &d->flags))
Andrei Emeltchenko534c92f2010-10-01 12:05:11 +0300612 rfcomm_schedule();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613
614 return 0;
615}
616
617int rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig)
618{
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900619 BT_DBG("dlc %p state %ld v24_sig 0x%x",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 d, d->state, d->v24_sig);
621
622 *v24_sig = d->v24_sig;
623 return 0;
624}
625
626/* ---- RFCOMM sessions ---- */
627static struct rfcomm_session *rfcomm_session_add(struct socket *sock, int state)
628{
Marcel Holtmann25ea6db2006-07-06 15:40:09 +0200629 struct rfcomm_session *s = kzalloc(sizeof(*s), GFP_KERNEL);
630
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 if (!s)
632 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633
634 BT_DBG("session %p sock %p", s, sock);
635
Luiz Augusto von Dentz9e726b12009-07-15 13:50:58 -0300636 setup_timer(&s->timer, rfcomm_session_timeout, (unsigned long) s);
637
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 INIT_LIST_HEAD(&s->dlcs);
639 s->state = state;
640 s->sock = sock;
641
642 s->mtu = RFCOMM_DEFAULT_MTU;
Marcel Holtmann7c2660b2006-07-03 10:02:51 +0200643 s->cfc = disable_cfc ? RFCOMM_CFC_DISABLED : RFCOMM_CFC_UNKNOWN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
645 /* Do not increment module usage count for listening sessions.
646 * Otherwise we won't be able to unload the module. */
647 if (state != BT_LISTEN)
648 if (!try_module_get(THIS_MODULE)) {
649 kfree(s);
650 return NULL;
651 }
652
653 list_add(&s->list, &session_list);
654
655 return s;
656}
657
Dean Jenkins8ff52f72013-02-28 14:21:55 +0000658static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659{
660 int state = s->state;
661
662 BT_DBG("session %p state %ld", s, s->state);
663
664 list_del(&s->list);
665
Luiz Augusto von Dentz9e726b12009-07-15 13:50:58 -0300666 rfcomm_session_clear_timer(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 sock_release(s->sock);
668 kfree(s);
669
670 if (state != BT_LISTEN)
671 module_put(THIS_MODULE);
Dean Jenkins8ff52f72013-02-28 14:21:55 +0000672
673 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674}
675
676static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst)
677{
678 struct rfcomm_session *s;
679 struct list_head *p, *n;
Marcel Holtmann24bc10c2013-10-13 09:49:54 -0700680 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 list_for_each_safe(p, n, &session_list) {
682 s = list_entry(p, struct rfcomm_session, list);
Marcel Holtmann24bc10c2013-10-13 09:49:54 -0700683 chan = l2cap_pi(s->sock->sk)->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684
Marcel Holtmann24bc10c2013-10-13 09:49:54 -0700685 if ((!bacmp(src, BDADDR_ANY) || !bacmp(&chan->src, src)) &&
686 !bacmp(&chan->dst, dst))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 return s;
688 }
689 return NULL;
690}
691
Dean Jenkins8ff52f72013-02-28 14:21:55 +0000692static struct rfcomm_session *rfcomm_session_close(struct rfcomm_session *s,
693 int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694{
695 struct rfcomm_dlc *d;
696 struct list_head *p, *n;
697
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 s->state = BT_CLOSED;
699
Dean Jenkins24fd6422013-02-28 14:21:58 +0000700 BT_DBG("session %p state %ld err %d", s, s->state, err);
701
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 /* Close all dlcs */
703 list_for_each_safe(p, n, &s->dlcs) {
704 d = list_entry(p, struct rfcomm_dlc, list);
705 d->state = BT_CLOSED;
706 __rfcomm_dlc_close(d, err);
707 }
708
Luiz Augusto von Dentz9e726b12009-07-15 13:50:58 -0300709 rfcomm_session_clear_timer(s);
Dean Jenkins08c30ac2013-02-28 14:21:56 +0000710 return rfcomm_session_del(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711}
712
Luiz Augusto von Dentz63ce0902010-08-19 14:06:10 +0300713static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
714 bdaddr_t *dst,
715 u8 sec_level,
716 int *err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717{
718 struct rfcomm_session *s = NULL;
719 struct sockaddr_l2 addr;
720 struct socket *sock;
721 struct sock *sk;
722
Andrei Emeltchenko6ed93dc2012-09-25 12:49:43 +0300723 BT_DBG("%pMR -> %pMR", src, dst);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724
725 *err = rfcomm_l2sock_create(&sock);
726 if (*err < 0)
727 return NULL;
728
729 bacpy(&addr.l2_bdaddr, src);
730 addr.l2_family = AF_BLUETOOTH;
731 addr.l2_psm = 0;
Marcel Holtmann37e62f52009-02-17 21:49:33 +0100732 addr.l2_cid = 0;
Seung-Woo Kimc507f132013-11-05 16:02:24 +0900733 addr.l2_bdaddr_type = BDADDR_BREDR;
Marcel Holtmann48db9ca2007-05-05 00:36:06 +0200734 *err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 if (*err < 0)
736 goto failed;
737
738 /* Set L2CAP options */
739 sk = sock->sk;
740 lock_sock(sk);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300741 l2cap_pi(sk)->chan->imtu = l2cap_mtu;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300742 l2cap_pi(sk)->chan->sec_level = sec_level;
Marcel Holtmanneae38ee2009-10-05 12:23:48 +0200743 if (l2cap_ertm)
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300744 l2cap_pi(sk)->chan->mode = L2CAP_MODE_ERTM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 release_sock(sk);
746
747 s = rfcomm_session_add(sock, BT_BOUND);
748 if (!s) {
749 *err = -ENOMEM;
750 goto failed;
751 }
752
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 s->initiator = 1;
754
755 bacpy(&addr.l2_bdaddr, dst);
756 addr.l2_family = AF_BLUETOOTH;
Syam Sidhardhan5bcb8092012-10-10 22:09:29 +0530757 addr.l2_psm = __constant_cpu_to_le16(RFCOMM_PSM);
Marcel Holtmann37e62f52009-02-17 21:49:33 +0100758 addr.l2_cid = 0;
Seung-Woo Kim8992da02013-11-05 17:15:42 +0900759 addr.l2_bdaddr_type = BDADDR_BREDR;
Marcel Holtmann48db9ca2007-05-05 00:36:06 +0200760 *err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK);
Marcel Holtmannb4c612a2006-09-23 09:54:38 +0200761 if (*err == 0 || *err == -EINPROGRESS)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 return s;
763
Dean Jenkins8ff52f72013-02-28 14:21:55 +0000764 return rfcomm_session_del(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765
766failed:
767 sock_release(sock);
768 return NULL;
769}
770
771void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, bdaddr_t *dst)
772{
Marcel Holtmann24bc10c2013-10-13 09:49:54 -0700773 struct l2cap_chan *chan = l2cap_pi(s->sock->sk)->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 if (src)
Marcel Holtmann24bc10c2013-10-13 09:49:54 -0700775 bacpy(src, &chan->src);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 if (dst)
Marcel Holtmann24bc10c2013-10-13 09:49:54 -0700777 bacpy(dst, &chan->dst);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778}
779
780/* ---- RFCOMM frame sending ---- */
Gustavo F. Padovan54365382011-12-20 16:30:44 -0200781static int rfcomm_send_frame(struct rfcomm_session *s, u8 *data, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 struct kvec iv = { data, len };
784 struct msghdr msg;
785
Gustavo F. Padovan54365382011-12-20 16:30:44 -0200786 BT_DBG("session %p len %d", s, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787
788 memset(&msg, 0, sizeof(msg));
789
Gustavo F. Padovan54365382011-12-20 16:30:44 -0200790 return kernel_sendmsg(s->sock, &msg, &iv, 1, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791}
792
Luiz Augusto von Dentz262038f2011-11-01 10:58:58 +0200793static int rfcomm_send_cmd(struct rfcomm_session *s, struct rfcomm_cmd *cmd)
794{
795 BT_DBG("%p cmd %u", s, cmd->ctrl);
796
Gustavo F. Padovan54365382011-12-20 16:30:44 -0200797 return rfcomm_send_frame(s, (void *) cmd, sizeof(*cmd));
Luiz Augusto von Dentz262038f2011-11-01 10:58:58 +0200798}
799
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800static int rfcomm_send_sabm(struct rfcomm_session *s, u8 dlci)
801{
802 struct rfcomm_cmd cmd;
803
804 BT_DBG("%p dlci %d", s, dlci);
805
806 cmd.addr = __addr(s->initiator, dlci);
807 cmd.ctrl = __ctrl(RFCOMM_SABM, 1);
808 cmd.len = __len8(0);
809 cmd.fcs = __fcs2((u8 *) &cmd);
810
Luiz Augusto von Dentz262038f2011-11-01 10:58:58 +0200811 return rfcomm_send_cmd(s, &cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812}
813
814static int rfcomm_send_ua(struct rfcomm_session *s, u8 dlci)
815{
816 struct rfcomm_cmd cmd;
817
818 BT_DBG("%p dlci %d", s, dlci);
819
820 cmd.addr = __addr(!s->initiator, dlci);
821 cmd.ctrl = __ctrl(RFCOMM_UA, 1);
822 cmd.len = __len8(0);
823 cmd.fcs = __fcs2((u8 *) &cmd);
824
Luiz Augusto von Dentz262038f2011-11-01 10:58:58 +0200825 return rfcomm_send_cmd(s, &cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826}
827
828static int rfcomm_send_disc(struct rfcomm_session *s, u8 dlci)
829{
830 struct rfcomm_cmd cmd;
831
832 BT_DBG("%p dlci %d", s, dlci);
833
834 cmd.addr = __addr(s->initiator, dlci);
835 cmd.ctrl = __ctrl(RFCOMM_DISC, 1);
836 cmd.len = __len8(0);
837 cmd.fcs = __fcs2((u8 *) &cmd);
838
Luiz Augusto von Dentz262038f2011-11-01 10:58:58 +0200839 return rfcomm_send_cmd(s, &cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840}
841
842static int rfcomm_queue_disc(struct rfcomm_dlc *d)
843{
844 struct rfcomm_cmd *cmd;
845 struct sk_buff *skb;
846
847 BT_DBG("dlc %p dlci %d", d, d->dlci);
848
849 skb = alloc_skb(sizeof(*cmd), GFP_KERNEL);
850 if (!skb)
851 return -ENOMEM;
852
853 cmd = (void *) __skb_put(skb, sizeof(*cmd));
854 cmd->addr = d->addr;
855 cmd->ctrl = __ctrl(RFCOMM_DISC, 1);
856 cmd->len = __len8(0);
857 cmd->fcs = __fcs2((u8 *) cmd);
858
859 skb_queue_tail(&d->tx_queue, skb);
Andrei Emeltchenko534c92f2010-10-01 12:05:11 +0300860 rfcomm_schedule();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 return 0;
862}
863
864static int rfcomm_send_dm(struct rfcomm_session *s, u8 dlci)
865{
866 struct rfcomm_cmd cmd;
867
868 BT_DBG("%p dlci %d", s, dlci);
869
870 cmd.addr = __addr(!s->initiator, dlci);
871 cmd.ctrl = __ctrl(RFCOMM_DM, 1);
872 cmd.len = __len8(0);
873 cmd.fcs = __fcs2((u8 *) &cmd);
874
Luiz Augusto von Dentz262038f2011-11-01 10:58:58 +0200875 return rfcomm_send_cmd(s, &cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876}
877
878static int rfcomm_send_nsc(struct rfcomm_session *s, int cr, u8 type)
879{
880 struct rfcomm_hdr *hdr;
881 struct rfcomm_mcc *mcc;
882 u8 buf[16], *ptr = buf;
883
884 BT_DBG("%p cr %d type %d", s, cr, type);
885
886 hdr = (void *) ptr; ptr += sizeof(*hdr);
887 hdr->addr = __addr(s->initiator, 0);
888 hdr->ctrl = __ctrl(RFCOMM_UIH, 0);
889 hdr->len = __len8(sizeof(*mcc) + 1);
890
891 mcc = (void *) ptr; ptr += sizeof(*mcc);
892 mcc->type = __mcc_type(cr, RFCOMM_NSC);
893 mcc->len = __len8(1);
894
895 /* Type that we didn't like */
896 *ptr = __mcc_type(cr, type); ptr++;
897
898 *ptr = __fcs(buf); ptr++;
899
Gustavo F. Padovan54365382011-12-20 16:30:44 -0200900 return rfcomm_send_frame(s, buf, ptr - buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901}
902
903static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d)
904{
905 struct rfcomm_hdr *hdr;
906 struct rfcomm_mcc *mcc;
907 struct rfcomm_pn *pn;
908 u8 buf[16], *ptr = buf;
909
910 BT_DBG("%p cr %d dlci %d mtu %d", s, cr, d->dlci, d->mtu);
911
912 hdr = (void *) ptr; ptr += sizeof(*hdr);
913 hdr->addr = __addr(s->initiator, 0);
914 hdr->ctrl = __ctrl(RFCOMM_UIH, 0);
915 hdr->len = __len8(sizeof(*mcc) + sizeof(*pn));
916
917 mcc = (void *) ptr; ptr += sizeof(*mcc);
918 mcc->type = __mcc_type(cr, RFCOMM_PN);
919 mcc->len = __len8(sizeof(*pn));
920
921 pn = (void *) ptr; ptr += sizeof(*pn);
922 pn->dlci = d->dlci;
923 pn->priority = d->priority;
924 pn->ack_timer = 0;
925 pn->max_retrans = 0;
926
927 if (s->cfc) {
928 pn->flow_ctrl = cr ? 0xf0 : 0xe0;
929 pn->credits = RFCOMM_DEFAULT_CREDITS;
930 } else {
931 pn->flow_ctrl = 0;
932 pn->credits = 0;
933 }
934
Marcel Holtmann98bcd082006-07-14 11:42:12 +0200935 if (cr && channel_mtu >= 0)
Marcel Holtmannb4324b52009-06-07 18:06:51 +0200936 pn->mtu = cpu_to_le16(channel_mtu);
Marcel Holtmann98bcd082006-07-14 11:42:12 +0200937 else
Marcel Holtmannb4324b52009-06-07 18:06:51 +0200938 pn->mtu = cpu_to_le16(d->mtu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939
940 *ptr = __fcs(buf); ptr++;
941
Gustavo F. Padovan54365382011-12-20 16:30:44 -0200942 return rfcomm_send_frame(s, buf, ptr - buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943}
944
J. Suter3a5e9032005-08-09 20:28:46 -0700945int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
946 u8 bit_rate, u8 data_bits, u8 stop_bits,
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900947 u8 parity, u8 flow_ctrl_settings,
J. Suter3a5e9032005-08-09 20:28:46 -0700948 u8 xon_char, u8 xoff_char, u16 param_mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949{
950 struct rfcomm_hdr *hdr;
951 struct rfcomm_mcc *mcc;
952 struct rfcomm_rpn *rpn;
953 u8 buf[16], *ptr = buf;
954
955 BT_DBG("%p cr %d dlci %d bit_r 0x%x data_b 0x%x stop_b 0x%x parity 0x%x"
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900956 " flwc_s 0x%x xon_c 0x%x xoff_c 0x%x p_mask 0x%x",
957 s, cr, dlci, bit_rate, data_bits, stop_bits, parity,
J. Suter3a5e9032005-08-09 20:28:46 -0700958 flow_ctrl_settings, xon_char, xoff_char, param_mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959
960 hdr = (void *) ptr; ptr += sizeof(*hdr);
961 hdr->addr = __addr(s->initiator, 0);
962 hdr->ctrl = __ctrl(RFCOMM_UIH, 0);
963 hdr->len = __len8(sizeof(*mcc) + sizeof(*rpn));
964
965 mcc = (void *) ptr; ptr += sizeof(*mcc);
966 mcc->type = __mcc_type(cr, RFCOMM_RPN);
967 mcc->len = __len8(sizeof(*rpn));
968
969 rpn = (void *) ptr; ptr += sizeof(*rpn);
970 rpn->dlci = __addr(1, dlci);
971 rpn->bit_rate = bit_rate;
972 rpn->line_settings = __rpn_line_settings(data_bits, stop_bits, parity);
973 rpn->flow_ctrl = flow_ctrl_settings;
974 rpn->xon_char = xon_char;
975 rpn->xoff_char = xoff_char;
Al Viroe8db8c92006-11-08 00:28:44 -0800976 rpn->param_mask = cpu_to_le16(param_mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977
978 *ptr = __fcs(buf); ptr++;
979
Gustavo F. Padovan54365382011-12-20 16:30:44 -0200980 return rfcomm_send_frame(s, buf, ptr - buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981}
982
983static int rfcomm_send_rls(struct rfcomm_session *s, int cr, u8 dlci, u8 status)
984{
985 struct rfcomm_hdr *hdr;
986 struct rfcomm_mcc *mcc;
987 struct rfcomm_rls *rls;
988 u8 buf[16], *ptr = buf;
989
990 BT_DBG("%p cr %d status 0x%x", s, cr, status);
991
992 hdr = (void *) ptr; ptr += sizeof(*hdr);
993 hdr->addr = __addr(s->initiator, 0);
994 hdr->ctrl = __ctrl(RFCOMM_UIH, 0);
995 hdr->len = __len8(sizeof(*mcc) + sizeof(*rls));
996
997 mcc = (void *) ptr; ptr += sizeof(*mcc);
998 mcc->type = __mcc_type(cr, RFCOMM_RLS);
999 mcc->len = __len8(sizeof(*rls));
1000
1001 rls = (void *) ptr; ptr += sizeof(*rls);
1002 rls->dlci = __addr(1, dlci);
1003 rls->status = status;
1004
1005 *ptr = __fcs(buf); ptr++;
1006
Gustavo F. Padovan54365382011-12-20 16:30:44 -02001007 return rfcomm_send_frame(s, buf, ptr - buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008}
1009
1010static int rfcomm_send_msc(struct rfcomm_session *s, int cr, u8 dlci, u8 v24_sig)
1011{
1012 struct rfcomm_hdr *hdr;
1013 struct rfcomm_mcc *mcc;
1014 struct rfcomm_msc *msc;
1015 u8 buf[16], *ptr = buf;
1016
1017 BT_DBG("%p cr %d v24 0x%x", s, cr, v24_sig);
1018
1019 hdr = (void *) ptr; ptr += sizeof(*hdr);
1020 hdr->addr = __addr(s->initiator, 0);
1021 hdr->ctrl = __ctrl(RFCOMM_UIH, 0);
1022 hdr->len = __len8(sizeof(*mcc) + sizeof(*msc));
1023
1024 mcc = (void *) ptr; ptr += sizeof(*mcc);
1025 mcc->type = __mcc_type(cr, RFCOMM_MSC);
1026 mcc->len = __len8(sizeof(*msc));
1027
1028 msc = (void *) ptr; ptr += sizeof(*msc);
1029 msc->dlci = __addr(1, dlci);
1030 msc->v24_sig = v24_sig | 0x01;
1031
1032 *ptr = __fcs(buf); ptr++;
1033
Gustavo F. Padovan54365382011-12-20 16:30:44 -02001034 return rfcomm_send_frame(s, buf, ptr - buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035}
1036
1037static int rfcomm_send_fcoff(struct rfcomm_session *s, int cr)
1038{
1039 struct rfcomm_hdr *hdr;
1040 struct rfcomm_mcc *mcc;
1041 u8 buf[16], *ptr = buf;
1042
1043 BT_DBG("%p cr %d", s, cr);
1044
1045 hdr = (void *) ptr; ptr += sizeof(*hdr);
1046 hdr->addr = __addr(s->initiator, 0);
1047 hdr->ctrl = __ctrl(RFCOMM_UIH, 0);
1048 hdr->len = __len8(sizeof(*mcc));
1049
1050 mcc = (void *) ptr; ptr += sizeof(*mcc);
1051 mcc->type = __mcc_type(cr, RFCOMM_FCOFF);
1052 mcc->len = __len8(0);
1053
1054 *ptr = __fcs(buf); ptr++;
1055
Gustavo F. Padovan54365382011-12-20 16:30:44 -02001056 return rfcomm_send_frame(s, buf, ptr - buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057}
1058
1059static int rfcomm_send_fcon(struct rfcomm_session *s, int cr)
1060{
1061 struct rfcomm_hdr *hdr;
1062 struct rfcomm_mcc *mcc;
1063 u8 buf[16], *ptr = buf;
1064
1065 BT_DBG("%p cr %d", s, cr);
1066
1067 hdr = (void *) ptr; ptr += sizeof(*hdr);
1068 hdr->addr = __addr(s->initiator, 0);
1069 hdr->ctrl = __ctrl(RFCOMM_UIH, 0);
1070 hdr->len = __len8(sizeof(*mcc));
1071
1072 mcc = (void *) ptr; ptr += sizeof(*mcc);
1073 mcc->type = __mcc_type(cr, RFCOMM_FCON);
1074 mcc->len = __len8(0);
1075
1076 *ptr = __fcs(buf); ptr++;
1077
Gustavo F. Padovan54365382011-12-20 16:30:44 -02001078 return rfcomm_send_frame(s, buf, ptr - buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079}
1080
1081static int rfcomm_send_test(struct rfcomm_session *s, int cr, u8 *pattern, int len)
1082{
1083 struct socket *sock = s->sock;
1084 struct kvec iv[3];
1085 struct msghdr msg;
1086 unsigned char hdr[5], crc[1];
1087
1088 if (len > 125)
1089 return -EINVAL;
1090
1091 BT_DBG("%p cr %d", s, cr);
1092
1093 hdr[0] = __addr(s->initiator, 0);
1094 hdr[1] = __ctrl(RFCOMM_UIH, 0);
1095 hdr[2] = 0x01 | ((len + 2) << 1);
1096 hdr[3] = 0x01 | ((cr & 0x01) << 1) | (RFCOMM_TEST << 2);
1097 hdr[4] = 0x01 | (len << 1);
1098
1099 crc[0] = __fcs(hdr);
1100
1101 iv[0].iov_base = hdr;
1102 iv[0].iov_len = 5;
1103 iv[1].iov_base = pattern;
1104 iv[1].iov_len = len;
1105 iv[2].iov_base = crc;
1106 iv[2].iov_len = 1;
1107
1108 memset(&msg, 0, sizeof(msg));
1109
1110 return kernel_sendmsg(sock, &msg, iv, 3, 6 + len);
1111}
1112
1113static int rfcomm_send_credits(struct rfcomm_session *s, u8 addr, u8 credits)
1114{
1115 struct rfcomm_hdr *hdr;
1116 u8 buf[16], *ptr = buf;
1117
1118 BT_DBG("%p addr %d credits %d", s, addr, credits);
1119
1120 hdr = (void *) ptr; ptr += sizeof(*hdr);
1121 hdr->addr = addr;
1122 hdr->ctrl = __ctrl(RFCOMM_UIH, 1);
1123 hdr->len = __len8(0);
1124
1125 *ptr = credits; ptr++;
1126
1127 *ptr = __fcs(buf); ptr++;
1128
Gustavo F. Padovan54365382011-12-20 16:30:44 -02001129 return rfcomm_send_frame(s, buf, ptr - buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130}
1131
1132static void rfcomm_make_uih(struct sk_buff *skb, u8 addr)
1133{
1134 struct rfcomm_hdr *hdr;
1135 int len = skb->len;
1136 u8 *crc;
1137
1138 if (len > 127) {
1139 hdr = (void *) skb_push(skb, 4);
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001140 put_unaligned(cpu_to_le16(__len16(len)), (__le16 *) &hdr->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 } else {
1142 hdr = (void *) skb_push(skb, 3);
1143 hdr->len = __len8(len);
1144 }
1145 hdr->addr = addr;
1146 hdr->ctrl = __ctrl(RFCOMM_UIH, 0);
1147
1148 crc = skb_put(skb, 1);
1149 *crc = __fcs((void *) hdr);
1150}
1151
1152/* ---- RFCOMM frame reception ---- */
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001153static struct rfcomm_session *rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154{
1155 BT_DBG("session %p state %ld dlci %d", s, s->state, dlci);
1156
1157 if (dlci) {
1158 /* Data channel */
1159 struct rfcomm_dlc *d = rfcomm_dlc_get(s, dlci);
1160 if (!d) {
1161 rfcomm_send_dm(s, dlci);
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001162 return s;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 }
1164
1165 switch (d->state) {
1166 case BT_CONNECT:
1167 rfcomm_dlc_clear_timer(d);
1168
1169 rfcomm_dlc_lock(d);
1170 d->state = BT_CONNECTED;
1171 d->state_change(d, 0);
1172 rfcomm_dlc_unlock(d);
1173
1174 rfcomm_send_msc(s, 1, dlci, d->v24_sig);
1175 break;
1176
1177 case BT_DISCONN:
1178 d->state = BT_CLOSED;
1179 __rfcomm_dlc_close(d, 0);
Marcel Holtmann9cf5b0e2007-05-05 00:36:13 +02001180
1181 if (list_empty(&s->dlcs)) {
1182 s->state = BT_DISCONN;
1183 rfcomm_send_disc(s, 0);
Mat Martineau79e65472011-12-06 16:23:26 -08001184 rfcomm_session_clear_timer(s);
Marcel Holtmann9cf5b0e2007-05-05 00:36:13 +02001185 }
1186
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 break;
1188 }
1189 } else {
1190 /* Control channel */
1191 switch (s->state) {
1192 case BT_CONNECT:
1193 s->state = BT_CONNECTED;
1194 rfcomm_process_connect(s);
1195 break;
Marcel Holtmann9cf5b0e2007-05-05 00:36:13 +02001196
1197 case BT_DISCONN:
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001198 s = rfcomm_session_close(s, ECONNRESET);
Marcel Holtmann9cf5b0e2007-05-05 00:36:13 +02001199 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 }
1201 }
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001202 return s;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203}
1204
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001205static struct rfcomm_session *rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206{
1207 int err = 0;
1208
1209 BT_DBG("session %p state %ld dlci %d", s, s->state, dlci);
1210
1211 if (dlci) {
1212 /* Data DLC */
1213 struct rfcomm_dlc *d = rfcomm_dlc_get(s, dlci);
1214 if (d) {
1215 if (d->state == BT_CONNECT || d->state == BT_CONFIG)
1216 err = ECONNREFUSED;
1217 else
1218 err = ECONNRESET;
1219
1220 d->state = BT_CLOSED;
1221 __rfcomm_dlc_close(d, err);
1222 }
1223 } else {
1224 if (s->state == BT_CONNECT)
1225 err = ECONNREFUSED;
1226 else
1227 err = ECONNRESET;
1228
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001229 s = rfcomm_session_close(s, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 }
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001231 return s;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232}
1233
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001234static struct rfcomm_session *rfcomm_recv_disc(struct rfcomm_session *s,
1235 u8 dlci)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236{
1237 int err = 0;
1238
1239 BT_DBG("session %p state %ld dlci %d", s, s->state, dlci);
1240
1241 if (dlci) {
1242 struct rfcomm_dlc *d = rfcomm_dlc_get(s, dlci);
1243 if (d) {
1244 rfcomm_send_ua(s, dlci);
1245
1246 if (d->state == BT_CONNECT || d->state == BT_CONFIG)
1247 err = ECONNREFUSED;
1248 else
1249 err = ECONNRESET;
1250
1251 d->state = BT_CLOSED;
1252 __rfcomm_dlc_close(d, err);
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001253 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 rfcomm_send_dm(s, dlci);
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001255
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 } else {
1257 rfcomm_send_ua(s, 0);
1258
1259 if (s->state == BT_CONNECT)
1260 err = ECONNREFUSED;
1261 else
1262 err = ECONNRESET;
1263
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001264 s = rfcomm_session_close(s, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 }
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001266 return s;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267}
1268
Marcel Holtmannbb23c0a2009-01-15 21:56:48 +01001269void rfcomm_dlc_accept(struct rfcomm_dlc *d)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270{
Marcel Holtmann300b9392006-07-03 10:37:55 +02001271 struct sock *sk = d->session->sock->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001272 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Marcel Holtmann300b9392006-07-03 10:37:55 +02001273
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 BT_DBG("dlc %p", d);
1275
1276 rfcomm_send_ua(d->session, d->dlci);
1277
Johan Hedberge2139b32009-03-26 16:41:56 +02001278 rfcomm_dlc_clear_timer(d);
1279
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 rfcomm_dlc_lock(d);
1281 d->state = BT_CONNECTED;
1282 d->state_change(d, 0);
1283 rfcomm_dlc_unlock(d);
1284
Marcel Holtmann9f2c8a02009-01-15 21:58:40 +01001285 if (d->role_switch)
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001286 hci_conn_switch_role(conn->hcon, 0x00);
Marcel Holtmann300b9392006-07-03 10:37:55 +02001287
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig);
1289}
1290
Marcel Holtmannbb23c0a2009-01-15 21:56:48 +01001291static void rfcomm_check_accept(struct rfcomm_dlc *d)
1292{
Marcel Holtmann9f2c8a02009-01-15 21:58:40 +01001293 if (rfcomm_check_security(d)) {
Marcel Holtmannbb23c0a2009-01-15 21:56:48 +01001294 if (d->defer_setup) {
1295 set_bit(RFCOMM_DEFER_SETUP, &d->flags);
1296 rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
Marcel Holtmann8bf47942009-02-16 02:59:49 +01001297
1298 rfcomm_dlc_lock(d);
1299 d->state = BT_CONNECT2;
1300 d->state_change(d, 0);
1301 rfcomm_dlc_unlock(d);
Marcel Holtmannbb23c0a2009-01-15 21:56:48 +01001302 } else
1303 rfcomm_dlc_accept(d);
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001304 } else {
1305 set_bit(RFCOMM_AUTH_PENDING, &d->flags);
1306 rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
Marcel Holtmannbb23c0a2009-01-15 21:56:48 +01001307 }
1308}
1309
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
1311{
1312 struct rfcomm_dlc *d;
1313 u8 channel;
1314
1315 BT_DBG("session %p state %ld dlci %d", s, s->state, dlci);
1316
1317 if (!dlci) {
1318 rfcomm_send_ua(s, 0);
1319
1320 if (s->state == BT_OPEN) {
1321 s->state = BT_CONNECTED;
1322 rfcomm_process_connect(s);
1323 }
1324 return 0;
1325 }
1326
1327 /* Check if DLC exists */
1328 d = rfcomm_dlc_get(s, dlci);
1329 if (d) {
1330 if (d->state == BT_OPEN) {
1331 /* DLC was previously opened by PN request */
Marcel Holtmannbb23c0a2009-01-15 21:56:48 +01001332 rfcomm_check_accept(d);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 }
1334 return 0;
1335 }
1336
1337 /* Notify socket layer about incoming connection */
1338 channel = __srv_channel(dlci);
1339 if (rfcomm_connect_ind(s, channel, &d)) {
1340 d->dlci = dlci;
1341 d->addr = __addr(s->initiator, dlci);
1342 rfcomm_dlc_link(s, d);
1343
Marcel Holtmannbb23c0a2009-01-15 21:56:48 +01001344 rfcomm_check_accept(d);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 } else {
1346 rfcomm_send_dm(s, dlci);
1347 }
1348
1349 return 0;
1350}
1351
1352static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn)
1353{
1354 struct rfcomm_session *s = d->session;
1355
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001356 BT_DBG("dlc %p state %ld dlci %d mtu %d fc 0x%x credits %d",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 d, d->state, d->dlci, pn->mtu, pn->flow_ctrl, pn->credits);
1358
Marcel Holtmann7c2660b2006-07-03 10:02:51 +02001359 if ((pn->flow_ctrl == 0xf0 && s->cfc != RFCOMM_CFC_DISABLED) ||
1360 pn->flow_ctrl == 0xe0) {
1361 d->cfc = RFCOMM_CFC_ENABLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 d->tx_credits = pn->credits;
1363 } else {
Marcel Holtmann7c2660b2006-07-03 10:02:51 +02001364 d->cfc = RFCOMM_CFC_DISABLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 set_bit(RFCOMM_TX_THROTTLED, &d->flags);
1366 }
1367
Marcel Holtmann7c2660b2006-07-03 10:02:51 +02001368 if (s->cfc == RFCOMM_CFC_UNKNOWN)
1369 s->cfc = d->cfc;
1370
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 d->priority = pn->priority;
1372
Marcel Holtmannb4324b52009-06-07 18:06:51 +02001373 d->mtu = __le16_to_cpu(pn->mtu);
Marcel Holtmann98bcd082006-07-14 11:42:12 +02001374
1375 if (cr && d->mtu > s->mtu)
1376 d->mtu = s->mtu;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377
1378 return 0;
1379}
1380
1381static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb)
1382{
1383 struct rfcomm_pn *pn = (void *) skb->data;
1384 struct rfcomm_dlc *d;
1385 u8 dlci = pn->dlci;
1386
1387 BT_DBG("session %p state %ld dlci %d", s, s->state, dlci);
1388
1389 if (!dlci)
1390 return 0;
1391
1392 d = rfcomm_dlc_get(s, dlci);
1393 if (d) {
1394 if (cr) {
1395 /* PN request */
1396 rfcomm_apply_pn(d, cr, pn);
1397 rfcomm_send_pn(s, 0, d);
1398 } else {
1399 /* PN response */
1400 switch (d->state) {
1401 case BT_CONFIG:
1402 rfcomm_apply_pn(d, cr, pn);
1403
1404 d->state = BT_CONNECT;
1405 rfcomm_send_sabm(s, d->dlci);
1406 break;
1407 }
1408 }
1409 } else {
1410 u8 channel = __srv_channel(dlci);
1411
1412 if (!cr)
1413 return 0;
1414
1415 /* PN request for non existing DLC.
1416 * Assume incoming connection. */
1417 if (rfcomm_connect_ind(s, channel, &d)) {
1418 d->dlci = dlci;
1419 d->addr = __addr(s->initiator, dlci);
1420 rfcomm_dlc_link(s, d);
1421
1422 rfcomm_apply_pn(d, cr, pn);
1423
1424 d->state = BT_OPEN;
1425 rfcomm_send_pn(s, 0, d);
1426 } else {
1427 rfcomm_send_dm(s, dlci);
1428 }
1429 }
1430 return 0;
1431}
1432
1433static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_buff *skb)
1434{
1435 struct rfcomm_rpn *rpn = (void *) skb->data;
1436 u8 dlci = __get_dlci(rpn->dlci);
1437
1438 u8 bit_rate = 0;
1439 u8 data_bits = 0;
1440 u8 stop_bits = 0;
1441 u8 parity = 0;
1442 u8 flow_ctrl = 0;
1443 u8 xon_char = 0;
1444 u8 xoff_char = 0;
1445 u16 rpn_mask = RFCOMM_RPN_PM_ALL;
J. Suter3a5e9032005-08-09 20:28:46 -07001446
1447 BT_DBG("dlci %d cr %d len 0x%x bitr 0x%x line 0x%x flow 0x%x xonc 0x%x xoffc 0x%x pm 0x%x",
1448 dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl,
1449 rpn->xon_char, rpn->xoff_char, rpn->param_mask);
1450
1451 if (!cr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 return 0;
J. Suter3a5e9032005-08-09 20:28:46 -07001453
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 if (len == 1) {
Yuri Kululin08601462010-07-23 13:57:12 +04001455 /* This is a request, return default (according to ETSI TS 07.10) settings */
1456 bit_rate = RFCOMM_RPN_BR_9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 data_bits = RFCOMM_RPN_DATA_8;
1458 stop_bits = RFCOMM_RPN_STOP_1;
1459 parity = RFCOMM_RPN_PARITY_NONE;
1460 flow_ctrl = RFCOMM_RPN_FLOW_NONE;
1461 xon_char = RFCOMM_RPN_XON_CHAR;
1462 xoff_char = RFCOMM_RPN_XOFF_CHAR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 goto rpn_out;
1464 }
J. Suter3a5e9032005-08-09 20:28:46 -07001465
1466 /* Check for sane values, ignore/accept bit_rate, 8 bits, 1 stop bit,
1467 * no parity, no flow control lines, normal XON/XOFF chars */
1468
Al Viroe8db8c92006-11-08 00:28:44 -08001469 if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_BITRATE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 bit_rate = rpn->bit_rate;
Yuri Kululin08601462010-07-23 13:57:12 +04001471 if (bit_rate > RFCOMM_RPN_BR_230400) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 BT_DBG("RPN bit rate mismatch 0x%x", bit_rate);
Yuri Kululin08601462010-07-23 13:57:12 +04001473 bit_rate = RFCOMM_RPN_BR_9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 rpn_mask ^= RFCOMM_RPN_PM_BITRATE;
1475 }
1476 }
J. Suter3a5e9032005-08-09 20:28:46 -07001477
Al Viroe8db8c92006-11-08 00:28:44 -08001478 if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_DATA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 data_bits = __get_rpn_data_bits(rpn->line_settings);
1480 if (data_bits != RFCOMM_RPN_DATA_8) {
1481 BT_DBG("RPN data bits mismatch 0x%x", data_bits);
1482 data_bits = RFCOMM_RPN_DATA_8;
1483 rpn_mask ^= RFCOMM_RPN_PM_DATA;
1484 }
1485 }
J. Suter3a5e9032005-08-09 20:28:46 -07001486
Al Viroe8db8c92006-11-08 00:28:44 -08001487 if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_STOP)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 stop_bits = __get_rpn_stop_bits(rpn->line_settings);
1489 if (stop_bits != RFCOMM_RPN_STOP_1) {
1490 BT_DBG("RPN stop bits mismatch 0x%x", stop_bits);
1491 stop_bits = RFCOMM_RPN_STOP_1;
1492 rpn_mask ^= RFCOMM_RPN_PM_STOP;
1493 }
1494 }
J. Suter3a5e9032005-08-09 20:28:46 -07001495
Al Viroe8db8c92006-11-08 00:28:44 -08001496 if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_PARITY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 parity = __get_rpn_parity(rpn->line_settings);
1498 if (parity != RFCOMM_RPN_PARITY_NONE) {
1499 BT_DBG("RPN parity mismatch 0x%x", parity);
1500 parity = RFCOMM_RPN_PARITY_NONE;
1501 rpn_mask ^= RFCOMM_RPN_PM_PARITY;
1502 }
1503 }
J. Suter3a5e9032005-08-09 20:28:46 -07001504
Al Viroe8db8c92006-11-08 00:28:44 -08001505 if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_FLOW)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506 flow_ctrl = rpn->flow_ctrl;
1507 if (flow_ctrl != RFCOMM_RPN_FLOW_NONE) {
1508 BT_DBG("RPN flow ctrl mismatch 0x%x", flow_ctrl);
1509 flow_ctrl = RFCOMM_RPN_FLOW_NONE;
1510 rpn_mask ^= RFCOMM_RPN_PM_FLOW;
1511 }
1512 }
J. Suter3a5e9032005-08-09 20:28:46 -07001513
Al Viroe8db8c92006-11-08 00:28:44 -08001514 if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_XON)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 xon_char = rpn->xon_char;
1516 if (xon_char != RFCOMM_RPN_XON_CHAR) {
1517 BT_DBG("RPN XON char mismatch 0x%x", xon_char);
1518 xon_char = RFCOMM_RPN_XON_CHAR;
1519 rpn_mask ^= RFCOMM_RPN_PM_XON;
1520 }
1521 }
J. Suter3a5e9032005-08-09 20:28:46 -07001522
Al Viroe8db8c92006-11-08 00:28:44 -08001523 if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_XOFF)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 xoff_char = rpn->xoff_char;
1525 if (xoff_char != RFCOMM_RPN_XOFF_CHAR) {
1526 BT_DBG("RPN XOFF char mismatch 0x%x", xoff_char);
1527 xoff_char = RFCOMM_RPN_XOFF_CHAR;
1528 rpn_mask ^= RFCOMM_RPN_PM_XOFF;
1529 }
1530 }
1531
1532rpn_out:
J. Suter3a5e9032005-08-09 20:28:46 -07001533 rfcomm_send_rpn(s, 0, dlci, bit_rate, data_bits, stop_bits,
1534 parity, flow_ctrl, xon_char, xoff_char, rpn_mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535
1536 return 0;
1537}
1538
1539static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb)
1540{
1541 struct rfcomm_rls *rls = (void *) skb->data;
1542 u8 dlci = __get_dlci(rls->dlci);
1543
1544 BT_DBG("dlci %d cr %d status 0x%x", dlci, cr, rls->status);
J. Suter3a5e9032005-08-09 20:28:46 -07001545
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 if (!cr)
1547 return 0;
1548
J. Suter3a5e9032005-08-09 20:28:46 -07001549 /* We should probably do something with this information here. But
1550 * for now it's sufficient just to reply -- Bluetooth 1.1 says it's
1551 * mandatory to recognise and respond to RLS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552
1553 rfcomm_send_rls(s, 0, dlci, rls->status);
1554
1555 return 0;
1556}
1557
1558static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb)
1559{
1560 struct rfcomm_msc *msc = (void *) skb->data;
1561 struct rfcomm_dlc *d;
1562 u8 dlci = __get_dlci(msc->dlci);
1563
1564 BT_DBG("dlci %d cr %d v24 0x%x", dlci, cr, msc->v24_sig);
1565
1566 d = rfcomm_dlc_get(s, dlci);
J. Suter3a5e9032005-08-09 20:28:46 -07001567 if (!d)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 return 0;
1569
1570 if (cr) {
1571 if (msc->v24_sig & RFCOMM_V24_FC && !d->cfc)
1572 set_bit(RFCOMM_TX_THROTTLED, &d->flags);
1573 else
1574 clear_bit(RFCOMM_TX_THROTTLED, &d->flags);
J. Suter3a5e9032005-08-09 20:28:46 -07001575
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 rfcomm_dlc_lock(d);
Marcel Holtmann8b6b3da2008-07-14 20:13:52 +02001577
1578 d->remote_v24_sig = msc->v24_sig;
1579
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 if (d->modem_status)
1581 d->modem_status(d, msc->v24_sig);
Marcel Holtmann8b6b3da2008-07-14 20:13:52 +02001582
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 rfcomm_dlc_unlock(d);
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001584
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 rfcomm_send_msc(s, 0, dlci, msc->v24_sig);
1586
1587 d->mscex |= RFCOMM_MSCEX_RX;
J. Suter3a5e9032005-08-09 20:28:46 -07001588 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 d->mscex |= RFCOMM_MSCEX_TX;
1590
1591 return 0;
1592}
1593
1594static int rfcomm_recv_mcc(struct rfcomm_session *s, struct sk_buff *skb)
1595{
1596 struct rfcomm_mcc *mcc = (void *) skb->data;
1597 u8 type, cr, len;
1598
1599 cr = __test_cr(mcc->type);
1600 type = __get_mcc_type(mcc->type);
1601 len = __get_mcc_len(mcc->len);
1602
1603 BT_DBG("%p type 0x%x cr %d", s, type, cr);
1604
1605 skb_pull(skb, 2);
1606
1607 switch (type) {
1608 case RFCOMM_PN:
1609 rfcomm_recv_pn(s, cr, skb);
1610 break;
1611
1612 case RFCOMM_RPN:
1613 rfcomm_recv_rpn(s, cr, len, skb);
1614 break;
1615
1616 case RFCOMM_RLS:
1617 rfcomm_recv_rls(s, cr, skb);
1618 break;
1619
1620 case RFCOMM_MSC:
1621 rfcomm_recv_msc(s, cr, skb);
1622 break;
1623
1624 case RFCOMM_FCOFF:
1625 if (cr) {
1626 set_bit(RFCOMM_TX_THROTTLED, &s->flags);
1627 rfcomm_send_fcoff(s, 0);
1628 }
1629 break;
1630
1631 case RFCOMM_FCON:
1632 if (cr) {
1633 clear_bit(RFCOMM_TX_THROTTLED, &s->flags);
1634 rfcomm_send_fcon(s, 0);
1635 }
1636 break;
1637
1638 case RFCOMM_TEST:
1639 if (cr)
1640 rfcomm_send_test(s, 0, skb->data, skb->len);
1641 break;
1642
1643 case RFCOMM_NSC:
1644 break;
1645
1646 default:
1647 BT_ERR("Unknown control type 0x%02x", type);
1648 rfcomm_send_nsc(s, cr, type);
1649 break;
1650 }
1651 return 0;
1652}
1653
1654static int rfcomm_recv_data(struct rfcomm_session *s, u8 dlci, int pf, struct sk_buff *skb)
1655{
1656 struct rfcomm_dlc *d;
1657
1658 BT_DBG("session %p state %ld dlci %d pf %d", s, s->state, dlci, pf);
1659
1660 d = rfcomm_dlc_get(s, dlci);
1661 if (!d) {
1662 rfcomm_send_dm(s, dlci);
1663 goto drop;
1664 }
1665
1666 if (pf && d->cfc) {
1667 u8 credits = *(u8 *) skb->data; skb_pull(skb, 1);
1668
1669 d->tx_credits += credits;
1670 if (d->tx_credits)
1671 clear_bit(RFCOMM_TX_THROTTLED, &d->flags);
1672 }
1673
1674 if (skb->len && d->state == BT_CONNECTED) {
1675 rfcomm_dlc_lock(d);
1676 d->rx_credits--;
1677 d->data_ready(d, skb);
1678 rfcomm_dlc_unlock(d);
1679 return 0;
1680 }
1681
1682drop:
1683 kfree_skb(skb);
1684 return 0;
1685}
1686
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001687static struct rfcomm_session *rfcomm_recv_frame(struct rfcomm_session *s,
1688 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689{
1690 struct rfcomm_hdr *hdr = (void *) skb->data;
1691 u8 type, dlci, fcs;
1692
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001693 if (!s) {
1694 /* no session, so free socket data */
1695 kfree_skb(skb);
1696 return s;
1697 }
1698
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 dlci = __get_dlci(hdr->addr);
1700 type = __get_type(hdr->ctrl);
1701
1702 /* Trim FCS */
1703 skb->len--; skb->tail--;
Arnaldo Carvalho de Melo27a884d2007-04-19 20:29:13 -07001704 fcs = *(u8 *)skb_tail_pointer(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705
1706 if (__check_fcs(skb->data, type, fcs)) {
1707 BT_ERR("bad checksum in packet");
1708 kfree_skb(skb);
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001709 return s;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 }
1711
1712 if (__test_ea(hdr->len))
1713 skb_pull(skb, 3);
1714 else
1715 skb_pull(skb, 4);
1716
1717 switch (type) {
1718 case RFCOMM_SABM:
1719 if (__test_pf(hdr->ctrl))
1720 rfcomm_recv_sabm(s, dlci);
1721 break;
1722
1723 case RFCOMM_DISC:
1724 if (__test_pf(hdr->ctrl))
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001725 s = rfcomm_recv_disc(s, dlci);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 break;
1727
1728 case RFCOMM_UA:
1729 if (__test_pf(hdr->ctrl))
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001730 s = rfcomm_recv_ua(s, dlci);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 break;
1732
1733 case RFCOMM_DM:
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001734 s = rfcomm_recv_dm(s, dlci);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 break;
1736
1737 case RFCOMM_UIH:
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001738 if (dlci) {
1739 rfcomm_recv_data(s, dlci, __test_pf(hdr->ctrl), skb);
1740 return s;
1741 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 rfcomm_recv_mcc(s, skb);
1743 break;
1744
1745 default:
Andrei Emeltchenko5017d8d2010-09-08 16:26:53 +03001746 BT_ERR("Unknown packet type 0x%02x", type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747 break;
1748 }
1749 kfree_skb(skb);
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001750 return s;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751}
1752
1753/* ---- Connection and data processing ---- */
1754
1755static void rfcomm_process_connect(struct rfcomm_session *s)
1756{
1757 struct rfcomm_dlc *d;
1758 struct list_head *p, *n;
1759
1760 BT_DBG("session %p state %ld", s, s->state);
1761
1762 list_for_each_safe(p, n, &s->dlcs) {
1763 d = list_entry(p, struct rfcomm_dlc, list);
1764 if (d->state == BT_CONFIG) {
1765 d->mtu = s->mtu;
Marcel Holtmann9f2c8a02009-01-15 21:58:40 +01001766 if (rfcomm_check_security(d)) {
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001767 rfcomm_send_pn(s, 1, d);
1768 } else {
Marcel Holtmann77db1982008-07-14 20:13:45 +02001769 set_bit(RFCOMM_AUTH_PENDING, &d->flags);
1770 rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01001771 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 }
1773 }
1774}
1775
1776/* Send data queued for the DLC.
1777 * Return number of frames left in the queue.
1778 */
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001779static int rfcomm_process_tx(struct rfcomm_dlc *d)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780{
1781 struct sk_buff *skb;
1782 int err;
1783
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001784 BT_DBG("dlc %p state %ld cfc %d rx_credits %d tx_credits %d",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 d, d->state, d->cfc, d->rx_credits, d->tx_credits);
1786
1787 /* Send pending MSC */
1788 if (test_and_clear_bit(RFCOMM_MSC_PENDING, &d->flags))
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001789 rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790
1791 if (d->cfc) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001792 /* CFC enabled.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793 * Give them some credits */
1794 if (!test_bit(RFCOMM_RX_THROTTLED, &d->flags) &&
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001795 d->rx_credits <= (d->cfc >> 2)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 rfcomm_send_credits(d->session, d->addr, d->cfc - d->rx_credits);
1797 d->rx_credits = d->cfc;
1798 }
1799 } else {
1800 /* CFC disabled.
1801 * Give ourselves some credits */
1802 d->tx_credits = 5;
1803 }
1804
1805 if (test_bit(RFCOMM_TX_THROTTLED, &d->flags))
1806 return skb_queue_len(&d->tx_queue);
1807
1808 while (d->tx_credits && (skb = skb_dequeue(&d->tx_queue))) {
Gustavo F. Padovan54365382011-12-20 16:30:44 -02001809 err = rfcomm_send_frame(d->session, skb->data, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 if (err < 0) {
1811 skb_queue_head(&d->tx_queue, skb);
1812 break;
1813 }
1814 kfree_skb(skb);
1815 d->tx_credits--;
1816 }
1817
1818 if (d->cfc && !d->tx_credits) {
1819 /* We're out of TX credits.
1820 * Set TX_THROTTLED flag to avoid unnesary wakeups by dlc_send. */
1821 set_bit(RFCOMM_TX_THROTTLED, &d->flags);
1822 }
1823
1824 return skb_queue_len(&d->tx_queue);
1825}
1826
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001827static void rfcomm_process_dlcs(struct rfcomm_session *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828{
1829 struct rfcomm_dlc *d;
1830 struct list_head *p, *n;
1831
1832 BT_DBG("session %p state %ld", s, s->state);
1833
1834 list_for_each_safe(p, n, &s->dlcs) {
1835 d = list_entry(p, struct rfcomm_dlc, list);
1836
1837 if (test_bit(RFCOMM_TIMED_OUT, &d->flags)) {
1838 __rfcomm_dlc_close(d, ETIMEDOUT);
1839 continue;
1840 }
1841
Szymon Jancdb544672011-09-26 14:19:47 +02001842 if (test_bit(RFCOMM_ENC_DROP, &d->flags)) {
1843 __rfcomm_dlc_close(d, ECONNREFUSED);
1844 continue;
1845 }
1846
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 if (test_and_clear_bit(RFCOMM_AUTH_ACCEPT, &d->flags)) {
1848 rfcomm_dlc_clear_timer(d);
Marcel Holtmann77db1982008-07-14 20:13:45 +02001849 if (d->out) {
1850 rfcomm_send_pn(s, 1, d);
1851 rfcomm_dlc_set_timer(d, RFCOMM_CONN_TIMEOUT);
Marcel Holtmannbb23c0a2009-01-15 21:56:48 +01001852 } else {
1853 if (d->defer_setup) {
1854 set_bit(RFCOMM_DEFER_SETUP, &d->flags);
1855 rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
Marcel Holtmann8bf47942009-02-16 02:59:49 +01001856
1857 rfcomm_dlc_lock(d);
1858 d->state = BT_CONNECT2;
1859 d->state_change(d, 0);
1860 rfcomm_dlc_unlock(d);
Marcel Holtmannbb23c0a2009-01-15 21:56:48 +01001861 } else
1862 rfcomm_dlc_accept(d);
1863 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 continue;
1865 } else if (test_and_clear_bit(RFCOMM_AUTH_REJECT, &d->flags)) {
1866 rfcomm_dlc_clear_timer(d);
Marcel Holtmann77db1982008-07-14 20:13:45 +02001867 if (!d->out)
1868 rfcomm_send_dm(s, d->dlci);
1869 else
1870 d->state = BT_CLOSED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871 __rfcomm_dlc_close(d, ECONNREFUSED);
1872 continue;
1873 }
1874
Jaikumar Ganesh6e1031a2009-02-02 18:03:57 -08001875 if (test_bit(RFCOMM_SEC_PENDING, &d->flags))
1876 continue;
1877
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878 if (test_bit(RFCOMM_TX_THROTTLED, &s->flags))
1879 continue;
1880
1881 if ((d->state == BT_CONNECTED || d->state == BT_DISCONN) &&
Marcel Holtmann77db1982008-07-14 20:13:45 +02001882 d->mscex == RFCOMM_MSCEX_OK)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 rfcomm_process_tx(d);
1884 }
1885}
1886
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001887static struct rfcomm_session *rfcomm_process_rx(struct rfcomm_session *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888{
1889 struct socket *sock = s->sock;
1890 struct sock *sk = sock->sk;
1891 struct sk_buff *skb;
1892
1893 BT_DBG("session %p state %ld qlen %d", s, s->state, skb_queue_len(&sk->sk_receive_queue));
1894
1895 /* Get data directly from socket receive queue without copying it. */
1896 while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
1897 skb_orphan(skb);
Mat Martineau44935722011-07-22 14:53:58 -07001898 if (!skb_linearize(skb))
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001899 s = rfcomm_recv_frame(s, skb);
Mat Martineau44935722011-07-22 14:53:58 -07001900 else
1901 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 }
1903
Dean Jenkins08c30ac2013-02-28 14:21:56 +00001904 if (s && (sk->sk_state == BT_CLOSED))
1905 s = rfcomm_session_close(s, sk->sk_err);
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001906
1907 return s;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908}
1909
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001910static void rfcomm_accept_connection(struct rfcomm_session *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911{
1912 struct socket *sock = s->sock, *nsock;
1913 int err;
1914
1915 /* Fast check for a new connection.
1916 * Avoids unnesesary socket allocations. */
1917 if (list_empty(&bt_sk(sock->sk)->accept_q))
1918 return;
1919
1920 BT_DBG("session %p", s);
1921
Marcel Holtmann48db9ca2007-05-05 00:36:06 +02001922 err = kernel_accept(sock, &nsock, O_NONBLOCK);
1923 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 return;
1925
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926 /* Set our callbacks */
1927 nsock->sk->sk_data_ready = rfcomm_l2data_ready;
1928 nsock->sk->sk_state_change = rfcomm_l2state_change;
1929
1930 s = rfcomm_session_add(nsock, BT_OPEN);
1931 if (s) {
Marcel Holtmann98bcd082006-07-14 11:42:12 +02001932 /* We should adjust MTU on incoming sessions.
1933 * L2CAP MTU minus UIH header and FCS. */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001934 s->mtu = min(l2cap_pi(nsock->sk)->chan->omtu,
1935 l2cap_pi(nsock->sk)->chan->imtu) - 5;
Marcel Holtmann98bcd082006-07-14 11:42:12 +02001936
Andrei Emeltchenko534c92f2010-10-01 12:05:11 +03001937 rfcomm_schedule();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 } else
1939 sock_release(nsock);
1940}
1941
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001942static struct rfcomm_session *rfcomm_check_connection(struct rfcomm_session *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943{
1944 struct sock *sk = s->sock->sk;
1945
1946 BT_DBG("%p state %ld", s, s->state);
1947
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +02001948 switch (sk->sk_state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949 case BT_CONNECTED:
1950 s->state = BT_CONNECT;
1951
1952 /* We can adjust MTU on outgoing sessions.
1953 * L2CAP MTU minus UIH header and FCS. */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001954 s->mtu = min(l2cap_pi(sk)->chan->omtu, l2cap_pi(sk)->chan->imtu) - 5;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955
1956 rfcomm_send_sabm(s, 0);
1957 break;
1958
1959 case BT_CLOSED:
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001960 s = rfcomm_session_close(s, sk->sk_err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 break;
1962 }
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001963 return s;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964}
1965
Gustavo Padovan6039aa732012-05-23 04:04:18 -03001966static void rfcomm_process_sessions(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967{
1968 struct list_head *p, *n;
1969
1970 rfcomm_lock();
1971
1972 list_for_each_safe(p, n, &session_list) {
1973 struct rfcomm_session *s;
1974 s = list_entry(p, struct rfcomm_session, list);
1975
Luiz Augusto von Dentz9e726b12009-07-15 13:50:58 -03001976 if (test_and_clear_bit(RFCOMM_TIMED_OUT, &s->flags)) {
1977 s->state = BT_DISCONN;
1978 rfcomm_send_disc(s, 0);
1979 continue;
1980 }
1981
Peter Hurley4339c252014-02-09 20:59:11 -05001982 switch (s->state) {
1983 case BT_LISTEN:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984 rfcomm_accept_connection(s);
1985 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987 case BT_BOUND:
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001988 s = rfcomm_check_connection(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 break;
1990
1991 default:
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001992 s = rfcomm_process_rx(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993 break;
1994 }
1995
Dean Jenkins8ff52f72013-02-28 14:21:55 +00001996 if (s)
1997 rfcomm_process_dlcs(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 }
1999
2000 rfcomm_unlock();
2001}
2002
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003static int rfcomm_add_listener(bdaddr_t *ba)
2004{
2005 struct sockaddr_l2 addr;
2006 struct socket *sock;
2007 struct sock *sk;
2008 struct rfcomm_session *s;
2009 int err = 0;
2010
2011 /* Create socket */
2012 err = rfcomm_l2sock_create(&sock);
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002013 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 BT_ERR("Create socket failed %d", err);
2015 return err;
2016 }
2017
2018 /* Bind socket */
2019 bacpy(&addr.l2_bdaddr, ba);
2020 addr.l2_family = AF_BLUETOOTH;
Syam Sidhardhan5bcb8092012-10-10 22:09:29 +05302021 addr.l2_psm = __constant_cpu_to_le16(RFCOMM_PSM);
Marcel Holtmann37e62f52009-02-17 21:49:33 +01002022 addr.l2_cid = 0;
Seung-Woo Kimc507f132013-11-05 16:02:24 +09002023 addr.l2_bdaddr_type = BDADDR_BREDR;
Marcel Holtmann48db9ca2007-05-05 00:36:06 +02002024 err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 if (err < 0) {
2026 BT_ERR("Bind failed %d", err);
2027 goto failed;
2028 }
2029
2030 /* Set L2CAP options */
2031 sk = sock->sk;
2032 lock_sock(sk);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002033 l2cap_pi(sk)->chan->imtu = l2cap_mtu;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 release_sock(sk);
2035
2036 /* Start listening on the socket */
Marcel Holtmann48db9ca2007-05-05 00:36:06 +02002037 err = kernel_listen(sock, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 if (err) {
2039 BT_ERR("Listen failed %d", err);
2040 goto failed;
2041 }
2042
2043 /* Add listening session */
2044 s = rfcomm_session_add(sock, BT_LISTEN);
Wei Yongjun0227c7b2013-03-20 20:23:37 +08002045 if (!s) {
2046 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 goto failed;
Wei Yongjun0227c7b2013-03-20 20:23:37 +08002048 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 return 0;
2051failed:
2052 sock_release(sock);
2053 return err;
2054}
2055
2056static void rfcomm_kill_listener(void)
2057{
2058 struct rfcomm_session *s;
2059 struct list_head *p, *n;
2060
2061 BT_DBG("");
2062
2063 list_for_each_safe(p, n, &session_list) {
2064 s = list_entry(p, struct rfcomm_session, list);
2065 rfcomm_session_del(s);
2066 }
2067}
2068
2069static int rfcomm_run(void *unused)
2070{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071 BT_DBG("");
2072
Marcel Holtmanna524ecc2007-10-20 21:37:20 +02002073 set_user_nice(current, -10);
2074
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075 rfcomm_add_listener(BDADDR_ANY);
2076
Peter Hurleye5842cd2011-07-24 00:10:35 -04002077 while (1) {
Marcel Holtmanna524ecc2007-10-20 21:37:20 +02002078 set_current_state(TASK_INTERRUPTIBLE);
Peter Hurleye5842cd2011-07-24 00:10:35 -04002079
2080 if (kthread_should_stop())
2081 break;
Marcel Holtmanna524ecc2007-10-20 21:37:20 +02002082
2083 /* Process stuff */
Marcel Holtmanna524ecc2007-10-20 21:37:20 +02002084 rfcomm_process_sessions();
Peter Hurleye5842cd2011-07-24 00:10:35 -04002085
2086 schedule();
Marcel Holtmanna524ecc2007-10-20 21:37:20 +02002087 }
Peter Hurleye5842cd2011-07-24 00:10:35 -04002088 __set_current_state(TASK_RUNNING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089
2090 rfcomm_kill_listener();
2091
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092 return 0;
2093}
2094
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01002095static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096{
2097 struct rfcomm_session *s;
2098 struct rfcomm_dlc *d;
2099 struct list_head *p, *n;
2100
2101 BT_DBG("conn %p status 0x%02x encrypt 0x%02x", conn, status, encrypt);
2102
2103 s = rfcomm_session_get(&conn->hdev->bdaddr, &conn->dst);
2104 if (!s)
2105 return;
2106
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 list_for_each_safe(p, n, &s->dlcs) {
2108 d = list_entry(p, struct rfcomm_dlc, list);
2109
Marcel Holtmann8c84b832009-01-16 08:17:51 +01002110 if (test_and_clear_bit(RFCOMM_SEC_PENDING, &d->flags)) {
2111 rfcomm_dlc_clear_timer(d);
2112 if (status || encrypt == 0x00) {
Szymon Jancdb544672011-09-26 14:19:47 +02002113 set_bit(RFCOMM_ENC_DROP, &d->flags);
Marcel Holtmann8c84b832009-01-16 08:17:51 +01002114 continue;
2115 }
2116 }
2117
2118 if (d->state == BT_CONNECTED && !status && encrypt == 0x00) {
2119 if (d->sec_level == BT_SECURITY_MEDIUM) {
2120 set_bit(RFCOMM_SEC_PENDING, &d->flags);
2121 rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
2122 continue;
Marcel Holtmann2c068e02014-01-15 22:37:41 -08002123 } else if (d->sec_level == BT_SECURITY_HIGH ||
2124 d->sec_level == BT_SECURITY_FIPS) {
Szymon Jancdb544672011-09-26 14:19:47 +02002125 set_bit(RFCOMM_ENC_DROP, &d->flags);
Marcel Holtmann8c84b832009-01-16 08:17:51 +01002126 continue;
2127 }
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02002128 }
2129
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130 if (!test_and_clear_bit(RFCOMM_AUTH_PENDING, &d->flags))
2131 continue;
2132
Waldemar Rymarkiewiczb3b1b062011-05-06 09:42:31 +02002133 if (!status && hci_conn_check_secure(conn, d->sec_level))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134 set_bit(RFCOMM_AUTH_ACCEPT, &d->flags);
2135 else
2136 set_bit(RFCOMM_AUTH_REJECT, &d->flags);
2137 }
2138
Andrei Emeltchenko534c92f2010-10-01 12:05:11 +03002139 rfcomm_schedule();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140}
2141
2142static struct hci_cb rfcomm_cb = {
2143 .name = "RFCOMM",
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01002144 .security_cfm = rfcomm_security_cfm
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145};
2146
Marcel Holtmannaef7d972010-03-21 05:27:45 +01002147static int rfcomm_dlc_debugfs_show(struct seq_file *f, void *x)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148{
2149 struct rfcomm_session *s;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150
2151 rfcomm_lock();
2152
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002153 list_for_each_entry(s, &session_list, list) {
Marcel Holtmann24bc10c2013-10-13 09:49:54 -07002154 struct l2cap_chan *chan = l2cap_pi(s->sock->sk)->chan;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002155 struct rfcomm_dlc *d;
2156 list_for_each_entry(d, &s->dlcs, list) {
Andrei Emeltchenkofcb73332012-09-25 12:49:44 +03002157 seq_printf(f, "%pMR %pMR %ld %d %d %d %d\n",
Marcel Holtmann24bc10c2013-10-13 09:49:54 -07002158 &chan->src, &chan->dst,
Andrei Emeltchenkofcb73332012-09-25 12:49:44 +03002159 d->state, d->dlci, d->mtu,
2160 d->rx_credits, d->tx_credits);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 }
2162 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 rfcomm_unlock();
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08002165
Marcel Holtmannaef7d972010-03-21 05:27:45 +01002166 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167}
2168
Marcel Holtmannaef7d972010-03-21 05:27:45 +01002169static int rfcomm_dlc_debugfs_open(struct inode *inode, struct file *file)
2170{
2171 return single_open(file, rfcomm_dlc_debugfs_show, inode->i_private);
2172}
2173
2174static const struct file_operations rfcomm_dlc_debugfs_fops = {
2175 .open = rfcomm_dlc_debugfs_open,
2176 .read = seq_read,
2177 .llseek = seq_lseek,
2178 .release = single_release,
2179};
2180
2181static struct dentry *rfcomm_dlc_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182
2183/* ---- Initialization ---- */
2184static int __init rfcomm_init(void)
2185{
Marcel Holtmann52d18342009-08-22 14:49:36 -07002186 int err;
Dave Youngaf0d3b12009-08-03 04:26:16 +00002187
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 hci_register_cb(&rfcomm_cb);
2189
Marcel Holtmanna524ecc2007-10-20 21:37:20 +02002190 rfcomm_thread = kthread_run(rfcomm_run, NULL, "krfcommd");
2191 if (IS_ERR(rfcomm_thread)) {
Marcel Holtmann52d18342009-08-22 14:49:36 -07002192 err = PTR_ERR(rfcomm_thread);
2193 goto unregister;
Marcel Holtmanna524ecc2007-10-20 21:37:20 +02002194 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195
Marcel Holtmann52d18342009-08-22 14:49:36 -07002196 err = rfcomm_init_ttys();
2197 if (err < 0)
2198 goto stop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199
Marcel Holtmann52d18342009-08-22 14:49:36 -07002200 err = rfcomm_init_sockets();
2201 if (err < 0)
2202 goto cleanup;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08002204 BT_INFO("RFCOMM ver %s", VERSION);
2205
Marcel Holtmann1120e4b2013-10-17 17:24:16 -07002206 if (IS_ERR_OR_NULL(bt_debugfs))
2207 return 0;
2208
2209 rfcomm_dlc_debugfs = debugfs_create_file("rfcomm_dlc", 0444,
2210 bt_debugfs, NULL,
2211 &rfcomm_dlc_debugfs_fops);
2212
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 return 0;
Dave Youngaf0d3b12009-08-03 04:26:16 +00002214
Marcel Holtmann52d18342009-08-22 14:49:36 -07002215cleanup:
Dave Youngaf0d3b12009-08-03 04:26:16 +00002216 rfcomm_cleanup_ttys();
Marcel Holtmann52d18342009-08-22 14:49:36 -07002217
2218stop:
Dave Youngaf0d3b12009-08-03 04:26:16 +00002219 kthread_stop(rfcomm_thread);
Marcel Holtmann52d18342009-08-22 14:49:36 -07002220
2221unregister:
Dave Youngaf0d3b12009-08-03 04:26:16 +00002222 hci_unregister_cb(&rfcomm_cb);
2223
Marcel Holtmann52d18342009-08-22 14:49:36 -07002224 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225}
2226
2227static void __exit rfcomm_exit(void)
2228{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01002229 debugfs_remove(rfcomm_dlc_debugfs);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08002230
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231 hci_unregister_cb(&rfcomm_cb);
2232
Marcel Holtmanna524ecc2007-10-20 21:37:20 +02002233 kthread_stop(rfcomm_thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235 rfcomm_cleanup_ttys();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236
2237 rfcomm_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238}
2239
2240module_init(rfcomm_init);
2241module_exit(rfcomm_exit);
2242
Marcel Holtmann7c2660b2006-07-03 10:02:51 +02002243module_param(disable_cfc, bool, 0644);
2244MODULE_PARM_DESC(disable_cfc, "Disable credit based flow control");
2245
Marcel Holtmann98bcd082006-07-14 11:42:12 +02002246module_param(channel_mtu, int, 0644);
2247MODULE_PARM_DESC(channel_mtu, "Default MTU for the RFCOMM channel");
2248
Marcel Holtmann56f3a402006-02-13 11:39:57 +01002249module_param(l2cap_mtu, uint, 0644);
2250MODULE_PARM_DESC(l2cap_mtu, "Default MTU for the L2CAP connection");
2251
Marcel Holtmanneae38ee2009-10-05 12:23:48 +02002252module_param(l2cap_ertm, bool, 0644);
2253MODULE_PARM_DESC(l2cap_ertm, "Use L2CAP ERTM mode for connection");
2254
Marcel Holtmann63fbd242008-08-18 13:23:53 +02002255MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256MODULE_DESCRIPTION("Bluetooth RFCOMM ver " VERSION);
2257MODULE_VERSION(VERSION);
2258MODULE_LICENSE("GPL");
2259MODULE_ALIAS("bt-proto-3");