blob: e87d15da882489a682bb7433c0f7392bd01036db [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
4
5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090015 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090020 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth address family and sockets. */
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/module.h>
28
29#include <linux/types.h>
30#include <linux/list.h>
31#include <linux/errno.h>
32#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/sched.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/skbuff.h>
35#include <linux/init.h>
36#include <linux/poll.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <net/sock.h>
Marcel Holtmann3241ad82008-07-14 20:13:50 +020038#include <asm/ioctls.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <linux/kmod.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
41#include <net/bluetooth/bluetooth.h>
42
Robert Love8affb4e2008-10-15 15:35:44 -040043#ifdef CONFIG_ANDROID_PARANOID_NETWORK
44#include <linux/android_aid.h>
45#endif
46
47#ifndef CONFIG_BT_SOCK_DEBUG
48#undef BT_DBG
49#define BT_DBG(D...)
50#endif
51
Gustavo F. Padovan64274512011-02-07 20:08:52 -020052#define VERSION "2.16"
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
54/* Bluetooth sockets */
55#define BT_MAX_PROTO 8
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +000056static const struct net_proto_family *bt_proto[BT_MAX_PROTO];
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010057static DEFINE_RWLOCK(bt_proto_lock);
Dave Young68845cb2008-04-01 23:58:35 -070058
Dave Young68845cb2008-04-01 23:58:35 -070059static struct lock_class_key bt_lock_key[BT_MAX_PROTO];
Jan Engelhardt36cbd3d2009-08-05 10:42:58 -070060static const char *const bt_key_strings[BT_MAX_PROTO] = {
Dave Young68845cb2008-04-01 23:58:35 -070061 "sk_lock-AF_BLUETOOTH-BTPROTO_L2CAP",
62 "sk_lock-AF_BLUETOOTH-BTPROTO_HCI",
63 "sk_lock-AF_BLUETOOTH-BTPROTO_SCO",
64 "sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM",
65 "sk_lock-AF_BLUETOOTH-BTPROTO_BNEP",
66 "sk_lock-AF_BLUETOOTH-BTPROTO_CMTP",
67 "sk_lock-AF_BLUETOOTH-BTPROTO_HIDP",
68 "sk_lock-AF_BLUETOOTH-BTPROTO_AVDTP",
69};
70
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010071static struct lock_class_key bt_slock_key[BT_MAX_PROTO];
Jan Engelhardt36cbd3d2009-08-05 10:42:58 -070072static const char *const bt_slock_key_strings[BT_MAX_PROTO] = {
Dave Young68845cb2008-04-01 23:58:35 -070073 "slock-AF_BLUETOOTH-BTPROTO_L2CAP",
74 "slock-AF_BLUETOOTH-BTPROTO_HCI",
75 "slock-AF_BLUETOOTH-BTPROTO_SCO",
76 "slock-AF_BLUETOOTH-BTPROTO_RFCOMM",
77 "slock-AF_BLUETOOTH-BTPROTO_BNEP",
78 "slock-AF_BLUETOOTH-BTPROTO_CMTP",
79 "slock-AF_BLUETOOTH-BTPROTO_HIDP",
80 "slock-AF_BLUETOOTH-BTPROTO_AVDTP",
81};
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010082
83static inline void bt_sock_reclassify_lock(struct socket *sock, int proto)
84{
85 struct sock *sk = sock->sk;
86
87 if (!sk)
88 return;
89
90 BUG_ON(sock_owned_by_user(sk));
91
92 sock_lock_init_class_and_name(sk,
93 bt_slock_key_strings[proto], &bt_slock_key[proto],
94 bt_key_strings[proto], &bt_lock_key[proto]);
95}
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +000097int bt_sock_register(int proto, const struct net_proto_family *ops)
Linus Torvalds1da177e2005-04-16 15:20:36 -070098{
Marcel Holtmann74da6262006-10-15 17:31:14 +020099 int err = 0;
100
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101 if (proto < 0 || proto >= BT_MAX_PROTO)
102 return -EINVAL;
103
Marcel Holtmann74da6262006-10-15 17:31:14 +0200104 write_lock(&bt_proto_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
Marcel Holtmann74da6262006-10-15 17:31:14 +0200106 if (bt_proto[proto])
107 err = -EEXIST;
108 else
109 bt_proto[proto] = ops;
110
111 write_unlock(&bt_proto_lock);
112
113 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114}
115EXPORT_SYMBOL(bt_sock_register);
116
117int bt_sock_unregister(int proto)
118{
Marcel Holtmann74da6262006-10-15 17:31:14 +0200119 int err = 0;
120
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121 if (proto < 0 || proto >= BT_MAX_PROTO)
122 return -EINVAL;
123
Marcel Holtmann74da6262006-10-15 17:31:14 +0200124 write_lock(&bt_proto_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125
Marcel Holtmann74da6262006-10-15 17:31:14 +0200126 if (!bt_proto[proto])
127 err = -ENOENT;
128 else
129 bt_proto[proto] = NULL;
130
131 write_unlock(&bt_proto_lock);
132
133 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134}
135EXPORT_SYMBOL(bt_sock_unregister);
136
Robert Love8affb4e2008-10-15 15:35:44 -0400137#ifdef CONFIG_ANDROID_PARANOID_NETWORK
138static inline int current_has_bt_admin(void)
139{
140 return (!current_euid() || in_egroup_p(AID_NET_BT_ADMIN));
141}
142
143static inline int current_has_bt(void)
144{
145 return (current_has_bt_admin() || in_egroup_p(AID_NET_BT));
146}
147# else
148static inline int current_has_bt_admin(void)
149{
150 return 1;
151}
152
153static inline int current_has_bt(void)
154{
155 return 1;
156}
157#endif
158
Eric Paris3f378b62009-11-05 22:18:14 -0800159static int bt_sock_create(struct net *net, struct socket *sock, int proto,
160 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161{
Marcel Holtmann74da6262006-10-15 17:31:14 +0200162 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163
Robert Love8affb4e2008-10-15 15:35:44 -0400164 if (proto == BTPROTO_RFCOMM || proto == BTPROTO_SCO ||
165 proto == BTPROTO_L2CAP) {
166 if (!current_has_bt())
167 return -EPERM;
168 } else if (!current_has_bt_admin())
169 return -EPERM;
170
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700171 if (net != &init_net)
172 return -EAFNOSUPPORT;
173
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 if (proto < 0 || proto >= BT_MAX_PROTO)
175 return -EINVAL;
176
Johannes Berg95a5afc2008-10-16 15:24:51 -0700177 if (!bt_proto[proto])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 request_module("bt-proto-%d", proto);
Marcel Holtmann74da6262006-10-15 17:31:14 +0200179
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 err = -EPROTONOSUPPORT;
Marcel Holtmann74da6262006-10-15 17:31:14 +0200181
182 read_lock(&bt_proto_lock);
183
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
Eric Paris3f378b62009-11-05 22:18:14 -0800185 err = bt_proto[proto]->create(net, sock, proto, kern);
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +0100186 bt_sock_reclassify_lock(sock, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 module_put(bt_proto[proto]->owner);
188 }
Marcel Holtmann74da6262006-10-15 17:31:14 +0200189
190 read_unlock(&bt_proto_lock);
191
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900192 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193}
194
195void bt_sock_link(struct bt_sock_list *l, struct sock *sk)
196{
197 write_lock_bh(&l->lock);
198 sk_add_node(sk, &l->head);
199 write_unlock_bh(&l->lock);
200}
201EXPORT_SYMBOL(bt_sock_link);
202
203void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk)
204{
205 write_lock_bh(&l->lock);
206 sk_del_node_init(sk);
207 write_unlock_bh(&l->lock);
208}
209EXPORT_SYMBOL(bt_sock_unlink);
210
211void bt_accept_enqueue(struct sock *parent, struct sock *sk)
212{
213 BT_DBG("parent %p, sk %p", parent, sk);
214
215 sock_hold(sk);
216 list_add_tail(&bt_sk(sk)->accept_q, &bt_sk(parent)->accept_q);
217 bt_sk(sk)->parent = parent;
218 parent->sk_ack_backlog++;
219}
220EXPORT_SYMBOL(bt_accept_enqueue);
221
222void bt_accept_unlink(struct sock *sk)
223{
224 BT_DBG("sk %p state %d", sk, sk->sk_state);
225
226 list_del_init(&bt_sk(sk)->accept_q);
227 bt_sk(sk)->parent->sk_ack_backlog--;
228 bt_sk(sk)->parent = NULL;
229 sock_put(sk);
230}
231EXPORT_SYMBOL(bt_accept_unlink);
232
233struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
234{
235 struct list_head *p, *n;
236 struct sock *sk;
237
238 BT_DBG("parent %p", parent);
239
Andrei Emeltchenkod37f50e2011-01-24 10:53:24 +0200240 local_bh_disable();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
242 sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
243
Andrei Emeltchenkod37f50e2011-01-24 10:53:24 +0200244 bh_lock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245
246 /* FIXME: Is this check still needed */
247 if (sk->sk_state == BT_CLOSED) {
Andrei Emeltchenkod37f50e2011-01-24 10:53:24 +0200248 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 bt_accept_unlink(sk);
250 continue;
251 }
252
Marcel Holtmannc4f912e2009-01-15 21:52:16 +0100253 if (sk->sk_state == BT_CONNECTED || !newsock ||
254 bt_sk(parent)->defer_setup) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 bt_accept_unlink(sk);
256 if (newsock)
257 sock_graft(sk, newsock);
Andrei Emeltchenkod37f50e2011-01-24 10:53:24 +0200258
259 bh_unlock_sock(sk);
260 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 return sk;
262 }
263
Andrei Emeltchenkod37f50e2011-01-24 10:53:24 +0200264 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 }
Andrei Emeltchenkod37f50e2011-01-24 10:53:24 +0200266 local_bh_enable();
267
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 return NULL;
269}
270EXPORT_SYMBOL(bt_accept_dequeue);
271
272int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
Marcel Holtmannc4f912e2009-01-15 21:52:16 +0100273 struct msghdr *msg, size_t len, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274{
275 int noblock = flags & MSG_DONTWAIT;
276 struct sock *sk = sock->sk;
277 struct sk_buff *skb;
278 size_t copied;
279 int err;
280
Marcel Holtmanna418b892008-11-30 12:17:28 +0100281 BT_DBG("sock %p sk %p len %zu", sock, sk, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282
283 if (flags & (MSG_OOB))
284 return -EOPNOTSUPP;
285
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200286 skb = skb_recv_datagram(sk, flags, noblock, &err);
287 if (!skb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 if (sk->sk_shutdown & RCV_SHUTDOWN)
289 return 0;
290 return err;
291 }
292
293 msg->msg_namelen = 0;
294
295 copied = skb->len;
296 if (len < copied) {
297 msg->msg_flags |= MSG_TRUNC;
298 copied = len;
299 }
300
Arnaldo Carvalho de Melobadff6d2007-03-13 13:06:52 -0300301 skb_reset_transport_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200303 if (err == 0)
Neil Horman3b885782009-10-12 13:26:31 -0700304 sock_recv_ts_and_drops(msg, sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
306 skb_free_datagram(sk, skb);
307
308 return err ? : copied;
309}
310EXPORT_SYMBOL(bt_sock_recvmsg);
311
Mat Martineau796c86e2010-09-08 10:05:27 -0700312static long bt_sock_data_wait(struct sock *sk, long timeo)
313{
314 DECLARE_WAITQUEUE(wait, current);
315
316 add_wait_queue(sk_sleep(sk), &wait);
317 for (;;) {
318 set_current_state(TASK_INTERRUPTIBLE);
319
320 if (!skb_queue_empty(&sk->sk_receive_queue))
321 break;
322
323 if (sk->sk_err || (sk->sk_shutdown & RCV_SHUTDOWN))
324 break;
325
326 if (signal_pending(current) || !timeo)
327 break;
328
329 set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
330 release_sock(sk);
331 timeo = schedule_timeout(timeo);
332 lock_sock(sk);
333 clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
334 }
335
336 __set_current_state(TASK_RUNNING);
337 remove_wait_queue(sk_sleep(sk), &wait);
338 return timeo;
339}
340
341int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
342 struct msghdr *msg, size_t size, int flags)
343{
344 struct sock *sk = sock->sk;
345 int err = 0;
346 size_t target, copied = 0;
347 long timeo;
348
349 if (flags & MSG_OOB)
350 return -EOPNOTSUPP;
351
352 msg->msg_namelen = 0;
353
354 BT_DBG("sk %p size %zu", sk, size);
355
356 lock_sock(sk);
357
358 target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
359 timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
360
361 do {
362 struct sk_buff *skb;
363 int chunk;
364
365 skb = skb_dequeue(&sk->sk_receive_queue);
366 if (!skb) {
367 if (copied >= target)
368 break;
369
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200370 err = sock_error(sk);
371 if (err)
Mat Martineau796c86e2010-09-08 10:05:27 -0700372 break;
373 if (sk->sk_shutdown & RCV_SHUTDOWN)
374 break;
375
376 err = -EAGAIN;
377 if (!timeo)
378 break;
379
380 timeo = bt_sock_data_wait(sk, timeo);
381
382 if (signal_pending(current)) {
383 err = sock_intr_errno(timeo);
384 goto out;
385 }
386 continue;
387 }
388
389 chunk = min_t(unsigned int, skb->len, size);
390 if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
391 skb_queue_head(&sk->sk_receive_queue, skb);
392 if (!copied)
393 copied = -EFAULT;
394 break;
395 }
396 copied += chunk;
397 size -= chunk;
398
399 sock_recv_ts_and_drops(msg, sk, skb);
400
401 if (!(flags & MSG_PEEK)) {
402 skb_pull(skb, chunk);
403 if (skb->len) {
404 skb_queue_head(&sk->sk_receive_queue, skb);
405 break;
406 }
407 kfree_skb(skb);
408
409 } else {
410 /* put message back and return */
411 skb_queue_head(&sk->sk_receive_queue, skb);
412 break;
413 }
414 } while (size);
415
416out:
417 release_sock(sk);
418 return copied ? : err;
419}
420EXPORT_SYMBOL(bt_sock_stream_recvmsg);
421
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422static inline unsigned int bt_accept_poll(struct sock *parent)
423{
424 struct list_head *p, *n;
425 struct sock *sk;
426
427 list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
428 sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
Marcel Holtmannd5f2d2b2009-02-16 02:57:30 +0100429 if (sk->sk_state == BT_CONNECTED ||
430 (bt_sk(parent)->defer_setup &&
431 sk->sk_state == BT_CONNECT2))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 return POLLIN | POLLRDNORM;
433 }
434
435 return 0;
436}
437
Gustavo F. Padovan8ffd8782011-02-17 19:24:05 -0300438unsigned int bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439{
440 struct sock *sk = sock->sk;
441 unsigned int mask = 0;
442
443 BT_DBG("sock %p, sk %p", sock, sk);
444
Eric Dumazetaa395142010-04-20 13:03:51 +0000445 poll_wait(file, sk_sleep(sk), wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446
447 if (sk->sk_state == BT_LISTEN)
448 return bt_accept_poll(sk);
449
450 if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
451 mask |= POLLERR;
452
Davide Libenzif348d702006-03-25 03:07:39 -0800453 if (sk->sk_shutdown & RCV_SHUTDOWN)
Eric Dumazetdb409802010-09-06 11:13:50 +0000454 mask |= POLLRDHUP | POLLIN | POLLRDNORM;
Davide Libenzif348d702006-03-25 03:07:39 -0800455
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 if (sk->sk_shutdown == SHUTDOWN_MASK)
457 mask |= POLLHUP;
458
Eric Dumazetdb409802010-09-06 11:13:50 +0000459 if (!skb_queue_empty(&sk->sk_receive_queue))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 mask |= POLLIN | POLLRDNORM;
461
462 if (sk->sk_state == BT_CLOSED)
463 mask |= POLLHUP;
464
465 if (sk->sk_state == BT_CONNECT ||
466 sk->sk_state == BT_CONNECT2 ||
467 sk->sk_state == BT_CONFIG)
468 return mask;
469
470 if (sock_writeable(sk))
471 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
472 else
473 set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
474
475 return mask;
476}
477EXPORT_SYMBOL(bt_sock_poll);
478
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200479int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
480{
481 struct sock *sk = sock->sk;
Marcel Holtmann43cbeee2008-07-14 20:13:51 +0200482 struct sk_buff *skb;
483 long amount;
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200484 int err;
485
486 BT_DBG("sk %p cmd %x arg %lx", sk, cmd, arg);
487
488 switch (cmd) {
Marcel Holtmann43cbeee2008-07-14 20:13:51 +0200489 case TIOCOUTQ:
490 if (sk->sk_state == BT_LISTEN)
491 return -EINVAL;
492
Eric Dumazet31e6d362009-06-17 19:05:41 -0700493 amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
Marcel Holtmann43cbeee2008-07-14 20:13:51 +0200494 if (amount < 0)
495 amount = 0;
496 err = put_user(amount, (int __user *) arg);
497 break;
498
499 case TIOCINQ:
500 if (sk->sk_state == BT_LISTEN)
501 return -EINVAL;
502
503 lock_sock(sk);
504 skb = skb_peek(&sk->sk_receive_queue);
505 amount = skb ? skb->len : 0;
506 release_sock(sk);
507 err = put_user(amount, (int __user *) arg);
508 break;
509
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200510 case SIOCGSTAMP:
511 err = sock_get_timestamp(sk, (struct timeval __user *) arg);
512 break;
513
514 case SIOCGSTAMPNS:
515 err = sock_get_timestampns(sk, (struct timespec __user *) arg);
516 break;
517
518 default:
519 err = -ENOIOCTLCMD;
520 break;
521 }
522
523 return err;
524}
525EXPORT_SYMBOL(bt_sock_ioctl);
526
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
528{
529 DECLARE_WAITQUEUE(wait, current);
530 int err = 0;
531
532 BT_DBG("sk %p", sk);
533
Eric Dumazetaa395142010-04-20 13:03:51 +0000534 add_wait_queue(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 while (sk->sk_state != state) {
536 set_current_state(TASK_INTERRUPTIBLE);
537
538 if (!timeo) {
Marcel Holtmannb4c612a2006-09-23 09:54:38 +0200539 err = -EINPROGRESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 break;
541 }
542
543 if (signal_pending(current)) {
544 err = sock_intr_errno(timeo);
545 break;
546 }
547
548 release_sock(sk);
549 timeo = schedule_timeout(timeo);
550 lock_sock(sk);
551
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -0800552 err = sock_error(sk);
553 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 }
556 set_current_state(TASK_RUNNING);
Eric Dumazetaa395142010-04-20 13:03:51 +0000557 remove_wait_queue(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 return err;
559}
560EXPORT_SYMBOL(bt_sock_wait_state);
561
562static struct net_proto_family bt_sock_family_ops = {
563 .owner = THIS_MODULE,
564 .family = PF_BLUETOOTH,
565 .create = bt_sock_create,
566};
567
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568static int __init bt_init(void)
569{
Marcel Holtmann27d35282006-07-03 10:02:37 +0200570 int err;
571
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 BT_INFO("Core ver %s", VERSION);
573
Marcel Holtmann27d35282006-07-03 10:02:37 +0200574 err = bt_sysfs_init();
575 if (err < 0)
576 return err;
577
578 err = sock_register(&bt_sock_family_ops);
579 if (err < 0) {
580 bt_sysfs_cleanup();
581 return err;
582 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583
584 BT_INFO("HCI device and connection manager initialized");
585
Gustavo F. Padovan64274512011-02-07 20:08:52 -0200586 err = hci_sock_init();
587 if (err < 0)
588 goto error;
589
590 err = l2cap_init();
Anand Gadiyar0ed54da2011-02-22 12:43:26 +0530591 if (err < 0)
Gustavo F. Padovan64274512011-02-07 20:08:52 -0200592 goto sock_err;
Gustavo F. Padovan64274512011-02-07 20:08:52 -0200593
594 err = sco_init();
595 if (err < 0) {
596 l2cap_exit();
597 goto sock_err;
598 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599
600 return 0;
Gustavo F. Padovan64274512011-02-07 20:08:52 -0200601
602sock_err:
603 hci_sock_cleanup();
604
605error:
606 sock_unregister(PF_BLUETOOTH);
607 bt_sysfs_cleanup();
608
609 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610}
611
612static void __exit bt_exit(void)
613{
Gustavo F. Padovan64274512011-02-07 20:08:52 -0200614
615 sco_exit();
616
617 l2cap_exit();
618
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 hci_sock_cleanup();
620
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 sock_unregister(PF_BLUETOOTH);
Marcel Holtmann27d35282006-07-03 10:02:37 +0200622
623 bt_sysfs_cleanup();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624}
625
626subsys_initcall(bt_init);
627module_exit(bt_exit);
628
Marcel Holtmann63fbd242008-08-18 13:23:53 +0200629MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630MODULE_DESCRIPTION("Bluetooth Core ver " VERSION);
631MODULE_VERSION(VERSION);
632MODULE_LICENSE("GPL");
633MODULE_ALIAS_NETPROTO(PF_BLUETOOTH);