blob: 3b1e54c3669f27f2ac68290ce72dbe2d0a681a00 [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
Kun Han Kim15b911f2011-07-08 09:30:28 -07004 Copyright (c) 2011, Code Aurora Forum. All rights reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005
6 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License version 2 as
10 published by the Free Software Foundation;
11
12 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
13 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
15 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090016 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
17 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070019 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090021 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
22 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070023 SOFTWARE IS DISCLAIMED.
24*/
25
26/* Bluetooth SCO sockets. */
27
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/module.h>
29
30#include <linux/types.h>
31#include <linux/errno.h>
32#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/sched.h>
34#include <linux/slab.h>
35#include <linux/poll.h>
36#include <linux/fcntl.h>
37#include <linux/init.h>
38#include <linux/interrupt.h>
39#include <linux/socket.h>
40#include <linux/skbuff.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080041#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010042#include <linux/debugfs.h>
43#include <linux/seq_file.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <linux/list.h>
45#include <net/sock.h>
46
47#include <asm/system.h>
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +020048#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
50#include <net/bluetooth/bluetooth.h>
51#include <net/bluetooth/hci_core.h>
52#include <net/bluetooth/sco.h>
53
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +020054static int disable_esco;
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
Eric Dumazet90ddc4f2005-12-22 12:49:22 -080056static const struct proto_ops sco_sock_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
58static struct bt_sock_list sco_sk_list = {
Robert P. J. Dayd5fb2962008-03-28 16:17:38 -070059 .lock = __RW_LOCK_UNLOCKED(sco_sk_list.lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070060};
61
62static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent);
63static void sco_chan_del(struct sock *sk, int err);
64
65static int sco_conn_del(struct hci_conn *conn, int err);
66
67static void sco_sock_close(struct sock *sk);
68static void sco_sock_kill(struct sock *sk);
69
70/* ---- SCO timers ---- */
71static void sco_sock_timeout(unsigned long arg)
72{
73 struct sock *sk = (struct sock *) arg;
74
75 BT_DBG("sock %p state %d", sk, sk->sk_state);
76
77 bh_lock_sock(sk);
78 sk->sk_err = ETIMEDOUT;
79 sk->sk_state_change(sk);
80 bh_unlock_sock(sk);
81
82 sco_sock_kill(sk);
83 sock_put(sk);
84}
85
86static void sco_sock_set_timer(struct sock *sk, long timeout)
87{
88 BT_DBG("sock %p state %d timeout %ld", sk, sk->sk_state, timeout);
89 sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
90}
91
92static void sco_sock_clear_timer(struct sock *sk)
93{
94 BT_DBG("sock %p state %d", sk, sk->sk_state);
95 sk_stop_timer(sk, &sk->sk_timer);
96}
97
Linus Torvalds1da177e2005-04-16 15:20:36 -070098/* ---- SCO connections ---- */
99static struct sco_conn *sco_conn_add(struct hci_conn *hcon, __u8 status)
100{
101 struct hci_dev *hdev = hcon->hdev;
Marcel Holtmann25ea6db2006-07-06 15:40:09 +0200102 struct sco_conn *conn = hcon->sco_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Marcel Holtmann25ea6db2006-07-06 15:40:09 +0200104 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 return conn;
106
Marcel Holtmann25ea6db2006-07-06 15:40:09 +0200107 conn = kzalloc(sizeof(struct sco_conn), GFP_ATOMIC);
108 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110
111 spin_lock_init(&conn->lock);
112
113 hcon->sco_data = conn;
114 conn->hcon = hcon;
115
116 conn->src = &hdev->bdaddr;
117 conn->dst = &hcon->dst;
118
119 if (hdev->sco_mtu > 0)
120 conn->mtu = hdev->sco_mtu;
121 else
122 conn->mtu = 60;
123
124 BT_DBG("hcon %p conn %p", hcon, conn);
Marcel Holtmann25ea6db2006-07-06 15:40:09 +0200125
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 return conn;
127}
128
129static inline struct sock *sco_chan_get(struct sco_conn *conn)
130{
131 struct sock *sk = NULL;
132 sco_conn_lock(conn);
133 sk = conn->sk;
134 sco_conn_unlock(conn);
135 return sk;
136}
137
138static int sco_conn_del(struct hci_conn *hcon, int err)
139{
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +0200140 struct sco_conn *conn = hcon->sco_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 struct sock *sk;
142
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +0200143 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 return 0;
145
146 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
147
148 /* Kill socket */
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +0200149 sk = sco_chan_get(conn);
150 if (sk) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 bh_lock_sock(sk);
152 sco_sock_clear_timer(sk);
153 sco_chan_del(sk, err);
154 bh_unlock_sock(sk);
155 sco_sock_kill(sk);
156 }
157
158 hcon->sco_data = NULL;
159 kfree(conn);
160 return 0;
161}
162
163static inline int sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent)
164{
165 int err = 0;
166
167 sco_conn_lock(conn);
Gustavo F. Padovanb9dbdbc2010-05-01 16:15:35 -0300168 if (conn->sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 err = -EBUSY;
Gustavo F. Padovanb9dbdbc2010-05-01 16:15:35 -0300170 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 __sco_chan_add(conn, sk, parent);
Gustavo F. Padovanb9dbdbc2010-05-01 16:15:35 -0300172
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173 sco_conn_unlock(conn);
174 return err;
175}
176
Kun Han Kim15b911f2011-07-08 09:30:28 -0700177static int sco_connect(struct sock *sk, __s8 is_wbs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178{
179 bdaddr_t *src = &bt_sk(sk)->src;
180 bdaddr_t *dst = &bt_sk(sk)->dst;
Nick Pellybbcda3b2010-02-11 11:54:28 -0800181 __u16 pkt_type = sco_pi(sk)->pkt_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 struct sco_conn *conn;
183 struct hci_conn *hcon;
184 struct hci_dev *hdev;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200185 int err, type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186
187 BT_DBG("%s -> %s", batostr(src), batostr(dst));
188
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +0200189 hdev = hci_get_route(dst, src);
190 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 return -EHOSTUNREACH;
192
193 hci_dev_lock_bh(hdev);
194
Kun Han Kim15b911f2011-07-08 09:30:28 -0700195 hdev->is_wbs = is_wbs;
196
197 if (lmp_esco_capable(hdev) && !disable_esco) {
Marcel Holtmann7cb127d2008-07-14 20:13:53 +0200198 type = ESCO_LINK;
Kun Han Kim15b911f2011-07-08 09:30:28 -0700199 } else if (is_wbs) {
200 return -ENAVAIL;
201 } else {
Marcel Holtmann7cb127d2008-07-14 20:13:53 +0200202 type = SCO_LINK;
Nick Pellybbcda3b2010-02-11 11:54:28 -0800203 pkt_type &= SCO_ESCO_MASK;
204 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200205
Kun Han Kim15b911f2011-07-08 09:30:28 -0700206 BT_DBG("type: %d, pkt_type: 0x%x", type, pkt_type);
207
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700208 hcon = hci_connect(hdev, type, pkt_type, dst,
209 BT_SECURITY_LOW, HCI_AT_NO_BONDING);
Ville Tervo30e76272011-02-22 16:10:53 -0300210 if (IS_ERR(hcon)) {
211 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300213 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214
Kun Han Kim15b911f2011-07-08 09:30:28 -0700215 if (is_wbs && (hcon->type != ESCO_LINK)) {
216 BT_ERR("WBS [ hcon->type: 0x%x, hcon->pkt_type: 0x%x ]",
217 hcon->type, hcon->pkt_type);
218 err = -EREMOTEIO;
219 goto done;
220 }
221
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 conn = sco_conn_add(hcon, 0);
223 if (!conn) {
224 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300225 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 goto done;
227 }
228
229 /* Update source addr of the socket */
230 bacpy(src, conn->src);
231
232 err = sco_chan_add(conn, sk, NULL);
233 if (err)
234 goto done;
235
236 if (hcon->state == BT_CONNECTED) {
237 sco_sock_clear_timer(sk);
238 sk->sk_state = BT_CONNECTED;
239 } else {
240 sk->sk_state = BT_CONNECT;
241 sco_sock_set_timer(sk, sk->sk_sndtimeo);
242 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200243
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244done:
245 hci_dev_unlock_bh(hdev);
246 hci_dev_put(hdev);
247 return err;
248}
249
250static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len)
251{
252 struct sco_conn *conn = sco_pi(sk)->conn;
253 struct sk_buff *skb;
254 int err, count;
255
256 /* Check outgoing MTU */
257 if (len > conn->mtu)
258 return -EINVAL;
259
260 BT_DBG("sk %p len %d", sk, len);
261
262 count = min_t(unsigned int, conn->mtu, len);
Gustavo F. Padovanb9dbdbc2010-05-01 16:15:35 -0300263 skb = bt_skb_send_alloc(sk, count,
264 msg->msg_flags & MSG_DONTWAIT, &err);
265 if (!skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 return err;
267
268 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) {
Gustavo F. Padovanb9dbdbc2010-05-01 16:15:35 -0300269 kfree_skb(skb);
270 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 }
272
Gustavo F. Padovan0d861d82010-05-01 16:15:35 -0300273 hci_send_sco(conn->hcon, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274
275 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276}
277
278static inline void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb)
279{
280 struct sock *sk = sco_chan_get(conn);
281
282 if (!sk)
283 goto drop;
284
285 BT_DBG("sk %p len %d", sk, skb->len);
286
287 if (sk->sk_state != BT_CONNECTED)
288 goto drop;
289
290 if (!sock_queue_rcv_skb(sk, skb))
291 return;
292
293drop:
294 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295}
296
297/* -------- Socket interface ---------- */
298static struct sock *__sco_get_sock_by_addr(bdaddr_t *ba)
299{
300 struct sock *sk;
301 struct hlist_node *node;
302
303 sk_for_each(sk, node, &sco_sk_list.head)
304 if (!bacmp(&bt_sk(sk)->src, ba))
305 goto found;
306 sk = NULL;
307found:
308 return sk;
309}
310
311/* Find socket listening on source bdaddr.
312 * Returns closest match.
313 */
314static struct sock *sco_get_sock_listen(bdaddr_t *src)
315{
316 struct sock *sk = NULL, *sk1 = NULL;
317 struct hlist_node *node;
318
319 read_lock(&sco_sk_list.lock);
320
321 sk_for_each(sk, node, &sco_sk_list.head) {
322 if (sk->sk_state != BT_LISTEN)
323 continue;
324
325 /* Exact match. */
326 if (!bacmp(&bt_sk(sk)->src, src))
327 break;
328
329 /* Closest match */
330 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
331 sk1 = sk;
332 }
333
334 read_unlock(&sco_sk_list.lock);
335
336 return node ? sk : sk1;
337}
338
339static void sco_sock_destruct(struct sock *sk)
340{
341 BT_DBG("sk %p", sk);
342
343 skb_queue_purge(&sk->sk_receive_queue);
344 skb_queue_purge(&sk->sk_write_queue);
345}
346
347static void sco_sock_cleanup_listen(struct sock *parent)
348{
349 struct sock *sk;
350
351 BT_DBG("parent %p", parent);
352
353 /* Close not yet accepted channels */
354 while ((sk = bt_accept_dequeue(parent, NULL))) {
355 sco_sock_close(sk);
356 sco_sock_kill(sk);
357 }
358
359 parent->sk_state = BT_CLOSED;
360 sock_set_flag(parent, SOCK_ZAPPED);
361}
362
363/* Kill socket (only if zapped and orphan)
364 * Must be called on unlocked socket.
365 */
366static void sco_sock_kill(struct sock *sk)
367{
368 if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
369 return;
370
371 BT_DBG("sk %p state %d", sk, sk->sk_state);
372
373 /* Kill poor orphan */
374 bt_sock_unlink(&sco_sk_list, sk);
375 sock_set_flag(sk, SOCK_DEAD);
376 sock_put(sk);
377}
378
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +0200379static void __sco_sock_close(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380{
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +0200381 BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382
383 switch (sk->sk_state) {
384 case BT_LISTEN:
385 sco_sock_cleanup_listen(sk);
386 break;
387
388 case BT_CONNECTED:
389 case BT_CONFIG:
390 case BT_CONNECT:
391 case BT_DISCONN:
392 sco_chan_del(sk, ECONNRESET);
393 break;
394
395 default:
396 sock_set_flag(sk, SOCK_ZAPPED);
397 break;
Stephen Hemminger3ff50b72007-04-20 17:09:22 -0700398 }
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +0200399}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +0200401/* Must be called on unlocked socket. */
402static void sco_sock_close(struct sock *sk)
403{
404 sco_sock_clear_timer(sk);
405 lock_sock(sk);
406 __sco_sock_close(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 sco_sock_kill(sk);
409}
410
411static void sco_sock_init(struct sock *sk, struct sock *parent)
412{
413 BT_DBG("sk %p", sk);
414
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900415 if (parent)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 sk->sk_type = parent->sk_type;
417}
418
419static struct proto sco_proto = {
420 .name = "SCO",
421 .owner = THIS_MODULE,
422 .obj_size = sizeof(struct sco_pinfo)
423};
424
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700425static struct sock *sco_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426{
427 struct sock *sk;
428
Pavel Emelyanov6257ff22007-11-01 00:39:31 -0700429 sk = sk_alloc(net, PF_BLUETOOTH, prio, &sco_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 if (!sk)
431 return NULL;
432
433 sock_init_data(sock, sk);
434 INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
435
436 sk->sk_destruct = sco_sock_destruct;
437 sk->sk_sndtimeo = SCO_CONN_TIMEOUT;
438
439 sock_reset_flag(sk, SOCK_ZAPPED);
440
441 sk->sk_protocol = proto;
442 sk->sk_state = BT_OPEN;
443
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800444 setup_timer(&sk->sk_timer, sco_sock_timeout, (unsigned long)sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445
446 bt_sock_link(&sco_sk_list, sk);
447 return sk;
448}
449
Eric Paris3f378b62009-11-05 22:18:14 -0800450static int sco_sock_create(struct net *net, struct socket *sock, int protocol,
451 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452{
453 struct sock *sk;
454
455 BT_DBG("sock %p", sock);
456
457 sock->state = SS_UNCONNECTED;
458
459 if (sock->type != SOCK_SEQPACKET)
460 return -ESOCKTNOSUPPORT;
461
462 sock->ops = &sco_sock_ops;
463
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700464 sk = sco_sock_alloc(net, sock, protocol, GFP_ATOMIC);
Marcel Holtmann74da6262006-10-15 17:31:14 +0200465 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 return -ENOMEM;
467
468 sco_sock_init(sk, NULL);
469 return 0;
470}
471
Nick Pellybbcda3b2010-02-11 11:54:28 -0800472static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473{
Nick Pellybbcda3b2010-02-11 11:54:28 -0800474 struct sockaddr_sco sa;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 struct sock *sk = sock->sk;
Nick Pellybbcda3b2010-02-11 11:54:28 -0800476 bdaddr_t *src = &sa.sco_bdaddr;
477 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
Nick Pellybbcda3b2010-02-11 11:54:28 -0800479 BT_DBG("sk %p %s", sk, batostr(&sa.sco_bdaddr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480
481 if (!addr || addr->sa_family != AF_BLUETOOTH)
482 return -EINVAL;
483
Nick Pellybbcda3b2010-02-11 11:54:28 -0800484 memset(&sa, 0, sizeof(sa));
485 len = min_t(unsigned int, sizeof(sa), alen);
486 memcpy(&sa, addr, len);
487
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 lock_sock(sk);
489
490 if (sk->sk_state != BT_OPEN) {
491 err = -EBADFD;
492 goto done;
493 }
494
495 write_lock_bh(&sco_sk_list.lock);
496
497 if (bacmp(src, BDADDR_ANY) && __sco_get_sock_by_addr(src)) {
498 err = -EADDRINUSE;
499 } else {
500 /* Save source address */
Nick Pellybbcda3b2010-02-11 11:54:28 -0800501 bacpy(&bt_sk(sk)->src, &sa.sco_bdaddr);
502 sco_pi(sk)->pkt_type = sa.sco_pkt_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 sk->sk_state = BT_BOUND;
504 }
505
506 write_unlock_bh(&sco_sk_list.lock);
507
508done:
509 release_sock(sk);
510 return err;
511}
512
513static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
514{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 struct sock *sk = sock->sk;
Nick Pellybbcda3b2010-02-11 11:54:28 -0800516 struct sockaddr_sco sa;
517 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518
519 BT_DBG("sk %p", sk);
520
Nick Pellybbcda3b2010-02-11 11:54:28 -0800521 if (!addr || addr->sa_family != AF_BLUETOOTH)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 return -EINVAL;
523
Nick Pellybbcda3b2010-02-11 11:54:28 -0800524 memset(&sa, 0, sizeof(sa));
525 len = min_t(unsigned int, sizeof(sa), alen);
526 memcpy(&sa, addr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527
528 lock_sock(sk);
529
Nick Pellybbcda3b2010-02-11 11:54:28 -0800530 if (sk->sk_type != SOCK_SEQPACKET) {
531 err = -EINVAL;
532 goto done;
533 }
534
535 if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) {
536 err = -EBADFD;
537 goto done;
538 }
539
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 /* Set destination address and psm */
Nick Pellybbcda3b2010-02-11 11:54:28 -0800541 bacpy(&bt_sk(sk)->dst, &sa.sco_bdaddr);
542 sco_pi(sk)->pkt_type = sa.sco_pkt_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543
Kun Han Kim15b911f2011-07-08 09:30:28 -0700544 err = sco_connect(sk, sa.is_wbs);
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +0200545 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 goto done;
547
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900548 err = bt_sock_wait_state(sk, BT_CONNECTED,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 sock_sndtimeo(sk, flags & O_NONBLOCK));
550
551done:
552 release_sock(sk);
553 return err;
554}
555
556static int sco_sock_listen(struct socket *sock, int backlog)
557{
558 struct sock *sk = sock->sk;
559 int err = 0;
560
561 BT_DBG("sk %p backlog %d", sk, backlog);
562
563 lock_sock(sk);
564
565 if (sk->sk_state != BT_BOUND || sock->type != SOCK_SEQPACKET) {
566 err = -EBADFD;
567 goto done;
568 }
569
570 sk->sk_max_ack_backlog = backlog;
571 sk->sk_ack_backlog = 0;
572 sk->sk_state = BT_LISTEN;
573
574done:
575 release_sock(sk);
576 return err;
577}
578
579static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flags)
580{
581 DECLARE_WAITQUEUE(wait, current);
582 struct sock *sk = sock->sk, *ch;
583 long timeo;
584 int err = 0;
585
586 lock_sock(sk);
587
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700588 if (sk->sk_state != BT_LISTEN) {
589 err = -EBADFD;
590 goto done;
591 }
592
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593 timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
594
595 BT_DBG("sk %p timeo %ld", sk, timeo);
596
597 /* Wait for an incoming connection. (wake-one). */
Eric Dumazetaa395142010-04-20 13:03:51 +0000598 add_wait_queue_exclusive(sk_sleep(sk), &wait);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700599 while (!(ch = bt_accept_dequeue(sk, newsock))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 set_current_state(TASK_INTERRUPTIBLE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700601 if (!timeo) {
602 err = -EAGAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 break;
604 }
605
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700606 release_sock(sk);
607 timeo = schedule_timeout(timeo);
608 lock_sock(sk);
Peter Hurleyd7581072011-07-24 00:11:01 -0400609
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700610 if (sk->sk_state != BT_LISTEN) {
611 err = -EBADFD;
Peter Hurleyd7581072011-07-24 00:11:01 -0400612 break;
613 }
614
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 if (signal_pending(current)) {
616 err = sock_intr_errno(timeo);
617 break;
618 }
619 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700620 set_current_state(TASK_RUNNING);
Eric Dumazetaa395142010-04-20 13:03:51 +0000621 remove_wait_queue(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622
623 if (err)
624 goto done;
625
626 newsock->state = SS_CONNECTED;
627
628 BT_DBG("new socket %p", ch);
629
630done:
631 release_sock(sk);
632 return err;
633}
634
635static int sco_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
636{
637 struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
638 struct sock *sk = sock->sk;
639
640 BT_DBG("sock %p, sk %p", sock, sk);
641
642 addr->sa_family = AF_BLUETOOTH;
643 *len = sizeof(struct sockaddr_sco);
644
645 if (peer)
646 bacpy(&sa->sco_bdaddr, &bt_sk(sk)->dst);
647 else
648 bacpy(&sa->sco_bdaddr, &bt_sk(sk)->src);
Nick Pellybbcda3b2010-02-11 11:54:28 -0800649 sa->sco_pkt_type = sco_pi(sk)->pkt_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650
651 return 0;
652}
653
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900654static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 struct msghdr *msg, size_t len)
656{
657 struct sock *sk = sock->sk;
Gustavo F. Padovanb9dbdbc2010-05-01 16:15:35 -0300658 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659
660 BT_DBG("sock %p, sk %p", sock, sk);
661
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -0800662 err = sock_error(sk);
663 if (err)
664 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665
666 if (msg->msg_flags & MSG_OOB)
667 return -EOPNOTSUPP;
668
669 lock_sock(sk);
670
671 if (sk->sk_state == BT_CONNECTED)
672 err = sco_send_frame(sk, msg, len);
673 else
674 err = -ENOTCONN;
675
676 release_sock(sk);
677 return err;
678}
679
David S. Millerb7058842009-09-30 16:12:20 -0700680static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681{
682 struct sock *sk = sock->sk;
683 int err = 0;
684
685 BT_DBG("sk %p", sk);
686
687 lock_sock(sk);
688
689 switch (optname) {
690 default:
691 err = -ENOPROTOOPT;
692 break;
693 }
694
695 release_sock(sk);
696 return err;
697}
698
Marcel Holtmannd58daf42009-01-15 21:52:14 +0100699static int sco_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700{
701 struct sock *sk = sock->sk;
702 struct sco_options opts;
703 struct sco_conninfo cinfo;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900704 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705
706 BT_DBG("sk %p", sk);
707
708 if (get_user(len, optlen))
709 return -EFAULT;
710
711 lock_sock(sk);
712
713 switch (optname) {
714 case SCO_OPTIONS:
715 if (sk->sk_state != BT_CONNECTED) {
716 err = -ENOTCONN;
717 break;
718 }
719
720 opts.mtu = sco_pi(sk)->conn->mtu;
721
722 BT_DBG("mtu %d", opts.mtu);
723
724 len = min_t(unsigned int, len, sizeof(opts));
725 if (copy_to_user(optval, (char *)&opts, len))
726 err = -EFAULT;
727
728 break;
729
730 case SCO_CONNINFO:
731 if (sk->sk_state != BT_CONNECTED) {
732 err = -ENOTCONN;
733 break;
734 }
735
Vasiliy Kulikovc4c896e2011-02-14 13:54:26 +0300736 memset(&cinfo, 0, sizeof(cinfo));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
738 memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
739
740 len = min_t(unsigned int, len, sizeof(cinfo));
741 if (copy_to_user(optval, (char *)&cinfo, len))
742 err = -EFAULT;
743
744 break;
745
746 default:
747 err = -ENOPROTOOPT;
748 break;
749 }
750
751 release_sock(sk);
752 return err;
753}
754
Marcel Holtmannd58daf42009-01-15 21:52:14 +0100755static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
756{
757 struct sock *sk = sock->sk;
758 int len, err = 0;
759
760 BT_DBG("sk %p", sk);
761
762 if (level == SOL_SCO)
763 return sco_sock_getsockopt_old(sock, optname, optval, optlen);
764
765 if (get_user(len, optlen))
766 return -EFAULT;
767
768 lock_sock(sk);
769
770 switch (optname) {
771 default:
772 err = -ENOPROTOOPT;
773 break;
774 }
775
776 release_sock(sk);
777 return err;
778}
779
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +0200780static int sco_sock_shutdown(struct socket *sock, int how)
781{
782 struct sock *sk = sock->sk;
783 int err = 0;
784
785 BT_DBG("sock %p, sk %p", sock, sk);
786
787 if (!sk)
788 return 0;
789
790 lock_sock(sk);
791 if (!sk->sk_shutdown) {
792 sk->sk_shutdown = SHUTDOWN_MASK;
793 sco_sock_clear_timer(sk);
794 __sco_sock_close(sk);
795
796 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
797 err = bt_sock_wait_state(sk, BT_CLOSED,
798 sk->sk_lingertime);
799 }
800 release_sock(sk);
801 return err;
802}
803
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804static int sco_sock_release(struct socket *sock)
805{
806 struct sock *sk = sock->sk;
807 int err = 0;
808
809 BT_DBG("sock %p, sk %p", sock, sk);
810
811 if (!sk)
812 return 0;
813
814 sco_sock_close(sk);
815
816 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) {
817 lock_sock(sk);
818 err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
819 release_sock(sk);
820 }
821
822 sock_orphan(sk);
823 sco_sock_kill(sk);
824 return err;
825}
826
827static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent)
828{
829 BT_DBG("conn %p", conn);
830
831 sco_pi(sk)->conn = conn;
832 conn->sk = sk;
833
834 if (parent)
835 bt_accept_enqueue(parent, sk);
836}
837
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900838/* Delete channel.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 * Must be called on the locked socket. */
840static void sco_chan_del(struct sock *sk, int err)
841{
842 struct sco_conn *conn;
843
844 conn = sco_pi(sk)->conn;
845
846 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
847
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900848 if (conn) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 sco_conn_lock(conn);
850 conn->sk = NULL;
851 sco_pi(sk)->conn = NULL;
852 sco_conn_unlock(conn);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700853 hci_conn_put(conn->hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 }
855
856 sk->sk_state = BT_CLOSED;
857 sk->sk_err = err;
858 sk->sk_state_change(sk);
859
860 sock_set_flag(sk, SOCK_ZAPPED);
861}
862
863static void sco_conn_ready(struct sco_conn *conn)
864{
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +0200865 struct sock *parent;
866 struct sock *sk = conn->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867
868 BT_DBG("conn %p", conn);
869
870 sco_conn_lock(conn);
871
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +0200872 if (sk) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 sco_sock_clear_timer(sk);
874 bh_lock_sock(sk);
875 sk->sk_state = BT_CONNECTED;
876 sk->sk_state_change(sk);
877 bh_unlock_sock(sk);
878 } else {
879 parent = sco_get_sock_listen(conn->src);
880 if (!parent)
881 goto done;
882
883 bh_lock_sock(parent);
884
Gustavo F. Padovanb9dbdbc2010-05-01 16:15:35 -0300885 sk = sco_sock_alloc(sock_net(parent), NULL,
886 BTPROTO_SCO, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 if (!sk) {
888 bh_unlock_sock(parent);
889 goto done;
890 }
891
892 sco_sock_init(sk, parent);
893
894 bacpy(&bt_sk(sk)->src, conn->src);
895 bacpy(&bt_sk(sk)->dst, conn->dst);
896
897 hci_conn_hold(conn->hcon);
898 __sco_chan_add(conn, sk, parent);
899
900 sk->sk_state = BT_CONNECTED;
901
902 /* Wake up parent */
903 parent->sk_data_ready(parent, 1);
904
905 bh_unlock_sock(parent);
906 }
907
908done:
909 sco_conn_unlock(conn);
910}
911
912/* ----- SCO interface with lower layer (HCI) ----- */
913static int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
914{
Marcel Holtmann71aeeaa2009-01-15 21:57:02 +0100915 register struct sock *sk;
916 struct hlist_node *node;
917 int lm = 0;
918
919 if (type != SCO_LINK && type != ESCO_LINK)
Gustavo F. Padovanc89ad732010-11-01 19:08:50 +0000920 return -EINVAL;
Marcel Holtmann71aeeaa2009-01-15 21:57:02 +0100921
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
923
Marcel Holtmann71aeeaa2009-01-15 21:57:02 +0100924 /* Find listening sockets */
925 read_lock(&sco_sk_list.lock);
926 sk_for_each(sk, node, &sco_sk_list.head) {
927 if (sk->sk_state != BT_LISTEN)
928 continue;
929
930 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr) ||
931 !bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
932 lm |= HCI_LM_ACCEPT;
933 break;
934 }
935 }
936 read_unlock(&sco_sk_list.lock);
937
938 return lm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939}
940
941static int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
942{
943 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
944
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200945 if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
Gustavo F. Padovanc89ad732010-11-01 19:08:50 +0000946 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947
948 if (!status) {
949 struct sco_conn *conn;
950
951 conn = sco_conn_add(hcon, status);
952 if (conn)
953 sco_conn_ready(conn);
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900954 } else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700955 sco_conn_del(hcon, bt_err(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956
957 return 0;
958}
959
Marcel Holtmann2950f212009-02-12 14:02:50 +0100960static int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961{
962 BT_DBG("hcon %p reason %d", hcon, reason);
963
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200964 if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
Gustavo F. Padovanc89ad732010-11-01 19:08:50 +0000965 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700967 sco_conn_del(hcon, bt_err(reason));
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200968
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 return 0;
970}
971
972static int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb)
973{
974 struct sco_conn *conn = hcon->sco_data;
975
976 if (!conn)
977 goto drop;
978
979 BT_DBG("conn %p len %d", conn, skb->len);
980
981 if (skb->len) {
982 sco_recv_frame(conn, skb);
983 return 0;
984 }
985
986drop:
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900987 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 return 0;
989}
990
Marcel Holtmannaef7d972010-03-21 05:27:45 +0100991static int sco_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992{
993 struct sock *sk;
994 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995
996 read_lock_bh(&sco_sk_list.lock);
997
Marcel Holtmannbe9d1222005-11-08 09:57:38 -0800998 sk_for_each(sk, node, &sco_sk_list.head) {
Marcel Holtmannaef7d972010-03-21 05:27:45 +0100999 seq_printf(f, "%s %s %d\n", batostr(&bt_sk(sk)->src),
1000 batostr(&bt_sk(sk)->dst), sk->sk_state);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08001001 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 read_unlock_bh(&sco_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08001004
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001005 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006}
1007
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001008static int sco_debugfs_open(struct inode *inode, struct file *file)
1009{
1010 return single_open(file, sco_debugfs_show, inode->i_private);
1011}
1012
1013static const struct file_operations sco_debugfs_fops = {
1014 .open = sco_debugfs_open,
1015 .read = seq_read,
1016 .llseek = seq_lseek,
1017 .release = single_release,
1018};
1019
1020static struct dentry *sco_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021
Eric Dumazet90ddc4f2005-12-22 12:49:22 -08001022static const struct proto_ops sco_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 .family = PF_BLUETOOTH,
1024 .owner = THIS_MODULE,
1025 .release = sco_sock_release,
1026 .bind = sco_sock_bind,
1027 .connect = sco_sock_connect,
1028 .listen = sco_sock_listen,
1029 .accept = sco_sock_accept,
1030 .getname = sco_sock_getname,
1031 .sendmsg = sco_sock_sendmsg,
1032 .recvmsg = bt_sock_recvmsg,
1033 .poll = bt_sock_poll,
Marcel Holtmann3241ad82008-07-14 20:13:50 +02001034 .ioctl = bt_sock_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 .mmap = sock_no_mmap,
1036 .socketpair = sock_no_socketpair,
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +02001037 .shutdown = sco_sock_shutdown,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 .setsockopt = sco_sock_setsockopt,
1039 .getsockopt = sco_sock_getsockopt
1040};
1041
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +00001042static const struct net_proto_family sco_sock_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 .family = PF_BLUETOOTH,
1044 .owner = THIS_MODULE,
1045 .create = sco_sock_create,
1046};
1047
1048static struct hci_proto sco_hci_proto = {
1049 .name = "SCO",
1050 .id = HCI_PROTO_SCO,
1051 .connect_ind = sco_connect_ind,
1052 .connect_cfm = sco_connect_cfm,
Marcel Holtmann2950f212009-02-12 14:02:50 +01001053 .disconn_cfm = sco_disconn_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 .recv_scodata = sco_recv_scodata
1055};
1056
Gustavo F. Padovan64274512011-02-07 20:08:52 -02001057int __init sco_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058{
1059 int err;
1060
1061 err = proto_register(&sco_proto, 0);
1062 if (err < 0)
1063 return err;
1064
1065 err = bt_sock_register(BTPROTO_SCO, &sco_sock_family_ops);
1066 if (err < 0) {
1067 BT_ERR("SCO socket registration failed");
1068 goto error;
1069 }
1070
1071 err = hci_register_proto(&sco_hci_proto);
1072 if (err < 0) {
1073 BT_ERR("SCO protocol registration failed");
1074 bt_sock_unregister(BTPROTO_SCO);
1075 goto error;
1076 }
1077
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001078 if (bt_debugfs) {
1079 sco_debugfs = debugfs_create_file("sco", 0444,
1080 bt_debugfs, NULL, &sco_debugfs_fops);
1081 if (!sco_debugfs)
1082 BT_ERR("Failed to create SCO debug file");
1083 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 BT_INFO("SCO socket layer initialized");
1086
1087 return 0;
1088
1089error:
1090 proto_unregister(&sco_proto);
1091 return err;
1092}
1093
Gustavo F. Padovan64274512011-02-07 20:08:52 -02001094void __exit sco_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001096 debugfs_remove(sco_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097
1098 if (bt_sock_unregister(BTPROTO_SCO) < 0)
1099 BT_ERR("SCO socket unregistration failed");
1100
1101 if (hci_unregister_proto(&sco_hci_proto) < 0)
1102 BT_ERR("SCO protocol unregistration failed");
1103
1104 proto_unregister(&sco_proto);
1105}
1106
Marcel Holtmann7cb127d2008-07-14 20:13:53 +02001107module_param(disable_esco, bool, 0644);
1108MODULE_PARM_DESC(disable_esco, "Disable eSCO connection creation");