blob: ef92864ac6258b32ec600ad5791e19d399d0965b [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
Gustavo F. Padovan64274512011-02-07 20:08:52 -020043#define VERSION "2.16"
Linus Torvalds1da177e2005-04-16 15:20:36 -070044
45/* Bluetooth sockets */
46#define BT_MAX_PROTO 8
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +000047static const struct net_proto_family *bt_proto[BT_MAX_PROTO];
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010048static DEFINE_RWLOCK(bt_proto_lock);
Dave Young68845cb2008-04-01 23:58:35 -070049
Dave Young68845cb2008-04-01 23:58:35 -070050static struct lock_class_key bt_lock_key[BT_MAX_PROTO];
Jan Engelhardt36cbd3d2009-08-05 10:42:58 -070051static const char *const bt_key_strings[BT_MAX_PROTO] = {
Dave Young68845cb2008-04-01 23:58:35 -070052 "sk_lock-AF_BLUETOOTH-BTPROTO_L2CAP",
53 "sk_lock-AF_BLUETOOTH-BTPROTO_HCI",
54 "sk_lock-AF_BLUETOOTH-BTPROTO_SCO",
55 "sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM",
56 "sk_lock-AF_BLUETOOTH-BTPROTO_BNEP",
57 "sk_lock-AF_BLUETOOTH-BTPROTO_CMTP",
58 "sk_lock-AF_BLUETOOTH-BTPROTO_HIDP",
59 "sk_lock-AF_BLUETOOTH-BTPROTO_AVDTP",
60};
61
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010062static struct lock_class_key bt_slock_key[BT_MAX_PROTO];
Jan Engelhardt36cbd3d2009-08-05 10:42:58 -070063static const char *const bt_slock_key_strings[BT_MAX_PROTO] = {
Dave Young68845cb2008-04-01 23:58:35 -070064 "slock-AF_BLUETOOTH-BTPROTO_L2CAP",
65 "slock-AF_BLUETOOTH-BTPROTO_HCI",
66 "slock-AF_BLUETOOTH-BTPROTO_SCO",
67 "slock-AF_BLUETOOTH-BTPROTO_RFCOMM",
68 "slock-AF_BLUETOOTH-BTPROTO_BNEP",
69 "slock-AF_BLUETOOTH-BTPROTO_CMTP",
70 "slock-AF_BLUETOOTH-BTPROTO_HIDP",
71 "slock-AF_BLUETOOTH-BTPROTO_AVDTP",
72};
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010073
74static inline void bt_sock_reclassify_lock(struct socket *sock, int proto)
75{
76 struct sock *sk = sock->sk;
77
78 if (!sk)
79 return;
80
81 BUG_ON(sock_owned_by_user(sk));
82
83 sock_lock_init_class_and_name(sk,
84 bt_slock_key_strings[proto], &bt_slock_key[proto],
85 bt_key_strings[proto], &bt_lock_key[proto]);
86}
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +000088int bt_sock_register(int proto, const struct net_proto_family *ops)
Linus Torvalds1da177e2005-04-16 15:20:36 -070089{
Marcel Holtmann74da6262006-10-15 17:31:14 +020090 int err = 0;
91
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 if (proto < 0 || proto >= BT_MAX_PROTO)
93 return -EINVAL;
94
Marcel Holtmann74da6262006-10-15 17:31:14 +020095 write_lock(&bt_proto_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
Marcel Holtmann74da6262006-10-15 17:31:14 +020097 if (bt_proto[proto])
98 err = -EEXIST;
99 else
100 bt_proto[proto] = ops;
101
102 write_unlock(&bt_proto_lock);
103
104 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105}
106EXPORT_SYMBOL(bt_sock_register);
107
108int bt_sock_unregister(int proto)
109{
Marcel Holtmann74da6262006-10-15 17:31:14 +0200110 int err = 0;
111
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 if (proto < 0 || proto >= BT_MAX_PROTO)
113 return -EINVAL;
114
Marcel Holtmann74da6262006-10-15 17:31:14 +0200115 write_lock(&bt_proto_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116
Marcel Holtmann74da6262006-10-15 17:31:14 +0200117 if (!bt_proto[proto])
118 err = -ENOENT;
119 else
120 bt_proto[proto] = NULL;
121
122 write_unlock(&bt_proto_lock);
123
124 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125}
126EXPORT_SYMBOL(bt_sock_unregister);
127
Eric Paris3f378b62009-11-05 22:18:14 -0800128static int bt_sock_create(struct net *net, struct socket *sock, int proto,
129 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130{
Marcel Holtmann74da6262006-10-15 17:31:14 +0200131 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700133 if (net != &init_net)
134 return -EAFNOSUPPORT;
135
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 if (proto < 0 || proto >= BT_MAX_PROTO)
137 return -EINVAL;
138
Johannes Berg95a5afc2008-10-16 15:24:51 -0700139 if (!bt_proto[proto])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 request_module("bt-proto-%d", proto);
Marcel Holtmann74da6262006-10-15 17:31:14 +0200141
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 err = -EPROTONOSUPPORT;
Marcel Holtmann74da6262006-10-15 17:31:14 +0200143
144 read_lock(&bt_proto_lock);
145
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
Eric Paris3f378b62009-11-05 22:18:14 -0800147 err = bt_proto[proto]->create(net, sock, proto, kern);
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +0100148 bt_sock_reclassify_lock(sock, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 module_put(bt_proto[proto]->owner);
150 }
Marcel Holtmann74da6262006-10-15 17:31:14 +0200151
152 read_unlock(&bt_proto_lock);
153
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900154 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155}
156
157void bt_sock_link(struct bt_sock_list *l, struct sock *sk)
158{
Gustavo F. Padovan94f5bfb2011-12-27 15:28:48 -0200159 write_lock(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 sk_add_node(sk, &l->head);
Gustavo F. Padovan94f5bfb2011-12-27 15:28:48 -0200161 write_unlock(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162}
163EXPORT_SYMBOL(bt_sock_link);
164
165void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk)
166{
Gustavo F. Padovan94f5bfb2011-12-27 15:28:48 -0200167 write_lock(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 sk_del_node_init(sk);
Gustavo F. Padovan94f5bfb2011-12-27 15:28:48 -0200169 write_unlock(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170}
171EXPORT_SYMBOL(bt_sock_unlink);
172
173void bt_accept_enqueue(struct sock *parent, struct sock *sk)
174{
175 BT_DBG("parent %p, sk %p", parent, sk);
176
177 sock_hold(sk);
178 list_add_tail(&bt_sk(sk)->accept_q, &bt_sk(parent)->accept_q);
179 bt_sk(sk)->parent = parent;
180 parent->sk_ack_backlog++;
181}
182EXPORT_SYMBOL(bt_accept_enqueue);
183
184void bt_accept_unlink(struct sock *sk)
185{
186 BT_DBG("sk %p state %d", sk, sk->sk_state);
187
188 list_del_init(&bt_sk(sk)->accept_q);
189 bt_sk(sk)->parent->sk_ack_backlog--;
190 bt_sk(sk)->parent = NULL;
191 sock_put(sk);
192}
193EXPORT_SYMBOL(bt_accept_unlink);
194
195struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
196{
197 struct list_head *p, *n;
198 struct sock *sk;
199
200 BT_DBG("parent %p", parent);
201
202 list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
203 sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
204
Gustavo F. Padovan8a154a82011-12-20 17:15:56 -0200205 lock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206
207 /* FIXME: Is this check still needed */
208 if (sk->sk_state == BT_CLOSED) {
Gustavo F. Padovan8a154a82011-12-20 17:15:56 -0200209 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 bt_accept_unlink(sk);
211 continue;
212 }
213
Marcel Holtmannc4f912e2009-01-15 21:52:16 +0100214 if (sk->sk_state == BT_CONNECTED || !newsock ||
215 bt_sk(parent)->defer_setup) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 bt_accept_unlink(sk);
217 if (newsock)
218 sock_graft(sk, newsock);
Andrei Emeltchenkod37f50e2011-01-24 10:53:24 +0200219
Gustavo F. Padovan8a154a82011-12-20 17:15:56 -0200220 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 return sk;
222 }
223
Gustavo F. Padovan8a154a82011-12-20 17:15:56 -0200224 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 }
Andrei Emeltchenkod37f50e2011-01-24 10:53:24 +0200226
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 return NULL;
228}
229EXPORT_SYMBOL(bt_accept_dequeue);
230
231int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
Marcel Holtmannc4f912e2009-01-15 21:52:16 +0100232 struct msghdr *msg, size_t len, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233{
234 int noblock = flags & MSG_DONTWAIT;
235 struct sock *sk = sock->sk;
236 struct sk_buff *skb;
237 size_t copied;
238 int err;
239
Marcel Holtmanna418b892008-11-30 12:17:28 +0100240 BT_DBG("sock %p sk %p len %zu", sock, sk, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241
242 if (flags & (MSG_OOB))
243 return -EOPNOTSUPP;
244
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200245 skb = skb_recv_datagram(sk, flags, noblock, &err);
246 if (!skb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 if (sk->sk_shutdown & RCV_SHUTDOWN)
248 return 0;
249 return err;
250 }
251
252 msg->msg_namelen = 0;
253
254 copied = skb->len;
255 if (len < copied) {
256 msg->msg_flags |= MSG_TRUNC;
257 copied = len;
258 }
259
Arnaldo Carvalho de Melobadff6d2007-03-13 13:06:52 -0300260 skb_reset_transport_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200262 if (err == 0)
Neil Horman3b885782009-10-12 13:26:31 -0700263 sock_recv_ts_and_drops(msg, sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264
265 skb_free_datagram(sk, skb);
266
267 return err ? : copied;
268}
269EXPORT_SYMBOL(bt_sock_recvmsg);
270
Mat Martineau796c86e2010-09-08 10:05:27 -0700271static long bt_sock_data_wait(struct sock *sk, long timeo)
272{
273 DECLARE_WAITQUEUE(wait, current);
274
275 add_wait_queue(sk_sleep(sk), &wait);
276 for (;;) {
277 set_current_state(TASK_INTERRUPTIBLE);
278
279 if (!skb_queue_empty(&sk->sk_receive_queue))
280 break;
281
282 if (sk->sk_err || (sk->sk_shutdown & RCV_SHUTDOWN))
283 break;
284
285 if (signal_pending(current) || !timeo)
286 break;
287
288 set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
289 release_sock(sk);
290 timeo = schedule_timeout(timeo);
291 lock_sock(sk);
292 clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
293 }
294
295 __set_current_state(TASK_RUNNING);
296 remove_wait_queue(sk_sleep(sk), &wait);
297 return timeo;
298}
299
300int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
301 struct msghdr *msg, size_t size, int flags)
302{
303 struct sock *sk = sock->sk;
304 int err = 0;
305 size_t target, copied = 0;
306 long timeo;
307
308 if (flags & MSG_OOB)
309 return -EOPNOTSUPP;
310
311 msg->msg_namelen = 0;
312
313 BT_DBG("sk %p size %zu", sk, size);
314
315 lock_sock(sk);
316
317 target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
318 timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
319
320 do {
321 struct sk_buff *skb;
322 int chunk;
323
324 skb = skb_dequeue(&sk->sk_receive_queue);
325 if (!skb) {
326 if (copied >= target)
327 break;
328
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200329 err = sock_error(sk);
330 if (err)
Mat Martineau796c86e2010-09-08 10:05:27 -0700331 break;
332 if (sk->sk_shutdown & RCV_SHUTDOWN)
333 break;
334
335 err = -EAGAIN;
336 if (!timeo)
337 break;
338
339 timeo = bt_sock_data_wait(sk, timeo);
340
341 if (signal_pending(current)) {
342 err = sock_intr_errno(timeo);
343 goto out;
344 }
345 continue;
346 }
347
348 chunk = min_t(unsigned int, skb->len, size);
Mat Martineau5b668eb2011-07-22 14:53:59 -0700349 if (skb_copy_datagram_iovec(skb, 0, msg->msg_iov, chunk)) {
Mat Martineau796c86e2010-09-08 10:05:27 -0700350 skb_queue_head(&sk->sk_receive_queue, skb);
351 if (!copied)
352 copied = -EFAULT;
353 break;
354 }
355 copied += chunk;
356 size -= chunk;
357
358 sock_recv_ts_and_drops(msg, sk, skb);
359
360 if (!(flags & MSG_PEEK)) {
Mat Martineau5b668eb2011-07-22 14:53:59 -0700361 int skb_len = skb_headlen(skb);
362
363 if (chunk <= skb_len) {
364 __skb_pull(skb, chunk);
365 } else {
366 struct sk_buff *frag;
367
368 __skb_pull(skb, skb_len);
369 chunk -= skb_len;
370
371 skb_walk_frags(skb, frag) {
372 if (chunk <= frag->len) {
373 /* Pulling partial data */
374 skb->len -= chunk;
375 skb->data_len -= chunk;
376 __skb_pull(frag, chunk);
377 break;
378 } else if (frag->len) {
379 /* Pulling all frag data */
380 chunk -= frag->len;
381 skb->len -= frag->len;
382 skb->data_len -= frag->len;
383 __skb_pull(frag, frag->len);
384 }
385 }
386 }
387
Mat Martineau796c86e2010-09-08 10:05:27 -0700388 if (skb->len) {
389 skb_queue_head(&sk->sk_receive_queue, skb);
390 break;
391 }
392 kfree_skb(skb);
393
394 } else {
395 /* put message back and return */
396 skb_queue_head(&sk->sk_receive_queue, skb);
397 break;
398 }
399 } while (size);
400
401out:
402 release_sock(sk);
403 return copied ? : err;
404}
405EXPORT_SYMBOL(bt_sock_stream_recvmsg);
406
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407static inline unsigned int bt_accept_poll(struct sock *parent)
408{
409 struct list_head *p, *n;
410 struct sock *sk;
411
412 list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
413 sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
Marcel Holtmannd5f2d2b2009-02-16 02:57:30 +0100414 if (sk->sk_state == BT_CONNECTED ||
415 (bt_sk(parent)->defer_setup &&
416 sk->sk_state == BT_CONNECT2))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 return POLLIN | POLLRDNORM;
418 }
419
420 return 0;
421}
422
Gustavo F. Padovan8ffd8782011-02-17 19:24:05 -0300423unsigned int bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424{
425 struct sock *sk = sock->sk;
426 unsigned int mask = 0;
427
428 BT_DBG("sock %p, sk %p", sock, sk);
429
Eric Dumazetaa395142010-04-20 13:03:51 +0000430 poll_wait(file, sk_sleep(sk), wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431
432 if (sk->sk_state == BT_LISTEN)
433 return bt_accept_poll(sk);
434
435 if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
436 mask |= POLLERR;
437
Davide Libenzif348d702006-03-25 03:07:39 -0800438 if (sk->sk_shutdown & RCV_SHUTDOWN)
Eric Dumazetdb409802010-09-06 11:13:50 +0000439 mask |= POLLRDHUP | POLLIN | POLLRDNORM;
Davide Libenzif348d702006-03-25 03:07:39 -0800440
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 if (sk->sk_shutdown == SHUTDOWN_MASK)
442 mask |= POLLHUP;
443
Eric Dumazetdb409802010-09-06 11:13:50 +0000444 if (!skb_queue_empty(&sk->sk_receive_queue))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 mask |= POLLIN | POLLRDNORM;
446
447 if (sk->sk_state == BT_CLOSED)
448 mask |= POLLHUP;
449
450 if (sk->sk_state == BT_CONNECT ||
451 sk->sk_state == BT_CONNECT2 ||
452 sk->sk_state == BT_CONFIG)
453 return mask;
454
455 if (sock_writeable(sk))
456 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
457 else
458 set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
459
460 return mask;
461}
462EXPORT_SYMBOL(bt_sock_poll);
463
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200464int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
465{
466 struct sock *sk = sock->sk;
Marcel Holtmann43cbeee2008-07-14 20:13:51 +0200467 struct sk_buff *skb;
468 long amount;
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200469 int err;
470
471 BT_DBG("sk %p cmd %x arg %lx", sk, cmd, arg);
472
473 switch (cmd) {
Marcel Holtmann43cbeee2008-07-14 20:13:51 +0200474 case TIOCOUTQ:
475 if (sk->sk_state == BT_LISTEN)
476 return -EINVAL;
477
Eric Dumazet31e6d362009-06-17 19:05:41 -0700478 amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
Marcel Holtmann43cbeee2008-07-14 20:13:51 +0200479 if (amount < 0)
480 amount = 0;
481 err = put_user(amount, (int __user *) arg);
482 break;
483
484 case TIOCINQ:
485 if (sk->sk_state == BT_LISTEN)
486 return -EINVAL;
487
488 lock_sock(sk);
489 skb = skb_peek(&sk->sk_receive_queue);
490 amount = skb ? skb->len : 0;
491 release_sock(sk);
492 err = put_user(amount, (int __user *) arg);
493 break;
494
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200495 case SIOCGSTAMP:
496 err = sock_get_timestamp(sk, (struct timeval __user *) arg);
497 break;
498
499 case SIOCGSTAMPNS:
500 err = sock_get_timestampns(sk, (struct timespec __user *) arg);
501 break;
502
503 default:
504 err = -ENOIOCTLCMD;
505 break;
506 }
507
508 return err;
509}
510EXPORT_SYMBOL(bt_sock_ioctl);
511
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
513{
514 DECLARE_WAITQUEUE(wait, current);
515 int err = 0;
516
517 BT_DBG("sk %p", sk);
518
Eric Dumazetaa395142010-04-20 13:03:51 +0000519 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurley9be4e3f2011-07-24 00:10:46 -0400520 set_current_state(TASK_INTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 while (sk->sk_state != state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 if (!timeo) {
Marcel Holtmannb4c612a2006-09-23 09:54:38 +0200523 err = -EINPROGRESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 break;
525 }
526
527 if (signal_pending(current)) {
528 err = sock_intr_errno(timeo);
529 break;
530 }
531
532 release_sock(sk);
533 timeo = schedule_timeout(timeo);
534 lock_sock(sk);
Peter Hurley9be4e3f2011-07-24 00:10:46 -0400535 set_current_state(TASK_INTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -0800537 err = sock_error(sk);
538 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 }
Peter Hurley9be4e3f2011-07-24 00:10:46 -0400541 __set_current_state(TASK_RUNNING);
Eric Dumazetaa395142010-04-20 13:03:51 +0000542 remove_wait_queue(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 return err;
544}
545EXPORT_SYMBOL(bt_sock_wait_state);
546
547static struct net_proto_family bt_sock_family_ops = {
548 .owner = THIS_MODULE,
549 .family = PF_BLUETOOTH,
550 .create = bt_sock_create,
551};
552
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553static int __init bt_init(void)
554{
Marcel Holtmann27d35282006-07-03 10:02:37 +0200555 int err;
556
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 BT_INFO("Core ver %s", VERSION);
558
Marcel Holtmann27d35282006-07-03 10:02:37 +0200559 err = bt_sysfs_init();
560 if (err < 0)
561 return err;
562
563 err = sock_register(&bt_sock_family_ops);
564 if (err < 0) {
565 bt_sysfs_cleanup();
566 return err;
567 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568
569 BT_INFO("HCI device and connection manager initialized");
570
Gustavo F. Padovan64274512011-02-07 20:08:52 -0200571 err = hci_sock_init();
572 if (err < 0)
573 goto error;
574
575 err = l2cap_init();
Anand Gadiyar0ed54da2011-02-22 12:43:26 +0530576 if (err < 0)
Gustavo F. Padovan64274512011-02-07 20:08:52 -0200577 goto sock_err;
Gustavo F. Padovan64274512011-02-07 20:08:52 -0200578
579 err = sco_init();
580 if (err < 0) {
581 l2cap_exit();
582 goto sock_err;
583 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584
585 return 0;
Gustavo F. Padovan64274512011-02-07 20:08:52 -0200586
587sock_err:
588 hci_sock_cleanup();
589
590error:
591 sock_unregister(PF_BLUETOOTH);
592 bt_sysfs_cleanup();
593
594 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595}
596
597static void __exit bt_exit(void)
598{
Gustavo F. Padovan64274512011-02-07 20:08:52 -0200599
600 sco_exit();
601
602 l2cap_exit();
603
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 hci_sock_cleanup();
605
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 sock_unregister(PF_BLUETOOTH);
Marcel Holtmann27d35282006-07-03 10:02:37 +0200607
608 bt_sysfs_cleanup();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609}
610
611subsys_initcall(bt_init);
612module_exit(bt_exit);
613
Marcel Holtmann63fbd242008-08-18 13:23:53 +0200614MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615MODULE_DESCRIPTION("Bluetooth Core ver " VERSION);
616MODULE_VERSION(VERSION);
617MODULE_LICENSE("GPL");
618MODULE_ALIAS_NETPROTO(PF_BLUETOOTH);