blob: 3170190f83c48c5943dab9da00f784ed0e143eb5 [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
Duy Truong790f06d2013-02-13 16:38:12 -08004 Copyright (c) 2011, The Linux Foundation. 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);
Nitin Srivastava744098c2012-12-10 14:14:56 +0530400 if (sco_pi(sk)->conn->hcon != NULL) {
401 hci_conn_put(sco_pi(sk)->conn->hcon);
402 sco_pi(sk)->conn->hcon = NULL;
403 }
Luiz Augusto von Dentz2e02b8612011-05-12 11:13:15 +0300404 } else
405 sco_chan_del(sk, ECONNRESET);
406 break;
407
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 case BT_CONNECT:
409 case BT_DISCONN:
410 sco_chan_del(sk, ECONNRESET);
411 break;
412
413 default:
414 sock_set_flag(sk, SOCK_ZAPPED);
415 break;
Stephen Hemminger3ff50b72007-04-20 17:09:22 -0700416 }
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +0200417}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +0200419/* Must be called on unlocked socket. */
420static void sco_sock_close(struct sock *sk)
421{
422 sco_sock_clear_timer(sk);
423 lock_sock(sk);
424 __sco_sock_close(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 sco_sock_kill(sk);
427}
428
429static void sco_sock_init(struct sock *sk, struct sock *parent)
430{
431 BT_DBG("sk %p", sk);
432
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900433 if (parent)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 sk->sk_type = parent->sk_type;
435}
436
437static struct proto sco_proto = {
438 .name = "SCO",
439 .owner = THIS_MODULE,
440 .obj_size = sizeof(struct sco_pinfo)
441};
442
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700443static struct sock *sco_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444{
445 struct sock *sk;
446
Pavel Emelyanov6257ff22007-11-01 00:39:31 -0700447 sk = sk_alloc(net, PF_BLUETOOTH, prio, &sco_proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 if (!sk)
449 return NULL;
450
451 sock_init_data(sock, sk);
452 INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
453
454 sk->sk_destruct = sco_sock_destruct;
455 sk->sk_sndtimeo = SCO_CONN_TIMEOUT;
456
457 sock_reset_flag(sk, SOCK_ZAPPED);
458
459 sk->sk_protocol = proto;
460 sk->sk_state = BT_OPEN;
461
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800462 setup_timer(&sk->sk_timer, sco_sock_timeout, (unsigned long)sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463
464 bt_sock_link(&sco_sk_list, sk);
465 return sk;
466}
467
Eric Paris3f378b62009-11-05 22:18:14 -0800468static int sco_sock_create(struct net *net, struct socket *sock, int protocol,
469 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470{
471 struct sock *sk;
472
473 BT_DBG("sock %p", sock);
474
475 sock->state = SS_UNCONNECTED;
476
477 if (sock->type != SOCK_SEQPACKET)
478 return -ESOCKTNOSUPPORT;
479
480 sock->ops = &sco_sock_ops;
481
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700482 sk = sco_sock_alloc(net, sock, protocol, GFP_ATOMIC);
Marcel Holtmann74da6262006-10-15 17:31:14 +0200483 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 return -ENOMEM;
485
486 sco_sock_init(sk, NULL);
487 return 0;
488}
489
Nick Pelly07021e22010-02-11 11:54:28 -0800490static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491{
Nick Pelly07021e22010-02-11 11:54:28 -0800492 struct sockaddr_sco sa;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 struct sock *sk = sock->sk;
Nick Pelly07021e22010-02-11 11:54:28 -0800494 bdaddr_t *src = &sa.sco_bdaddr;
495 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496
Nick Pelly07021e22010-02-11 11:54:28 -0800497 BT_DBG("sk %p %s", sk, batostr(&sa.sco_bdaddr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498
499 if (!addr || addr->sa_family != AF_BLUETOOTH)
500 return -EINVAL;
501
Nick Pelly07021e22010-02-11 11:54:28 -0800502 memset(&sa, 0, sizeof(sa));
503 len = min_t(unsigned int, sizeof(sa), alen);
504 memcpy(&sa, addr, len);
505
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 lock_sock(sk);
507
508 if (sk->sk_state != BT_OPEN) {
509 err = -EBADFD;
510 goto done;
511 }
512
513 write_lock_bh(&sco_sk_list.lock);
514
515 if (bacmp(src, BDADDR_ANY) && __sco_get_sock_by_addr(src)) {
516 err = -EADDRINUSE;
517 } else {
518 /* Save source address */
Nick Pelly07021e22010-02-11 11:54:28 -0800519 bacpy(&bt_sk(sk)->src, &sa.sco_bdaddr);
520 sco_pi(sk)->pkt_type = sa.sco_pkt_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 sk->sk_state = BT_BOUND;
522 }
523
524 write_unlock_bh(&sco_sk_list.lock);
525
526done:
527 release_sock(sk);
528 return err;
529}
530
531static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
532{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 struct sock *sk = sock->sk;
Nick Pelly07021e22010-02-11 11:54:28 -0800534 struct sockaddr_sco sa;
535 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
537 BT_DBG("sk %p", sk);
538
Nick Pelly07021e22010-02-11 11:54:28 -0800539 if (!addr || addr->sa_family != AF_BLUETOOTH)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 return -EINVAL;
541
Nick Pelly07021e22010-02-11 11:54:28 -0800542 memset(&sa, 0, sizeof(sa));
543 len = min_t(unsigned int, sizeof(sa), alen);
544 memcpy(&sa, addr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545
546 lock_sock(sk);
547
Nick Pelly07021e22010-02-11 11:54:28 -0800548 if (sk->sk_type != SOCK_SEQPACKET) {
549 err = -EINVAL;
550 goto done;
551 }
552
553 if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) {
554 err = -EBADFD;
555 goto done;
556 }
557
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 /* Set destination address and psm */
Nick Pelly07021e22010-02-11 11:54:28 -0800559 bacpy(&bt_sk(sk)->dst, &sa.sco_bdaddr);
560 sco_pi(sk)->pkt_type = sa.sco_pkt_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561
Kun Han Kim15b911f2011-07-08 09:30:28 -0700562 err = sco_connect(sk, sa.is_wbs);
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +0200563 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 goto done;
565
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900566 err = bt_sock_wait_state(sk, BT_CONNECTED,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 sock_sndtimeo(sk, flags & O_NONBLOCK));
568
569done:
570 release_sock(sk);
571 return err;
572}
573
574static int sco_sock_listen(struct socket *sock, int backlog)
575{
576 struct sock *sk = sock->sk;
577 int err = 0;
578
579 BT_DBG("sk %p backlog %d", sk, backlog);
580
581 lock_sock(sk);
582
583 if (sk->sk_state != BT_BOUND || sock->type != SOCK_SEQPACKET) {
584 err = -EBADFD;
585 goto done;
586 }
587
588 sk->sk_max_ack_backlog = backlog;
589 sk->sk_ack_backlog = 0;
590 sk->sk_state = BT_LISTEN;
591
592done:
593 release_sock(sk);
594 return err;
595}
596
597static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flags)
598{
599 DECLARE_WAITQUEUE(wait, current);
600 struct sock *sk = sock->sk, *ch;
601 long timeo;
602 int err = 0;
603
604 lock_sock(sk);
605
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700606 if (sk->sk_state != BT_LISTEN) {
607 err = -EBADFD;
608 goto done;
609 }
610
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
612
613 BT_DBG("sk %p timeo %ld", sk, timeo);
614
615 /* Wait for an incoming connection. (wake-one). */
Eric Dumazetaa395142010-04-20 13:03:51 +0000616 add_wait_queue_exclusive(sk_sleep(sk), &wait);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700617 while (!(ch = bt_accept_dequeue(sk, newsock))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 set_current_state(TASK_INTERRUPTIBLE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700619 if (!timeo) {
620 err = -EAGAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 break;
622 }
623
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700624 release_sock(sk);
625 timeo = schedule_timeout(timeo);
626 lock_sock(sk);
Peter Hurley552b0d32011-07-24 00:11:01 -0400627
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700628 if (sk->sk_state != BT_LISTEN) {
629 err = -EBADFD;
Peter Hurley552b0d32011-07-24 00:11:01 -0400630 break;
631 }
632
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 if (signal_pending(current)) {
634 err = sock_intr_errno(timeo);
635 break;
636 }
637 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700638 set_current_state(TASK_RUNNING);
Eric Dumazetaa395142010-04-20 13:03:51 +0000639 remove_wait_queue(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
641 if (err)
642 goto done;
643
644 newsock->state = SS_CONNECTED;
645
646 BT_DBG("new socket %p", ch);
647
648done:
649 release_sock(sk);
650 return err;
651}
652
653static int sco_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
654{
655 struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
656 struct sock *sk = sock->sk;
657
658 BT_DBG("sock %p, sk %p", sock, sk);
659
660 addr->sa_family = AF_BLUETOOTH;
661 *len = sizeof(struct sockaddr_sco);
662
663 if (peer)
664 bacpy(&sa->sco_bdaddr, &bt_sk(sk)->dst);
665 else
666 bacpy(&sa->sco_bdaddr, &bt_sk(sk)->src);
Nick Pelly07021e22010-02-11 11:54:28 -0800667 sa->sco_pkt_type = sco_pi(sk)->pkt_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668
669 return 0;
670}
671
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900672static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 struct msghdr *msg, size_t len)
674{
675 struct sock *sk = sock->sk;
Gustavo F. Padovanb9dbdbc2010-05-01 16:15:35 -0300676 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
678 BT_DBG("sock %p, sk %p", sock, sk);
679
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -0800680 err = sock_error(sk);
681 if (err)
682 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683
684 if (msg->msg_flags & MSG_OOB)
685 return -EOPNOTSUPP;
686
687 lock_sock(sk);
688
689 if (sk->sk_state == BT_CONNECTED)
690 err = sco_send_frame(sk, msg, len);
691 else
692 err = -ENOTCONN;
693
694 release_sock(sk);
695 return err;
696}
697
David S. Millerb7058842009-09-30 16:12:20 -0700698static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699{
700 struct sock *sk = sock->sk;
701 int err = 0;
702
703 BT_DBG("sk %p", sk);
704
705 lock_sock(sk);
706
707 switch (optname) {
708 default:
709 err = -ENOPROTOOPT;
710 break;
711 }
712
713 release_sock(sk);
714 return err;
715}
716
Marcel Holtmannd58daf42009-01-15 21:52:14 +0100717static int sco_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718{
719 struct sock *sk = sock->sk;
720 struct sco_options opts;
721 struct sco_conninfo cinfo;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900722 int len, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723
724 BT_DBG("sk %p", sk);
725
726 if (get_user(len, optlen))
727 return -EFAULT;
728
729 lock_sock(sk);
730
731 switch (optname) {
732 case SCO_OPTIONS:
733 if (sk->sk_state != BT_CONNECTED) {
734 err = -ENOTCONN;
735 break;
736 }
737
738 opts.mtu = sco_pi(sk)->conn->mtu;
739
740 BT_DBG("mtu %d", opts.mtu);
741
742 len = min_t(unsigned int, len, sizeof(opts));
743 if (copy_to_user(optval, (char *)&opts, len))
744 err = -EFAULT;
745
746 break;
747
748 case SCO_CONNINFO:
749 if (sk->sk_state != BT_CONNECTED) {
750 err = -ENOTCONN;
751 break;
752 }
753
Vasiliy Kulikovc4c896e2011-02-14 13:54:26 +0300754 memset(&cinfo, 0, sizeof(cinfo));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
756 memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
757
758 len = min_t(unsigned int, len, sizeof(cinfo));
759 if (copy_to_user(optval, (char *)&cinfo, len))
760 err = -EFAULT;
761
762 break;
763
764 default:
765 err = -ENOPROTOOPT;
766 break;
767 }
768
769 release_sock(sk);
770 return err;
771}
772
Marcel Holtmannd58daf42009-01-15 21:52:14 +0100773static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
774{
775 struct sock *sk = sock->sk;
776 int len, err = 0;
777
778 BT_DBG("sk %p", sk);
779
780 if (level == SOL_SCO)
781 return sco_sock_getsockopt_old(sock, optname, optval, optlen);
782
783 if (get_user(len, optlen))
784 return -EFAULT;
785
786 lock_sock(sk);
787
788 switch (optname) {
789 default:
790 err = -ENOPROTOOPT;
791 break;
792 }
793
794 release_sock(sk);
795 return err;
796}
797
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +0200798static int sco_sock_shutdown(struct socket *sock, int how)
799{
800 struct sock *sk = sock->sk;
801 int err = 0;
802
803 BT_DBG("sock %p, sk %p", sock, sk);
804
805 if (!sk)
806 return 0;
807
808 lock_sock(sk);
809 if (!sk->sk_shutdown) {
810 sk->sk_shutdown = SHUTDOWN_MASK;
811 sco_sock_clear_timer(sk);
812 __sco_sock_close(sk);
813
814 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
815 err = bt_sock_wait_state(sk, BT_CLOSED,
816 sk->sk_lingertime);
Srinivas Krovvidif7999962012-08-01 18:21:37 +0530817 else
818 err = bt_sock_wait_state(sk, BT_CLOSED,
819 SCO_DISCONN_TIMEOUT);
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +0200820 }
821 release_sock(sk);
822 return err;
823}
824
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825static int sco_sock_release(struct socket *sock)
826{
827 struct sock *sk = sock->sk;
828 int err = 0;
829
830 BT_DBG("sock %p, sk %p", sock, sk);
831
832 if (!sk)
833 return 0;
834
835 sco_sock_close(sk);
836
837 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) {
838 lock_sock(sk);
839 err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
840 release_sock(sk);
Srinivas Krovvidif7999962012-08-01 18:21:37 +0530841 } else {
842 lock_sock(sk);
843 err = bt_sock_wait_state(sk, BT_CLOSED,
844 SCO_DISCONN_TIMEOUT);
845 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 }
847
848 sock_orphan(sk);
849 sco_sock_kill(sk);
850 return err;
851}
852
853static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent)
854{
855 BT_DBG("conn %p", conn);
856
857 sco_pi(sk)->conn = conn;
858 conn->sk = sk;
859
860 if (parent)
861 bt_accept_enqueue(parent, sk);
862}
863
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900864/* Delete channel.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 * Must be called on the locked socket. */
866static void sco_chan_del(struct sock *sk, int err)
867{
868 struct sco_conn *conn;
869
870 conn = sco_pi(sk)->conn;
871
872 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
873
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900874 if (conn) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 sco_conn_lock(conn);
876 conn->sk = NULL;
877 sco_pi(sk)->conn = NULL;
878 sco_conn_unlock(conn);
Luiz Augusto von Dentz2e02b8612011-05-12 11:13:15 +0300879
880 if (conn->hcon)
881 hci_conn_put(conn->hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 }
883
884 sk->sk_state = BT_CLOSED;
885 sk->sk_err = err;
886 sk->sk_state_change(sk);
887
888 sock_set_flag(sk, SOCK_ZAPPED);
889}
890
891static void sco_conn_ready(struct sco_conn *conn)
892{
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +0200893 struct sock *parent;
894 struct sock *sk = conn->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895
896 BT_DBG("conn %p", conn);
897
898 sco_conn_lock(conn);
899
Andrei Emeltchenko735cbc42010-12-01 16:58:22 +0200900 if (sk) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 sco_sock_clear_timer(sk);
902 bh_lock_sock(sk);
903 sk->sk_state = BT_CONNECTED;
904 sk->sk_state_change(sk);
905 bh_unlock_sock(sk);
906 } else {
907 parent = sco_get_sock_listen(conn->src);
908 if (!parent)
909 goto done;
910
911 bh_lock_sock(parent);
912
Gustavo F. Padovanb9dbdbc2010-05-01 16:15:35 -0300913 sk = sco_sock_alloc(sock_net(parent), NULL,
914 BTPROTO_SCO, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 if (!sk) {
916 bh_unlock_sock(parent);
917 goto done;
918 }
919
920 sco_sock_init(sk, parent);
921
922 bacpy(&bt_sk(sk)->src, conn->src);
923 bacpy(&bt_sk(sk)->dst, conn->dst);
924
925 hci_conn_hold(conn->hcon);
926 __sco_chan_add(conn, sk, parent);
927
928 sk->sk_state = BT_CONNECTED;
929
930 /* Wake up parent */
931 parent->sk_data_ready(parent, 1);
932
933 bh_unlock_sock(parent);
934 }
935
936done:
937 sco_conn_unlock(conn);
938}
939
940/* ----- SCO interface with lower layer (HCI) ----- */
941static int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
942{
Marcel Holtmann71aeeaa2009-01-15 21:57:02 +0100943 register struct sock *sk;
944 struct hlist_node *node;
945 int lm = 0;
946
947 if (type != SCO_LINK && type != ESCO_LINK)
Mat Martineau8b51dd42012-02-13 10:38:24 -0800948 return 0;
Marcel Holtmann71aeeaa2009-01-15 21:57:02 +0100949
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
951
Marcel Holtmann71aeeaa2009-01-15 21:57:02 +0100952 /* Find listening sockets */
953 read_lock(&sco_sk_list.lock);
954 sk_for_each(sk, node, &sco_sk_list.head) {
955 if (sk->sk_state != BT_LISTEN)
956 continue;
957
958 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr) ||
959 !bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
960 lm |= HCI_LM_ACCEPT;
961 break;
962 }
963 }
964 read_unlock(&sco_sk_list.lock);
965
966 return lm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967}
968
969static int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
970{
971 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
972
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200973 if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
Gustavo F. Padovanc89ad732010-11-01 19:08:50 +0000974 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975
976 if (!status) {
977 struct sco_conn *conn;
978
979 conn = sco_conn_add(hcon, status);
980 if (conn)
981 sco_conn_ready(conn);
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900982 } else
Mat Martineau3b9239a2012-02-16 11:54:30 -0800983 sco_conn_del(hcon, bt_err(status), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984
985 return 0;
986}
987
Mat Martineau3b9239a2012-02-16 11:54:30 -0800988static int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason, __u8 is_process)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989{
990 BT_DBG("hcon %p reason %d", hcon, reason);
991
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200992 if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
Gustavo F. Padovanc89ad732010-11-01 19:08:50 +0000993 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994
Mat Martineau3b9239a2012-02-16 11:54:30 -0800995 sco_conn_del(hcon, bt_err(reason), is_process);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200996
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 return 0;
998}
999
1000static int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb)
1001{
1002 struct sco_conn *conn = hcon->sco_data;
1003
1004 if (!conn)
1005 goto drop;
1006
1007 BT_DBG("conn %p len %d", conn, skb->len);
1008
1009 if (skb->len) {
1010 sco_recv_frame(conn, skb);
1011 return 0;
1012 }
1013
1014drop:
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001015 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 return 0;
1017}
1018
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001019static int sco_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020{
1021 struct sock *sk;
1022 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023
1024 read_lock_bh(&sco_sk_list.lock);
1025
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08001026 sk_for_each(sk, node, &sco_sk_list.head) {
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001027 seq_printf(f, "%s %s %d\n", batostr(&bt_sk(sk)->src),
1028 batostr(&bt_sk(sk)->dst), sk->sk_state);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08001029 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 read_unlock_bh(&sco_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08001032
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001033 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034}
1035
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001036static int sco_debugfs_open(struct inode *inode, struct file *file)
1037{
1038 return single_open(file, sco_debugfs_show, inode->i_private);
1039}
1040
1041static const struct file_operations sco_debugfs_fops = {
1042 .open = sco_debugfs_open,
1043 .read = seq_read,
1044 .llseek = seq_lseek,
1045 .release = single_release,
1046};
1047
1048static struct dentry *sco_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049
Eric Dumazet90ddc4f2005-12-22 12:49:22 -08001050static const struct proto_ops sco_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 .family = PF_BLUETOOTH,
1052 .owner = THIS_MODULE,
1053 .release = sco_sock_release,
1054 .bind = sco_sock_bind,
1055 .connect = sco_sock_connect,
1056 .listen = sco_sock_listen,
1057 .accept = sco_sock_accept,
1058 .getname = sco_sock_getname,
1059 .sendmsg = sco_sock_sendmsg,
1060 .recvmsg = bt_sock_recvmsg,
1061 .poll = bt_sock_poll,
Marcel Holtmann3241ad82008-07-14 20:13:50 +02001062 .ioctl = bt_sock_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 .mmap = sock_no_mmap,
1064 .socketpair = sock_no_socketpair,
Marcel Holtmannfd0b3ff2009-06-16 00:01:49 +02001065 .shutdown = sco_sock_shutdown,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 .setsockopt = sco_sock_setsockopt,
1067 .getsockopt = sco_sock_getsockopt
1068};
1069
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +00001070static const struct net_proto_family sco_sock_family_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 .family = PF_BLUETOOTH,
1072 .owner = THIS_MODULE,
1073 .create = sco_sock_create,
1074};
1075
1076static struct hci_proto sco_hci_proto = {
1077 .name = "SCO",
1078 .id = HCI_PROTO_SCO,
1079 .connect_ind = sco_connect_ind,
1080 .connect_cfm = sco_connect_cfm,
Marcel Holtmann2950f212009-02-12 14:02:50 +01001081 .disconn_cfm = sco_disconn_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 .recv_scodata = sco_recv_scodata
1083};
1084
Gustavo F. Padovan64274512011-02-07 20:08:52 -02001085int __init sco_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086{
1087 int err;
1088
1089 err = proto_register(&sco_proto, 0);
1090 if (err < 0)
1091 return err;
1092
1093 err = bt_sock_register(BTPROTO_SCO, &sco_sock_family_ops);
1094 if (err < 0) {
1095 BT_ERR("SCO socket registration failed");
1096 goto error;
1097 }
1098
1099 err = hci_register_proto(&sco_hci_proto);
1100 if (err < 0) {
1101 BT_ERR("SCO protocol registration failed");
1102 bt_sock_unregister(BTPROTO_SCO);
1103 goto error;
1104 }
1105
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001106 if (bt_debugfs) {
1107 sco_debugfs = debugfs_create_file("sco", 0444,
1108 bt_debugfs, NULL, &sco_debugfs_fops);
1109 if (!sco_debugfs)
1110 BT_ERR("Failed to create SCO debug file");
1111 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 BT_INFO("SCO socket layer initialized");
1114
1115 return 0;
1116
1117error:
1118 proto_unregister(&sco_proto);
1119 return err;
1120}
1121
Gustavo F. Padovan64274512011-02-07 20:08:52 -02001122void __exit sco_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01001124 debugfs_remove(sco_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125
1126 if (bt_sock_unregister(BTPROTO_SCO) < 0)
1127 BT_ERR("SCO socket unregistration failed");
1128
1129 if (hci_unregister_proto(&sco_hci_proto) < 0)
1130 BT_ERR("SCO protocol unregistration failed");
1131
1132 proto_unregister(&sco_proto);
1133}
1134
Marcel Holtmann7cb127d2008-07-14 20:13:53 +02001135module_param(disable_esco, bool, 0644);
1136MODULE_PARM_DESC(disable_esco, "Disable eSCO connection creation");