blob: 9669d4ab58f1e1de617b6d967581c801102e4c71 [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:
Luiz Augusto von Dentz2e02b8612011-05-12 11:13:15 +0300397 if (sco_pi(sk)->conn) {
398 sk->sk_state = BT_DISCONN;
399 sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT);
400 hci_conn_put(sco_pi(sk)->conn->hcon);
401 sco_pi(sk)->conn->hcon = NULL;
402 } else
403 sco_chan_del(sk, ECONNRESET);
404 break;
405
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 case BT_CONNECT:
407 case BT_DISCONN:
408 sco_chan_del(sk, ECONNRESET);
409 break;
410
411 default:
412 sock_set_flag(sk, SOCK_ZAPPED);
413 break;
Stephen Hemminger3ff50b72007-04-20 17:09:22 -0700414 }
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +0200415}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +0200417/* Must be called on unlocked socket. */
418static void sco_sock_close(struct sock *sk)
419{
420 sco_sock_clear_timer(sk);
421 lock_sock(sk);
422 __sco_sock_close(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 sco_sock_kill(sk);
425}
426
427static void sco_sock_init(struct sock *sk, struct sock *parent)
428{
429 BT_DBG("sk %p", sk);
430
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900431 if (parent)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 sk->sk_type = parent->sk_type;
433}
434
435static struct proto sco_proto = {
436 .name = "SCO",
437 .owner = THIS_MODULE,
438 .obj_size = sizeof(struct sco_pinfo)
439};
440
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700441static struct sock *sco_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442{
443 struct sock *sk;
444
Pavel Emelyanov6257ff22007-11-01 00:39:31 -0700445 sk = sk_alloc(net, PF_BLUETOOTH, prio, &sco_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 if (!sk)
447 return NULL;
448
449 sock_init_data(sock, sk);
450 INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
451
452 sk->sk_destruct = sco_sock_destruct;
453 sk->sk_sndtimeo = SCO_CONN_TIMEOUT;
454
455 sock_reset_flag(sk, SOCK_ZAPPED);
456
457 sk->sk_protocol = proto;
458 sk->sk_state = BT_OPEN;
459
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800460 setup_timer(&sk->sk_timer, sco_sock_timeout, (unsigned long)sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461
462 bt_sock_link(&sco_sk_list, sk);
463 return sk;
464}
465
Eric Paris3f378b62009-11-05 22:18:14 -0800466static int sco_sock_create(struct net *net, struct socket *sock, int protocol,
467 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468{
469 struct sock *sk;
470
471 BT_DBG("sock %p", sock);
472
473 sock->state = SS_UNCONNECTED;
474
475 if (sock->type != SOCK_SEQPACKET)
476 return -ESOCKTNOSUPPORT;
477
478 sock->ops = &sco_sock_ops;
479
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700480 sk = sco_sock_alloc(net, sock, protocol, GFP_ATOMIC);
Marcel Holtmann74da6262006-10-15 17:31:14 +0200481 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 return -ENOMEM;
483
484 sco_sock_init(sk, NULL);
485 return 0;
486}
487
Nick Pelly07021e22010-02-11 11:54:28 -0800488static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489{
Nick Pelly07021e22010-02-11 11:54:28 -0800490 struct sockaddr_sco sa;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 struct sock *sk = sock->sk;
Nick Pelly07021e22010-02-11 11:54:28 -0800492 bdaddr_t *src = &sa.sco_bdaddr;
493 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494
Nick Pelly07021e22010-02-11 11:54:28 -0800495 BT_DBG("sk %p %s", sk, batostr(&sa.sco_bdaddr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496
497 if (!addr || addr->sa_family != AF_BLUETOOTH)
498 return -EINVAL;
499
Nick Pelly07021e22010-02-11 11:54:28 -0800500 memset(&sa, 0, sizeof(sa));
501 len = min_t(unsigned int, sizeof(sa), alen);
502 memcpy(&sa, addr, len);
503
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 lock_sock(sk);
505
506 if (sk->sk_state != BT_OPEN) {
507 err = -EBADFD;
508 goto done;
509 }
510
511 write_lock_bh(&sco_sk_list.lock);
512
513 if (bacmp(src, BDADDR_ANY) && __sco_get_sock_by_addr(src)) {
514 err = -EADDRINUSE;
515 } else {
516 /* Save source address */
Nick Pelly07021e22010-02-11 11:54:28 -0800517 bacpy(&bt_sk(sk)->src, &sa.sco_bdaddr);
518 sco_pi(sk)->pkt_type = sa.sco_pkt_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 sk->sk_state = BT_BOUND;
520 }
521
522 write_unlock_bh(&sco_sk_list.lock);
523
524done:
525 release_sock(sk);
526 return err;
527}
528
529static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
530{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 struct sock *sk = sock->sk;
Nick Pelly07021e22010-02-11 11:54:28 -0800532 struct sockaddr_sco sa;
533 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534
535 BT_DBG("sk %p", sk);
536
Nick Pelly07021e22010-02-11 11:54:28 -0800537 if (!addr || addr->sa_family != AF_BLUETOOTH)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 return -EINVAL;
539
Nick Pelly07021e22010-02-11 11:54:28 -0800540 memset(&sa, 0, sizeof(sa));
541 len = min_t(unsigned int, sizeof(sa), alen);
542 memcpy(&sa, addr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543
544 lock_sock(sk);
545
Nick Pelly07021e22010-02-11 11:54:28 -0800546 if (sk->sk_type != SOCK_SEQPACKET) {
547 err = -EINVAL;
548 goto done;
549 }
550
551 if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) {
552 err = -EBADFD;
553 goto done;
554 }
555
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 /* Set destination address and psm */
Nick Pelly07021e22010-02-11 11:54:28 -0800557 bacpy(&bt_sk(sk)->dst, &sa.sco_bdaddr);
558 sco_pi(sk)->pkt_type = sa.sco_pkt_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559
Kun Han Kim15b911f2011-07-08 09:30:28 -0700560 err = sco_connect(sk, sa.is_wbs);
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +0200561 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 goto done;
563
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900564 err = bt_sock_wait_state(sk, BT_CONNECTED,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 sock_sndtimeo(sk, flags & O_NONBLOCK));
566
567done:
568 release_sock(sk);
569 return err;
570}
571
572static int sco_sock_listen(struct socket *sock, int backlog)
573{
574 struct sock *sk = sock->sk;
575 int err = 0;
576
577 BT_DBG("sk %p backlog %d", sk, backlog);
578
579 lock_sock(sk);
580
581 if (sk->sk_state != BT_BOUND || sock->type != SOCK_SEQPACKET) {
582 err = -EBADFD;
583 goto done;
584 }
585
586 sk->sk_max_ack_backlog = backlog;
587 sk->sk_ack_backlog = 0;
588 sk->sk_state = BT_LISTEN;
589
590done:
591 release_sock(sk);
592 return err;
593}
594
595static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flags)
596{
597 DECLARE_WAITQUEUE(wait, current);
598 struct sock *sk = sock->sk, *ch;
599 long timeo;
600 int err = 0;
601
602 lock_sock(sk);
603
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700604 if (sk->sk_state != BT_LISTEN) {
605 err = -EBADFD;
606 goto done;
607 }
608
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
610
611 BT_DBG("sk %p timeo %ld", sk, timeo);
612
613 /* Wait for an incoming connection. (wake-one). */
Eric Dumazetaa395142010-04-20 13:03:51 +0000614 add_wait_queue_exclusive(sk_sleep(sk), &wait);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700615 while (!(ch = bt_accept_dequeue(sk, newsock))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 set_current_state(TASK_INTERRUPTIBLE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700617 if (!timeo) {
618 err = -EAGAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 break;
620 }
621
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700622 release_sock(sk);
623 timeo = schedule_timeout(timeo);
624 lock_sock(sk);
Peter Hurley552b0d32011-07-24 00:11:01 -0400625
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700626 if (sk->sk_state != BT_LISTEN) {
627 err = -EBADFD;
Peter Hurley552b0d32011-07-24 00:11:01 -0400628 break;
629 }
630
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 if (signal_pending(current)) {
632 err = sock_intr_errno(timeo);
633 break;
634 }
635 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700636 set_current_state(TASK_RUNNING);
Eric Dumazetaa395142010-04-20 13:03:51 +0000637 remove_wait_queue(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638
639 if (err)
640 goto done;
641
642 newsock->state = SS_CONNECTED;
643
644 BT_DBG("new socket %p", ch);
645
646done:
647 release_sock(sk);
648 return err;
649}
650
651static int sco_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
652{
653 struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
654 struct sock *sk = sock->sk;
655
656 BT_DBG("sock %p, sk %p", sock, sk);
657
658 addr->sa_family = AF_BLUETOOTH;
659 *len = sizeof(struct sockaddr_sco);
660
661 if (peer)
662 bacpy(&sa->sco_bdaddr, &bt_sk(sk)->dst);
663 else
664 bacpy(&sa->sco_bdaddr, &bt_sk(sk)->src);
Nick Pelly07021e22010-02-11 11:54:28 -0800665 sa->sco_pkt_type = sco_pi(sk)->pkt_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666
667 return 0;
668}
669
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900670static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 struct msghdr *msg, size_t len)
672{
673 struct sock *sk = sock->sk;
Gustavo F. Padovanb9dbdbc2010-05-01 16:15:35 -0300674 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675
676 BT_DBG("sock %p, sk %p", sock, sk);
677
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -0800678 err = sock_error(sk);
679 if (err)
680 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681
682 if (msg->msg_flags & MSG_OOB)
683 return -EOPNOTSUPP;
684
685 lock_sock(sk);
686
687 if (sk->sk_state == BT_CONNECTED)
688 err = sco_send_frame(sk, msg, len);
689 else
690 err = -ENOTCONN;
691
692 release_sock(sk);
693 return err;
694}
695
David S. Millerb7058842009-09-30 16:12:20 -0700696static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697{
698 struct sock *sk = sock->sk;
699 int err = 0;
700
701 BT_DBG("sk %p", sk);
702
703 lock_sock(sk);
704
705 switch (optname) {
706 default:
707 err = -ENOPROTOOPT;
708 break;
709 }
710
711 release_sock(sk);
712 return err;
713}
714
Marcel Holtmannd58daf42009-01-15 21:52:14 +0100715static int sco_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716{
717 struct sock *sk = sock->sk;
718 struct sco_options opts;
719 struct sco_conninfo cinfo;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900720 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721
722 BT_DBG("sk %p", sk);
723
724 if (get_user(len, optlen))
725 return -EFAULT;
726
727 lock_sock(sk);
728
729 switch (optname) {
730 case SCO_OPTIONS:
731 if (sk->sk_state != BT_CONNECTED) {
732 err = -ENOTCONN;
733 break;
734 }
735
736 opts.mtu = sco_pi(sk)->conn->mtu;
737
738 BT_DBG("mtu %d", opts.mtu);
739
740 len = min_t(unsigned int, len, sizeof(opts));
741 if (copy_to_user(optval, (char *)&opts, len))
742 err = -EFAULT;
743
744 break;
745
746 case SCO_CONNINFO:
747 if (sk->sk_state != BT_CONNECTED) {
748 err = -ENOTCONN;
749 break;
750 }
751
Vasiliy Kulikovc4c896e2011-02-14 13:54:26 +0300752 memset(&cinfo, 0, sizeof(cinfo));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
754 memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
755
756 len = min_t(unsigned int, len, sizeof(cinfo));
757 if (copy_to_user(optval, (char *)&cinfo, len))
758 err = -EFAULT;
759
760 break;
761
762 default:
763 err = -ENOPROTOOPT;
764 break;
765 }
766
767 release_sock(sk);
768 return err;
769}
770
Marcel Holtmannd58daf42009-01-15 21:52:14 +0100771static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
772{
773 struct sock *sk = sock->sk;
774 int len, err = 0;
775
776 BT_DBG("sk %p", sk);
777
778 if (level == SOL_SCO)
779 return sco_sock_getsockopt_old(sock, optname, optval, optlen);
780
781 if (get_user(len, optlen))
782 return -EFAULT;
783
784 lock_sock(sk);
785
786 switch (optname) {
787 default:
788 err = -ENOPROTOOPT;
789 break;
790 }
791
792 release_sock(sk);
793 return err;
794}
795
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +0200796static int sco_sock_shutdown(struct socket *sock, int how)
797{
798 struct sock *sk = sock->sk;
799 int err = 0;
800
801 BT_DBG("sock %p, sk %p", sock, sk);
802
803 if (!sk)
804 return 0;
805
806 lock_sock(sk);
807 if (!sk->sk_shutdown) {
808 sk->sk_shutdown = SHUTDOWN_MASK;
809 sco_sock_clear_timer(sk);
810 __sco_sock_close(sk);
811
812 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
813 err = bt_sock_wait_state(sk, BT_CLOSED,
814 sk->sk_lingertime);
Srinivas Krovvidif7999962012-08-01 18:21:37 +0530815 else
816 err = bt_sock_wait_state(sk, BT_CLOSED,
817 SCO_DISCONN_TIMEOUT);
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +0200818 }
819 release_sock(sk);
820 return err;
821}
822
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823static int sco_sock_release(struct socket *sock)
824{
825 struct sock *sk = sock->sk;
826 int err = 0;
827
828 BT_DBG("sock %p, sk %p", sock, sk);
829
830 if (!sk)
831 return 0;
832
833 sco_sock_close(sk);
834
835 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) {
836 lock_sock(sk);
837 err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
838 release_sock(sk);
Srinivas Krovvidif7999962012-08-01 18:21:37 +0530839 } else {
840 lock_sock(sk);
841 err = bt_sock_wait_state(sk, BT_CLOSED,
842 SCO_DISCONN_TIMEOUT);
843 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 }
845
846 sock_orphan(sk);
847 sco_sock_kill(sk);
848 return err;
849}
850
851static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent)
852{
853 BT_DBG("conn %p", conn);
854
855 sco_pi(sk)->conn = conn;
856 conn->sk = sk;
857
858 if (parent)
859 bt_accept_enqueue(parent, sk);
860}
861
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900862/* Delete channel.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 * Must be called on the locked socket. */
864static void sco_chan_del(struct sock *sk, int err)
865{
866 struct sco_conn *conn;
867
868 conn = sco_pi(sk)->conn;
869
870 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
871
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900872 if (conn) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 sco_conn_lock(conn);
874 conn->sk = NULL;
875 sco_pi(sk)->conn = NULL;
876 sco_conn_unlock(conn);
Luiz Augusto von Dentz2e02b8612011-05-12 11:13:15 +0300877
878 if (conn->hcon)
879 hci_conn_put(conn->hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 }
881
882 sk->sk_state = BT_CLOSED;
883 sk->sk_err = err;
884 sk->sk_state_change(sk);
885
886 sock_set_flag(sk, SOCK_ZAPPED);
887}
888
889static void sco_conn_ready(struct sco_conn *conn)
890{
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +0200891 struct sock *parent;
892 struct sock *sk = conn->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893
894 BT_DBG("conn %p", conn);
895
896 sco_conn_lock(conn);
897
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +0200898 if (sk) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 sco_sock_clear_timer(sk);
900 bh_lock_sock(sk);
901 sk->sk_state = BT_CONNECTED;
902 sk->sk_state_change(sk);
903 bh_unlock_sock(sk);
904 } else {
905 parent = sco_get_sock_listen(conn->src);
906 if (!parent)
907 goto done;
908
909 bh_lock_sock(parent);
910
Gustavo F. Padovanb9dbdbc2010-05-01 16:15:35 -0300911 sk = sco_sock_alloc(sock_net(parent), NULL,
912 BTPROTO_SCO, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 if (!sk) {
914 bh_unlock_sock(parent);
915 goto done;
916 }
917
918 sco_sock_init(sk, parent);
919
920 bacpy(&bt_sk(sk)->src, conn->src);
921 bacpy(&bt_sk(sk)->dst, conn->dst);
922
923 hci_conn_hold(conn->hcon);
924 __sco_chan_add(conn, sk, parent);
925
926 sk->sk_state = BT_CONNECTED;
927
928 /* Wake up parent */
929 parent->sk_data_ready(parent, 1);
930
931 bh_unlock_sock(parent);
932 }
933
934done:
935 sco_conn_unlock(conn);
936}
937
938/* ----- SCO interface with lower layer (HCI) ----- */
939static int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
940{
Marcel Holtmann71aeeaa2009-01-15 21:57:02 +0100941 register struct sock *sk;
942 struct hlist_node *node;
943 int lm = 0;
944
945 if (type != SCO_LINK && type != ESCO_LINK)
Mat Martineau8b51dd42012-02-13 10:38:24 -0800946 return 0;
Marcel Holtmann71aeeaa2009-01-15 21:57:02 +0100947
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
949
Marcel Holtmann71aeeaa2009-01-15 21:57:02 +0100950 /* Find listening sockets */
951 read_lock(&sco_sk_list.lock);
952 sk_for_each(sk, node, &sco_sk_list.head) {
953 if (sk->sk_state != BT_LISTEN)
954 continue;
955
956 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr) ||
957 !bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
958 lm |= HCI_LM_ACCEPT;
959 break;
960 }
961 }
962 read_unlock(&sco_sk_list.lock);
963
964 return lm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965}
966
967static int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
968{
969 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
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
974 if (!status) {
975 struct sco_conn *conn;
976
977 conn = sco_conn_add(hcon, status);
978 if (conn)
979 sco_conn_ready(conn);
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900980 } else
Mat Martineau3b9239a2012-02-16 11:54:30 -0800981 sco_conn_del(hcon, bt_err(status), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982
983 return 0;
984}
985
Mat Martineau3b9239a2012-02-16 11:54:30 -0800986static int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason, __u8 is_process)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987{
988 BT_DBG("hcon %p reason %d", hcon, reason);
989
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200990 if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
Gustavo F. Padovanc89ad732010-11-01 19:08:50 +0000991 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992
Mat Martineau3b9239a2012-02-16 11:54:30 -0800993 sco_conn_del(hcon, bt_err(reason), is_process);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200994
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 return 0;
996}
997
998static int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb)
999{
1000 struct sco_conn *conn = hcon->sco_data;
1001
1002 if (!conn)
1003 goto drop;
1004
1005 BT_DBG("conn %p len %d", conn, skb->len);
1006
1007 if (skb->len) {
1008 sco_recv_frame(conn, skb);
1009 return 0;
1010 }
1011
1012drop:
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001013 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 return 0;
1015}
1016
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001017static int sco_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018{
1019 struct sock *sk;
1020 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021
1022 read_lock_bh(&sco_sk_list.lock);
1023
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08001024 sk_for_each(sk, node, &sco_sk_list.head) {
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001025 seq_printf(f, "%s %s %d\n", batostr(&bt_sk(sk)->src),
1026 batostr(&bt_sk(sk)->dst), sk->sk_state);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08001027 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 read_unlock_bh(&sco_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08001030
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001031 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032}
1033
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001034static int sco_debugfs_open(struct inode *inode, struct file *file)
1035{
1036 return single_open(file, sco_debugfs_show, inode->i_private);
1037}
1038
1039static const struct file_operations sco_debugfs_fops = {
1040 .open = sco_debugfs_open,
1041 .read = seq_read,
1042 .llseek = seq_lseek,
1043 .release = single_release,
1044};
1045
1046static struct dentry *sco_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
Eric Dumazet90ddc4f2005-12-22 12:49:22 -08001048static const struct proto_ops sco_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 .family = PF_BLUETOOTH,
1050 .owner = THIS_MODULE,
1051 .release = sco_sock_release,
1052 .bind = sco_sock_bind,
1053 .connect = sco_sock_connect,
1054 .listen = sco_sock_listen,
1055 .accept = sco_sock_accept,
1056 .getname = sco_sock_getname,
1057 .sendmsg = sco_sock_sendmsg,
1058 .recvmsg = bt_sock_recvmsg,
1059 .poll = bt_sock_poll,
Marcel Holtmann3241ad82008-07-14 20:13:50 +02001060 .ioctl = bt_sock_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 .mmap = sock_no_mmap,
1062 .socketpair = sock_no_socketpair,
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +02001063 .shutdown = sco_sock_shutdown,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 .setsockopt = sco_sock_setsockopt,
1065 .getsockopt = sco_sock_getsockopt
1066};
1067
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +00001068static const struct net_proto_family sco_sock_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 .family = PF_BLUETOOTH,
1070 .owner = THIS_MODULE,
1071 .create = sco_sock_create,
1072};
1073
1074static struct hci_proto sco_hci_proto = {
1075 .name = "SCO",
1076 .id = HCI_PROTO_SCO,
1077 .connect_ind = sco_connect_ind,
1078 .connect_cfm = sco_connect_cfm,
Marcel Holtmann2950f212009-02-12 14:02:50 +01001079 .disconn_cfm = sco_disconn_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 .recv_scodata = sco_recv_scodata
1081};
1082
Gustavo F. Padovan64274512011-02-07 20:08:52 -02001083int __init sco_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084{
1085 int err;
1086
1087 err = proto_register(&sco_proto, 0);
1088 if (err < 0)
1089 return err;
1090
1091 err = bt_sock_register(BTPROTO_SCO, &sco_sock_family_ops);
1092 if (err < 0) {
1093 BT_ERR("SCO socket registration failed");
1094 goto error;
1095 }
1096
1097 err = hci_register_proto(&sco_hci_proto);
1098 if (err < 0) {
1099 BT_ERR("SCO protocol registration failed");
1100 bt_sock_unregister(BTPROTO_SCO);
1101 goto error;
1102 }
1103
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001104 if (bt_debugfs) {
1105 sco_debugfs = debugfs_create_file("sco", 0444,
1106 bt_debugfs, NULL, &sco_debugfs_fops);
1107 if (!sco_debugfs)
1108 BT_ERR("Failed to create SCO debug file");
1109 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 BT_INFO("SCO socket layer initialized");
1112
1113 return 0;
1114
1115error:
1116 proto_unregister(&sco_proto);
1117 return err;
1118}
1119
Gustavo F. Padovan64274512011-02-07 20:08:52 -02001120void __exit sco_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001122 debugfs_remove(sco_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123
1124 if (bt_sock_unregister(BTPROTO_SCO) < 0)
1125 BT_ERR("SCO socket unregistration failed");
1126
1127 if (hci_unregister_proto(&sco_hci_proto) < 0)
1128 BT_ERR("SCO protocol unregistration failed");
1129
1130 proto_unregister(&sco_proto);
1131}
1132
Marcel Holtmann7cb127d2008-07-14 20:13:53 +02001133module_param(disable_esco, bool, 0644);
1134MODULE_PARM_DESC(disable_esco, "Disable eSCO connection creation");