blob: f090a77cf3c46ca2952a46bd12e3fbfdf0cf803f [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
Steve Mucklef132c6c2012-06-06 18:30:57 -070028#include <linux/interrupt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30
31#include <linux/types.h>
32#include <linux/errno.h>
33#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/sched.h>
35#include <linux/slab.h>
36#include <linux/poll.h>
37#include <linux/fcntl.h>
38#include <linux/init.h>
39#include <linux/interrupt.h>
40#include <linux/socket.h>
41#include <linux/skbuff.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080042#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010043#include <linux/debugfs.h>
44#include <linux/seq_file.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <linux/list.h>
46#include <net/sock.h>
47
48#include <asm/system.h>
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +020049#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51#include <net/bluetooth/bluetooth.h>
52#include <net/bluetooth/hci_core.h>
53#include <net/bluetooth/sco.h>
54
Rusty Russelleb939922011-12-19 14:08:01 +000055static bool disable_esco;
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
Eric Dumazet90ddc4f2005-12-22 12:49:22 -080057static const struct proto_ops sco_sock_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
59static struct bt_sock_list sco_sk_list = {
Robert P. J. Dayd5fb2962008-03-28 16:17:38 -070060 .lock = __RW_LOCK_UNLOCKED(sco_sk_list.lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070061};
62
63static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent);
64static void sco_chan_del(struct sock *sk, int err);
65
Mat Martineau3b9239a2012-02-16 11:54:30 -080066static int sco_conn_del(struct hci_conn *conn, int err, u8 is_process);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
68static void sco_sock_close(struct sock *sk);
69static void sco_sock_kill(struct sock *sk);
70
71/* ---- SCO timers ---- */
72static void sco_sock_timeout(unsigned long arg)
73{
74 struct sock *sk = (struct sock *) arg;
75
76 BT_DBG("sock %p state %d", sk, sk->sk_state);
77
78 bh_lock_sock(sk);
79 sk->sk_err = ETIMEDOUT;
80 sk->sk_state_change(sk);
81 bh_unlock_sock(sk);
82
83 sco_sock_kill(sk);
84 sock_put(sk);
85}
86
87static void sco_sock_set_timer(struct sock *sk, long timeout)
88{
89 BT_DBG("sock %p state %d timeout %ld", sk, sk->sk_state, timeout);
90 sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
91}
92
93static void sco_sock_clear_timer(struct sock *sk)
94{
95 BT_DBG("sock %p state %d", sk, sk->sk_state);
96 sk_stop_timer(sk, &sk->sk_timer);
97}
98
Linus Torvalds1da177e2005-04-16 15:20:36 -070099/* ---- SCO connections ---- */
100static struct sco_conn *sco_conn_add(struct hci_conn *hcon, __u8 status)
101{
102 struct hci_dev *hdev = hcon->hdev;
Marcel Holtmann25ea6db2006-07-06 15:40:09 +0200103 struct sco_conn *conn = hcon->sco_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
Marcel Holtmann25ea6db2006-07-06 15:40:09 +0200105 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 return conn;
107
Marcel Holtmann25ea6db2006-07-06 15:40:09 +0200108 conn = kzalloc(sizeof(struct sco_conn), GFP_ATOMIC);
109 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111
112 spin_lock_init(&conn->lock);
113
114 hcon->sco_data = conn;
115 conn->hcon = hcon;
116
117 conn->src = &hdev->bdaddr;
118 conn->dst = &hcon->dst;
119
120 if (hdev->sco_mtu > 0)
121 conn->mtu = hdev->sco_mtu;
122 else
123 conn->mtu = 60;
124
125 BT_DBG("hcon %p conn %p", hcon, conn);
Marcel Holtmann25ea6db2006-07-06 15:40:09 +0200126
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 return conn;
128}
129
130static inline struct sock *sco_chan_get(struct sco_conn *conn)
131{
132 struct sock *sk = NULL;
133 sco_conn_lock(conn);
134 sk = conn->sk;
135 sco_conn_unlock(conn);
136 return sk;
137}
138
Mat Martineau3b9239a2012-02-16 11:54:30 -0800139static int sco_conn_del(struct hci_conn *hcon, int err, u8 is_process)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140{
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +0200141 struct sco_conn *conn = hcon->sco_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 struct sock *sk;
143
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +0200144 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 return 0;
146
147 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
148
149 /* Kill socket */
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +0200150 sk = sco_chan_get(conn);
151 if (sk) {
Mat Martineau3b9239a2012-02-16 11:54:30 -0800152 if (is_process)
153 lock_sock(sk);
154 else
155 bh_lock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 sco_sock_clear_timer(sk);
157 sco_chan_del(sk, err);
Mat Martineau3b9239a2012-02-16 11:54:30 -0800158 if (is_process)
159 release_sock(sk);
160 else
161 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 sco_sock_kill(sk);
163 }
164
165 hcon->sco_data = NULL;
166 kfree(conn);
167 return 0;
168}
169
170static inline int sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent)
171{
172 int err = 0;
173
174 sco_conn_lock(conn);
Gustavo F. Padovanb9dbdbc2010-05-01 16:15:35 -0300175 if (conn->sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 err = -EBUSY;
Gustavo F. Padovanb9dbdbc2010-05-01 16:15:35 -0300177 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 __sco_chan_add(conn, sk, parent);
Gustavo F. Padovanb9dbdbc2010-05-01 16:15:35 -0300179
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 sco_conn_unlock(conn);
181 return err;
182}
183
Kun Han Kim15b911f2011-07-08 09:30:28 -0700184static int sco_connect(struct sock *sk, __s8 is_wbs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185{
186 bdaddr_t *src = &bt_sk(sk)->src;
187 bdaddr_t *dst = &bt_sk(sk)->dst;
Nick Pelly07021e22010-02-11 11:54:28 -0800188 __u16 pkt_type = sco_pi(sk)->pkt_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 struct sco_conn *conn;
190 struct hci_conn *hcon;
191 struct hci_dev *hdev;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200192 int err, type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193
194 BT_DBG("%s -> %s", batostr(src), batostr(dst));
195
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +0200196 hdev = hci_get_route(dst, src);
197 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 return -EHOSTUNREACH;
199
200 hci_dev_lock_bh(hdev);
201
Kun Han Kim15b911f2011-07-08 09:30:28 -0700202 hdev->is_wbs = is_wbs;
203
204 if (lmp_esco_capable(hdev) && !disable_esco) {
Marcel Holtmann7cb127d2008-07-14 20:13:53 +0200205 type = ESCO_LINK;
Kun Han Kim15b911f2011-07-08 09:30:28 -0700206 } else if (is_wbs) {
207 return -ENAVAIL;
208 } else {
Marcel Holtmann7cb127d2008-07-14 20:13:53 +0200209 type = SCO_LINK;
Nick Pelly07021e22010-02-11 11:54:28 -0800210 pkt_type &= SCO_ESCO_MASK;
211 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200212
Kun Han Kim15b911f2011-07-08 09:30:28 -0700213 BT_DBG("type: %d, pkt_type: 0x%x", type, pkt_type);
214
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700215 hcon = hci_connect(hdev, type, pkt_type, dst,
216 BT_SECURITY_LOW, HCI_AT_NO_BONDING);
Ville Tervo30e76272011-02-22 16:10:53 -0300217 if (IS_ERR(hcon)) {
218 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300220 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221
Kun Han Kim15b911f2011-07-08 09:30:28 -0700222 if (is_wbs && (hcon->type != ESCO_LINK)) {
223 BT_ERR("WBS [ hcon->type: 0x%x, hcon->pkt_type: 0x%x ]",
224 hcon->type, hcon->pkt_type);
225 err = -EREMOTEIO;
226 goto done;
227 }
228
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 conn = sco_conn_add(hcon, 0);
230 if (!conn) {
231 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300232 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 goto done;
234 }
235
236 /* Update source addr of the socket */
237 bacpy(src, conn->src);
238
239 err = sco_chan_add(conn, sk, NULL);
240 if (err)
241 goto done;
242
243 if (hcon->state == BT_CONNECTED) {
244 sco_sock_clear_timer(sk);
245 sk->sk_state = BT_CONNECTED;
246 } else {
247 sk->sk_state = BT_CONNECT;
248 sco_sock_set_timer(sk, sk->sk_sndtimeo);
249 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200250
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251done:
252 hci_dev_unlock_bh(hdev);
253 hci_dev_put(hdev);
254 return err;
255}
256
257static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len)
258{
259 struct sco_conn *conn = sco_pi(sk)->conn;
260 struct sk_buff *skb;
261 int err, count;
262
263 /* Check outgoing MTU */
264 if (len > conn->mtu)
265 return -EINVAL;
266
267 BT_DBG("sk %p len %d", sk, len);
268
269 count = min_t(unsigned int, conn->mtu, len);
Gustavo F. Padovanb9dbdbc2010-05-01 16:15:35 -0300270 skb = bt_skb_send_alloc(sk, count,
271 msg->msg_flags & MSG_DONTWAIT, &err);
272 if (!skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 return err;
274
275 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) {
Gustavo F. Padovanb9dbdbc2010-05-01 16:15:35 -0300276 kfree_skb(skb);
277 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 }
279
Gustavo F. Padovan0d861d82010-05-01 16:15:35 -0300280 hci_send_sco(conn->hcon, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281
282 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283}
284
285static inline void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb)
286{
287 struct sock *sk = sco_chan_get(conn);
288
289 if (!sk)
290 goto drop;
291
292 BT_DBG("sk %p len %d", sk, skb->len);
293
294 if (sk->sk_state != BT_CONNECTED)
295 goto drop;
296
297 if (!sock_queue_rcv_skb(sk, skb))
298 return;
299
300drop:
301 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302}
303
304/* -------- Socket interface ---------- */
305static struct sock *__sco_get_sock_by_addr(bdaddr_t *ba)
306{
307 struct sock *sk;
308 struct hlist_node *node;
309
310 sk_for_each(sk, node, &sco_sk_list.head)
311 if (!bacmp(&bt_sk(sk)->src, ba))
312 goto found;
313 sk = NULL;
314found:
315 return sk;
316}
317
318/* Find socket listening on source bdaddr.
319 * Returns closest match.
320 */
321static struct sock *sco_get_sock_listen(bdaddr_t *src)
322{
323 struct sock *sk = NULL, *sk1 = NULL;
324 struct hlist_node *node;
325
326 read_lock(&sco_sk_list.lock);
327
328 sk_for_each(sk, node, &sco_sk_list.head) {
329 if (sk->sk_state != BT_LISTEN)
330 continue;
331
332 /* Exact match. */
333 if (!bacmp(&bt_sk(sk)->src, src))
334 break;
335
336 /* Closest match */
337 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
338 sk1 = sk;
339 }
340
341 read_unlock(&sco_sk_list.lock);
342
343 return node ? sk : sk1;
344}
345
346static void sco_sock_destruct(struct sock *sk)
347{
348 BT_DBG("sk %p", sk);
349
350 skb_queue_purge(&sk->sk_receive_queue);
351 skb_queue_purge(&sk->sk_write_queue);
352}
353
354static void sco_sock_cleanup_listen(struct sock *parent)
355{
356 struct sock *sk;
357
358 BT_DBG("parent %p", parent);
359
360 /* Close not yet accepted channels */
361 while ((sk = bt_accept_dequeue(parent, NULL))) {
362 sco_sock_close(sk);
363 sco_sock_kill(sk);
364 }
365
366 parent->sk_state = BT_CLOSED;
367 sock_set_flag(parent, SOCK_ZAPPED);
368}
369
370/* Kill socket (only if zapped and orphan)
371 * Must be called on unlocked socket.
372 */
373static void sco_sock_kill(struct sock *sk)
374{
375 if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
376 return;
377
378 BT_DBG("sk %p state %d", sk, sk->sk_state);
379
380 /* Kill poor orphan */
381 bt_sock_unlink(&sco_sk_list, sk);
382 sock_set_flag(sk, SOCK_DEAD);
383 sock_put(sk);
384}
385
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +0200386static void __sco_sock_close(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387{
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +0200388 BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389
390 switch (sk->sk_state) {
391 case BT_LISTEN:
392 sco_sock_cleanup_listen(sk);
393 break;
394
395 case BT_CONNECTED:
396 case BT_CONFIG:
397 case BT_CONNECT:
398 case BT_DISCONN:
399 sco_chan_del(sk, ECONNRESET);
400 break;
401
402 default:
403 sock_set_flag(sk, SOCK_ZAPPED);
404 break;
Stephen Hemminger3ff50b72007-04-20 17:09:22 -0700405 }
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +0200406}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +0200408/* Must be called on unlocked socket. */
409static void sco_sock_close(struct sock *sk)
410{
411 sco_sock_clear_timer(sk);
412 lock_sock(sk);
413 __sco_sock_close(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 sco_sock_kill(sk);
416}
417
418static void sco_sock_init(struct sock *sk, struct sock *parent)
419{
420 BT_DBG("sk %p", sk);
421
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900422 if (parent)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 sk->sk_type = parent->sk_type;
424}
425
426static struct proto sco_proto = {
427 .name = "SCO",
428 .owner = THIS_MODULE,
429 .obj_size = sizeof(struct sco_pinfo)
430};
431
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700432static struct sock *sco_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433{
434 struct sock *sk;
435
Pavel Emelyanov6257ff22007-11-01 00:39:31 -0700436 sk = sk_alloc(net, PF_BLUETOOTH, prio, &sco_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 if (!sk)
438 return NULL;
439
440 sock_init_data(sock, sk);
441 INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
442
443 sk->sk_destruct = sco_sock_destruct;
444 sk->sk_sndtimeo = SCO_CONN_TIMEOUT;
445
446 sock_reset_flag(sk, SOCK_ZAPPED);
447
448 sk->sk_protocol = proto;
449 sk->sk_state = BT_OPEN;
450
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800451 setup_timer(&sk->sk_timer, sco_sock_timeout, (unsigned long)sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452
453 bt_sock_link(&sco_sk_list, sk);
454 return sk;
455}
456
Eric Paris3f378b62009-11-05 22:18:14 -0800457static int sco_sock_create(struct net *net, struct socket *sock, int protocol,
458 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459{
460 struct sock *sk;
461
462 BT_DBG("sock %p", sock);
463
464 sock->state = SS_UNCONNECTED;
465
466 if (sock->type != SOCK_SEQPACKET)
467 return -ESOCKTNOSUPPORT;
468
469 sock->ops = &sco_sock_ops;
470
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700471 sk = sco_sock_alloc(net, sock, protocol, GFP_ATOMIC);
Marcel Holtmann74da6262006-10-15 17:31:14 +0200472 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 return -ENOMEM;
474
475 sco_sock_init(sk, NULL);
476 return 0;
477}
478
Nick Pelly07021e22010-02-11 11:54:28 -0800479static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480{
Nick Pelly07021e22010-02-11 11:54:28 -0800481 struct sockaddr_sco sa;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 struct sock *sk = sock->sk;
Nick Pelly07021e22010-02-11 11:54:28 -0800483 bdaddr_t *src = &sa.sco_bdaddr;
484 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485
Nick Pelly07021e22010-02-11 11:54:28 -0800486 BT_DBG("sk %p %s", sk, batostr(&sa.sco_bdaddr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
488 if (!addr || addr->sa_family != AF_BLUETOOTH)
489 return -EINVAL;
490
Nick Pelly07021e22010-02-11 11:54:28 -0800491 memset(&sa, 0, sizeof(sa));
492 len = min_t(unsigned int, sizeof(sa), alen);
493 memcpy(&sa, addr, len);
494
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 lock_sock(sk);
496
497 if (sk->sk_state != BT_OPEN) {
498 err = -EBADFD;
499 goto done;
500 }
501
502 write_lock_bh(&sco_sk_list.lock);
503
504 if (bacmp(src, BDADDR_ANY) && __sco_get_sock_by_addr(src)) {
505 err = -EADDRINUSE;
506 } else {
507 /* Save source address */
Nick Pelly07021e22010-02-11 11:54:28 -0800508 bacpy(&bt_sk(sk)->src, &sa.sco_bdaddr);
509 sco_pi(sk)->pkt_type = sa.sco_pkt_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 sk->sk_state = BT_BOUND;
511 }
512
513 write_unlock_bh(&sco_sk_list.lock);
514
515done:
516 release_sock(sk);
517 return err;
518}
519
520static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
521{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 struct sock *sk = sock->sk;
Nick Pelly07021e22010-02-11 11:54:28 -0800523 struct sockaddr_sco sa;
524 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525
526 BT_DBG("sk %p", sk);
527
Nick Pelly07021e22010-02-11 11:54:28 -0800528 if (!addr || addr->sa_family != AF_BLUETOOTH)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 return -EINVAL;
530
Nick Pelly07021e22010-02-11 11:54:28 -0800531 memset(&sa, 0, sizeof(sa));
532 len = min_t(unsigned int, sizeof(sa), alen);
533 memcpy(&sa, addr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534
535 lock_sock(sk);
536
Nick Pelly07021e22010-02-11 11:54:28 -0800537 if (sk->sk_type != SOCK_SEQPACKET) {
538 err = -EINVAL;
539 goto done;
540 }
541
542 if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) {
543 err = -EBADFD;
544 goto done;
545 }
546
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 /* Set destination address and psm */
Nick Pelly07021e22010-02-11 11:54:28 -0800548 bacpy(&bt_sk(sk)->dst, &sa.sco_bdaddr);
549 sco_pi(sk)->pkt_type = sa.sco_pkt_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
Kun Han Kim15b911f2011-07-08 09:30:28 -0700551 err = sco_connect(sk, sa.is_wbs);
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +0200552 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 goto done;
554
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900555 err = bt_sock_wait_state(sk, BT_CONNECTED,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 sock_sndtimeo(sk, flags & O_NONBLOCK));
557
558done:
559 release_sock(sk);
560 return err;
561}
562
563static int sco_sock_listen(struct socket *sock, int backlog)
564{
565 struct sock *sk = sock->sk;
566 int err = 0;
567
568 BT_DBG("sk %p backlog %d", sk, backlog);
569
570 lock_sock(sk);
571
572 if (sk->sk_state != BT_BOUND || sock->type != SOCK_SEQPACKET) {
573 err = -EBADFD;
574 goto done;
575 }
576
577 sk->sk_max_ack_backlog = backlog;
578 sk->sk_ack_backlog = 0;
579 sk->sk_state = BT_LISTEN;
580
581done:
582 release_sock(sk);
583 return err;
584}
585
586static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flags)
587{
588 DECLARE_WAITQUEUE(wait, current);
589 struct sock *sk = sock->sk, *ch;
590 long timeo;
591 int err = 0;
592
593 lock_sock(sk);
594
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700595 if (sk->sk_state != BT_LISTEN) {
596 err = -EBADFD;
597 goto done;
598 }
599
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
601
602 BT_DBG("sk %p timeo %ld", sk, timeo);
603
604 /* Wait for an incoming connection. (wake-one). */
Eric Dumazetaa395142010-04-20 13:03:51 +0000605 add_wait_queue_exclusive(sk_sleep(sk), &wait);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700606 while (!(ch = bt_accept_dequeue(sk, newsock))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 set_current_state(TASK_INTERRUPTIBLE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700608 if (!timeo) {
609 err = -EAGAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 break;
611 }
612
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700613 release_sock(sk);
614 timeo = schedule_timeout(timeo);
615 lock_sock(sk);
Peter Hurley552b0d32011-07-24 00:11:01 -0400616
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700617 if (sk->sk_state != BT_LISTEN) {
618 err = -EBADFD;
Peter Hurley552b0d32011-07-24 00:11:01 -0400619 break;
620 }
621
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 if (signal_pending(current)) {
623 err = sock_intr_errno(timeo);
624 break;
625 }
626 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700627 set_current_state(TASK_RUNNING);
Eric Dumazetaa395142010-04-20 13:03:51 +0000628 remove_wait_queue(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629
630 if (err)
631 goto done;
632
633 newsock->state = SS_CONNECTED;
634
635 BT_DBG("new socket %p", ch);
636
637done:
638 release_sock(sk);
639 return err;
640}
641
642static int sco_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
643{
644 struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
645 struct sock *sk = sock->sk;
646
647 BT_DBG("sock %p, sk %p", sock, sk);
648
649 addr->sa_family = AF_BLUETOOTH;
650 *len = sizeof(struct sockaddr_sco);
651
652 if (peer)
653 bacpy(&sa->sco_bdaddr, &bt_sk(sk)->dst);
654 else
655 bacpy(&sa->sco_bdaddr, &bt_sk(sk)->src);
Nick Pelly07021e22010-02-11 11:54:28 -0800656 sa->sco_pkt_type = sco_pi(sk)->pkt_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657
658 return 0;
659}
660
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900661static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 struct msghdr *msg, size_t len)
663{
664 struct sock *sk = sock->sk;
Gustavo F. Padovanb9dbdbc2010-05-01 16:15:35 -0300665 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666
667 BT_DBG("sock %p, sk %p", sock, sk);
668
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -0800669 err = sock_error(sk);
670 if (err)
671 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672
673 if (msg->msg_flags & MSG_OOB)
674 return -EOPNOTSUPP;
675
676 lock_sock(sk);
677
678 if (sk->sk_state == BT_CONNECTED)
679 err = sco_send_frame(sk, msg, len);
680 else
681 err = -ENOTCONN;
682
683 release_sock(sk);
684 return err;
685}
686
David S. Millerb7058842009-09-30 16:12:20 -0700687static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688{
689 struct sock *sk = sock->sk;
690 int err = 0;
691
692 BT_DBG("sk %p", sk);
693
694 lock_sock(sk);
695
696 switch (optname) {
697 default:
698 err = -ENOPROTOOPT;
699 break;
700 }
701
702 release_sock(sk);
703 return err;
704}
705
Marcel Holtmannd58daf42009-01-15 21:52:14 +0100706static int sco_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707{
708 struct sock *sk = sock->sk;
709 struct sco_options opts;
710 struct sco_conninfo cinfo;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900711 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712
713 BT_DBG("sk %p", sk);
714
715 if (get_user(len, optlen))
716 return -EFAULT;
717
718 lock_sock(sk);
719
720 switch (optname) {
721 case SCO_OPTIONS:
722 if (sk->sk_state != BT_CONNECTED) {
723 err = -ENOTCONN;
724 break;
725 }
726
727 opts.mtu = sco_pi(sk)->conn->mtu;
728
729 BT_DBG("mtu %d", opts.mtu);
730
731 len = min_t(unsigned int, len, sizeof(opts));
732 if (copy_to_user(optval, (char *)&opts, len))
733 err = -EFAULT;
734
735 break;
736
737 case SCO_CONNINFO:
738 if (sk->sk_state != BT_CONNECTED) {
739 err = -ENOTCONN;
740 break;
741 }
742
Vasiliy Kulikovc4c896e2011-02-14 13:54:26 +0300743 memset(&cinfo, 0, sizeof(cinfo));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
745 memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
746
747 len = min_t(unsigned int, len, sizeof(cinfo));
748 if (copy_to_user(optval, (char *)&cinfo, len))
749 err = -EFAULT;
750
751 break;
752
753 default:
754 err = -ENOPROTOOPT;
755 break;
756 }
757
758 release_sock(sk);
759 return err;
760}
761
Marcel Holtmannd58daf42009-01-15 21:52:14 +0100762static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
763{
764 struct sock *sk = sock->sk;
765 int len, err = 0;
766
767 BT_DBG("sk %p", sk);
768
769 if (level == SOL_SCO)
770 return sco_sock_getsockopt_old(sock, optname, optval, optlen);
771
772 if (get_user(len, optlen))
773 return -EFAULT;
774
775 lock_sock(sk);
776
777 switch (optname) {
778 default:
779 err = -ENOPROTOOPT;
780 break;
781 }
782
783 release_sock(sk);
784 return err;
785}
786
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +0200787static int sco_sock_shutdown(struct socket *sock, int how)
788{
789 struct sock *sk = sock->sk;
790 int err = 0;
791
792 BT_DBG("sock %p, sk %p", sock, sk);
793
794 if (!sk)
795 return 0;
796
797 lock_sock(sk);
798 if (!sk->sk_shutdown) {
799 sk->sk_shutdown = SHUTDOWN_MASK;
800 sco_sock_clear_timer(sk);
801 __sco_sock_close(sk);
802
803 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
804 err = bt_sock_wait_state(sk, BT_CLOSED,
805 sk->sk_lingertime);
806 }
807 release_sock(sk);
808 return err;
809}
810
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811static int sco_sock_release(struct socket *sock)
812{
813 struct sock *sk = sock->sk;
814 int err = 0;
815
816 BT_DBG("sock %p, sk %p", sock, sk);
817
818 if (!sk)
819 return 0;
820
821 sco_sock_close(sk);
822
823 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) {
824 lock_sock(sk);
825 err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
826 release_sock(sk);
827 }
828
829 sock_orphan(sk);
830 sco_sock_kill(sk);
831 return err;
832}
833
834static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent)
835{
836 BT_DBG("conn %p", conn);
837
838 sco_pi(sk)->conn = conn;
839 conn->sk = sk;
840
841 if (parent)
842 bt_accept_enqueue(parent, sk);
843}
844
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900845/* Delete channel.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 * Must be called on the locked socket. */
847static void sco_chan_del(struct sock *sk, int err)
848{
849 struct sco_conn *conn;
850
851 conn = sco_pi(sk)->conn;
852
853 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
854
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900855 if (conn) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 sco_conn_lock(conn);
857 conn->sk = NULL;
858 sco_pi(sk)->conn = NULL;
859 sco_conn_unlock(conn);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700860 hci_conn_put(conn->hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 }
862
863 sk->sk_state = BT_CLOSED;
864 sk->sk_err = err;
865 sk->sk_state_change(sk);
866
867 sock_set_flag(sk, SOCK_ZAPPED);
868}
869
870static void sco_conn_ready(struct sco_conn *conn)
871{
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +0200872 struct sock *parent;
873 struct sock *sk = conn->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874
875 BT_DBG("conn %p", conn);
876
877 sco_conn_lock(conn);
878
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +0200879 if (sk) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 sco_sock_clear_timer(sk);
881 bh_lock_sock(sk);
882 sk->sk_state = BT_CONNECTED;
883 sk->sk_state_change(sk);
884 bh_unlock_sock(sk);
885 } else {
886 parent = sco_get_sock_listen(conn->src);
887 if (!parent)
888 goto done;
889
890 bh_lock_sock(parent);
891
Gustavo F. Padovanb9dbdbc2010-05-01 16:15:35 -0300892 sk = sco_sock_alloc(sock_net(parent), NULL,
893 BTPROTO_SCO, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 if (!sk) {
895 bh_unlock_sock(parent);
896 goto done;
897 }
898
899 sco_sock_init(sk, parent);
900
901 bacpy(&bt_sk(sk)->src, conn->src);
902 bacpy(&bt_sk(sk)->dst, conn->dst);
903
904 hci_conn_hold(conn->hcon);
905 __sco_chan_add(conn, sk, parent);
906
907 sk->sk_state = BT_CONNECTED;
908
909 /* Wake up parent */
910 parent->sk_data_ready(parent, 1);
911
912 bh_unlock_sock(parent);
913 }
914
915done:
916 sco_conn_unlock(conn);
917}
918
919/* ----- SCO interface with lower layer (HCI) ----- */
920static int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
921{
Marcel Holtmann71aeeaa2009-01-15 21:57:02 +0100922 register struct sock *sk;
923 struct hlist_node *node;
924 int lm = 0;
925
926 if (type != SCO_LINK && type != ESCO_LINK)
Mat Martineau8b51dd42012-02-13 10:38:24 -0800927 return 0;
Marcel Holtmann71aeeaa2009-01-15 21:57:02 +0100928
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
930
Marcel Holtmann71aeeaa2009-01-15 21:57:02 +0100931 /* Find listening sockets */
932 read_lock(&sco_sk_list.lock);
933 sk_for_each(sk, node, &sco_sk_list.head) {
934 if (sk->sk_state != BT_LISTEN)
935 continue;
936
937 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr) ||
938 !bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
939 lm |= HCI_LM_ACCEPT;
940 break;
941 }
942 }
943 read_unlock(&sco_sk_list.lock);
944
945 return lm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946}
947
948static int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
949{
950 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
951
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200952 if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
Gustavo F. Padovanc89ad732010-11-01 19:08:50 +0000953 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954
955 if (!status) {
956 struct sco_conn *conn;
957
958 conn = sco_conn_add(hcon, status);
959 if (conn)
960 sco_conn_ready(conn);
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900961 } else
Mat Martineau3b9239a2012-02-16 11:54:30 -0800962 sco_conn_del(hcon, bt_err(status), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963
964 return 0;
965}
966
Mat Martineau3b9239a2012-02-16 11:54:30 -0800967static int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason, __u8 is_process)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968{
969 BT_DBG("hcon %p reason %d", hcon, reason);
970
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200971 if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
Gustavo F. Padovanc89ad732010-11-01 19:08:50 +0000972 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973
Mat Martineau3b9239a2012-02-16 11:54:30 -0800974 sco_conn_del(hcon, bt_err(reason), is_process);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200975
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 return 0;
977}
978
979static int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb)
980{
981 struct sco_conn *conn = hcon->sco_data;
982
983 if (!conn)
984 goto drop;
985
986 BT_DBG("conn %p len %d", conn, skb->len);
987
988 if (skb->len) {
989 sco_recv_frame(conn, skb);
990 return 0;
991 }
992
993drop:
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900994 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 return 0;
996}
997
Marcel Holtmannaef7d972010-03-21 05:27:45 +0100998static int sco_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999{
1000 struct sock *sk;
1001 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002
1003 read_lock_bh(&sco_sk_list.lock);
1004
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08001005 sk_for_each(sk, node, &sco_sk_list.head) {
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001006 seq_printf(f, "%s %s %d\n", batostr(&bt_sk(sk)->src),
1007 batostr(&bt_sk(sk)->dst), sk->sk_state);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08001008 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 read_unlock_bh(&sco_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08001011
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001012 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013}
1014
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001015static int sco_debugfs_open(struct inode *inode, struct file *file)
1016{
1017 return single_open(file, sco_debugfs_show, inode->i_private);
1018}
1019
1020static const struct file_operations sco_debugfs_fops = {
1021 .open = sco_debugfs_open,
1022 .read = seq_read,
1023 .llseek = seq_lseek,
1024 .release = single_release,
1025};
1026
1027static struct dentry *sco_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028
Eric Dumazet90ddc4f2005-12-22 12:49:22 -08001029static const struct proto_ops sco_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 .family = PF_BLUETOOTH,
1031 .owner = THIS_MODULE,
1032 .release = sco_sock_release,
1033 .bind = sco_sock_bind,
1034 .connect = sco_sock_connect,
1035 .listen = sco_sock_listen,
1036 .accept = sco_sock_accept,
1037 .getname = sco_sock_getname,
1038 .sendmsg = sco_sock_sendmsg,
1039 .recvmsg = bt_sock_recvmsg,
1040 .poll = bt_sock_poll,
Marcel Holtmann3241ad82008-07-14 20:13:50 +02001041 .ioctl = bt_sock_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 .mmap = sock_no_mmap,
1043 .socketpair = sock_no_socketpair,
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +02001044 .shutdown = sco_sock_shutdown,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 .setsockopt = sco_sock_setsockopt,
1046 .getsockopt = sco_sock_getsockopt
1047};
1048
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +00001049static const struct net_proto_family sco_sock_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 .family = PF_BLUETOOTH,
1051 .owner = THIS_MODULE,
1052 .create = sco_sock_create,
1053};
1054
1055static struct hci_proto sco_hci_proto = {
1056 .name = "SCO",
1057 .id = HCI_PROTO_SCO,
1058 .connect_ind = sco_connect_ind,
1059 .connect_cfm = sco_connect_cfm,
Marcel Holtmann2950f212009-02-12 14:02:50 +01001060 .disconn_cfm = sco_disconn_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 .recv_scodata = sco_recv_scodata
1062};
1063
Gustavo F. Padovan64274512011-02-07 20:08:52 -02001064int __init sco_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065{
1066 int err;
1067
1068 err = proto_register(&sco_proto, 0);
1069 if (err < 0)
1070 return err;
1071
1072 err = bt_sock_register(BTPROTO_SCO, &sco_sock_family_ops);
1073 if (err < 0) {
1074 BT_ERR("SCO socket registration failed");
1075 goto error;
1076 }
1077
1078 err = hci_register_proto(&sco_hci_proto);
1079 if (err < 0) {
1080 BT_ERR("SCO protocol registration failed");
1081 bt_sock_unregister(BTPROTO_SCO);
1082 goto error;
1083 }
1084
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001085 if (bt_debugfs) {
1086 sco_debugfs = debugfs_create_file("sco", 0444,
1087 bt_debugfs, NULL, &sco_debugfs_fops);
1088 if (!sco_debugfs)
1089 BT_ERR("Failed to create SCO debug file");
1090 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 BT_INFO("SCO socket layer initialized");
1093
1094 return 0;
1095
1096error:
1097 proto_unregister(&sco_proto);
1098 return err;
1099}
1100
Gustavo F. Padovan64274512011-02-07 20:08:52 -02001101void __exit sco_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001103 debugfs_remove(sco_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104
1105 if (bt_sock_unregister(BTPROTO_SCO) < 0)
1106 BT_ERR("SCO socket unregistration failed");
1107
1108 if (hci_unregister_proto(&sco_hci_proto) < 0)
1109 BT_ERR("SCO protocol unregistration failed");
1110
1111 proto_unregister(&sco_proto);
1112}
1113
Marcel Holtmann7cb127d2008-07-14 20:13:53 +02001114module_param(disable_esco, bool, 0644);
1115MODULE_PARM_DESC(disable_esco, "Disable eSCO connection creation");