blob: f7db5792ec648d3078d047cb46d0b269a68028bf [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>
Marcel Holtmann3241ad82008-07-14 20:13:50 +020028#include <asm/ioctls.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029
30#include <net/bluetooth/bluetooth.h>
31
Gustavo F. Padovan64274512011-02-07 20:08:52 -020032#define VERSION "2.16"
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
34/* Bluetooth sockets */
35#define BT_MAX_PROTO 8
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +000036static const struct net_proto_family *bt_proto[BT_MAX_PROTO];
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010037static DEFINE_RWLOCK(bt_proto_lock);
Dave Young68845cb2008-04-01 23:58:35 -070038
Dave Young68845cb2008-04-01 23:58:35 -070039static struct lock_class_key bt_lock_key[BT_MAX_PROTO];
Jan Engelhardt36cbd3d2009-08-05 10:42:58 -070040static const char *const bt_key_strings[BT_MAX_PROTO] = {
Dave Young68845cb2008-04-01 23:58:35 -070041 "sk_lock-AF_BLUETOOTH-BTPROTO_L2CAP",
42 "sk_lock-AF_BLUETOOTH-BTPROTO_HCI",
43 "sk_lock-AF_BLUETOOTH-BTPROTO_SCO",
44 "sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM",
45 "sk_lock-AF_BLUETOOTH-BTPROTO_BNEP",
46 "sk_lock-AF_BLUETOOTH-BTPROTO_CMTP",
47 "sk_lock-AF_BLUETOOTH-BTPROTO_HIDP",
48 "sk_lock-AF_BLUETOOTH-BTPROTO_AVDTP",
49};
50
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010051static struct lock_class_key bt_slock_key[BT_MAX_PROTO];
Jan Engelhardt36cbd3d2009-08-05 10:42:58 -070052static const char *const bt_slock_key_strings[BT_MAX_PROTO] = {
Dave Young68845cb2008-04-01 23:58:35 -070053 "slock-AF_BLUETOOTH-BTPROTO_L2CAP",
54 "slock-AF_BLUETOOTH-BTPROTO_HCI",
55 "slock-AF_BLUETOOTH-BTPROTO_SCO",
56 "slock-AF_BLUETOOTH-BTPROTO_RFCOMM",
57 "slock-AF_BLUETOOTH-BTPROTO_BNEP",
58 "slock-AF_BLUETOOTH-BTPROTO_CMTP",
59 "slock-AF_BLUETOOTH-BTPROTO_HIDP",
60 "slock-AF_BLUETOOTH-BTPROTO_AVDTP",
61};
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010062
Octavian Purdilab5a30dd2012-01-22 00:28:34 +020063void bt_sock_reclassify_lock(struct sock *sk, int proto)
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010064{
Octavian Purdilab5a30dd2012-01-22 00:28:34 +020065 BUG_ON(!sk);
Marcel Holtmanndb7aa1c2008-11-30 12:17:19 +010066 BUG_ON(sock_owned_by_user(sk));
67
68 sock_lock_init_class_and_name(sk,
69 bt_slock_key_strings[proto], &bt_slock_key[proto],
70 bt_key_strings[proto], &bt_lock_key[proto]);
71}
Octavian Purdilab5a30dd2012-01-22 00:28:34 +020072EXPORT_SYMBOL(bt_sock_reclassify_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070073
Stephen Hemmingerec1b4cf2009-10-05 05:58:39 +000074int bt_sock_register(int proto, const struct net_proto_family *ops)
Linus Torvalds1da177e2005-04-16 15:20:36 -070075{
Marcel Holtmann74da6262006-10-15 17:31:14 +020076 int err = 0;
77
Linus Torvalds1da177e2005-04-16 15:20:36 -070078 if (proto < 0 || proto >= BT_MAX_PROTO)
79 return -EINVAL;
80
Marcel Holtmann74da6262006-10-15 17:31:14 +020081 write_lock(&bt_proto_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070082
Marcel Holtmann74da6262006-10-15 17:31:14 +020083 if (bt_proto[proto])
84 err = -EEXIST;
85 else
86 bt_proto[proto] = ops;
87
88 write_unlock(&bt_proto_lock);
89
90 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -070091}
92EXPORT_SYMBOL(bt_sock_register);
93
94int bt_sock_unregister(int proto)
95{
Marcel Holtmann74da6262006-10-15 17:31:14 +020096 int err = 0;
97
Linus Torvalds1da177e2005-04-16 15:20:36 -070098 if (proto < 0 || proto >= BT_MAX_PROTO)
99 return -EINVAL;
100
Marcel Holtmann74da6262006-10-15 17:31:14 +0200101 write_lock(&bt_proto_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
Marcel Holtmann74da6262006-10-15 17:31:14 +0200103 if (!bt_proto[proto])
104 err = -ENOENT;
105 else
106 bt_proto[proto] = NULL;
107
108 write_unlock(&bt_proto_lock);
109
110 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111}
112EXPORT_SYMBOL(bt_sock_unregister);
113
Eric Paris3f378b62009-11-05 22:18:14 -0800114static int bt_sock_create(struct net *net, struct socket *sock, int proto,
115 int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116{
Marcel Holtmann74da6262006-10-15 17:31:14 +0200117 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118
Eric W. Biederman1b8d7ae2007-10-08 23:24:22 -0700119 if (net != &init_net)
120 return -EAFNOSUPPORT;
121
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 if (proto < 0 || proto >= BT_MAX_PROTO)
123 return -EINVAL;
124
Johannes Berg95a5afc2008-10-16 15:24:51 -0700125 if (!bt_proto[proto])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 request_module("bt-proto-%d", proto);
Marcel Holtmann74da6262006-10-15 17:31:14 +0200127
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 err = -EPROTONOSUPPORT;
Marcel Holtmann74da6262006-10-15 17:31:14 +0200129
130 read_lock(&bt_proto_lock);
131
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
Eric Paris3f378b62009-11-05 22:18:14 -0800133 err = bt_proto[proto]->create(net, sock, proto, kern);
Octavian Purdilab5a30dd2012-01-22 00:28:34 +0200134 if (!err)
135 bt_sock_reclassify_lock(sock->sk, proto);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 module_put(bt_proto[proto]->owner);
137 }
Marcel Holtmann74da6262006-10-15 17:31:14 +0200138
139 read_unlock(&bt_proto_lock);
140
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900141 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142}
143
144void bt_sock_link(struct bt_sock_list *l, struct sock *sk)
145{
Gustavo F. Padovan94f5bfb2011-12-27 15:28:48 -0200146 write_lock(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 sk_add_node(sk, &l->head);
Gustavo F. Padovan94f5bfb2011-12-27 15:28:48 -0200148 write_unlock(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149}
150EXPORT_SYMBOL(bt_sock_link);
151
152void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk)
153{
Gustavo F. Padovan94f5bfb2011-12-27 15:28:48 -0200154 write_lock(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 sk_del_node_init(sk);
Gustavo F. Padovan94f5bfb2011-12-27 15:28:48 -0200156 write_unlock(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157}
158EXPORT_SYMBOL(bt_sock_unlink);
159
160void bt_accept_enqueue(struct sock *parent, struct sock *sk)
161{
162 BT_DBG("parent %p, sk %p", parent, sk);
163
164 sock_hold(sk);
165 list_add_tail(&bt_sk(sk)->accept_q, &bt_sk(parent)->accept_q);
166 bt_sk(sk)->parent = parent;
167 parent->sk_ack_backlog++;
168}
169EXPORT_SYMBOL(bt_accept_enqueue);
170
171void bt_accept_unlink(struct sock *sk)
172{
173 BT_DBG("sk %p state %d", sk, sk->sk_state);
174
175 list_del_init(&bt_sk(sk)->accept_q);
176 bt_sk(sk)->parent->sk_ack_backlog--;
177 bt_sk(sk)->parent = NULL;
178 sock_put(sk);
179}
180EXPORT_SYMBOL(bt_accept_unlink);
181
182struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
183{
184 struct list_head *p, *n;
185 struct sock *sk;
186
187 BT_DBG("parent %p", parent);
188
189 list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
190 sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
191
Gustavo F. Padovan8a154a82011-12-20 17:15:56 -0200192 lock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193
194 /* FIXME: Is this check still needed */
195 if (sk->sk_state == BT_CLOSED) {
Gustavo F. Padovan8a154a82011-12-20 17:15:56 -0200196 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 bt_accept_unlink(sk);
198 continue;
199 }
200
Marcel Holtmannc4f912e2009-01-15 21:52:16 +0100201 if (sk->sk_state == BT_CONNECTED || !newsock ||
Vinicius Costa Gomesd0609912012-05-31 22:53:39 -0300202 test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 bt_accept_unlink(sk);
204 if (newsock)
205 sock_graft(sk, newsock);
Andrei Emeltchenkod37f50e2011-01-24 10:53:24 +0200206
Gustavo F. Padovan8a154a82011-12-20 17:15:56 -0200207 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 return sk;
209 }
210
Gustavo F. Padovan8a154a82011-12-20 17:15:56 -0200211 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 }
Andrei Emeltchenkod37f50e2011-01-24 10:53:24 +0200213
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 return NULL;
215}
216EXPORT_SYMBOL(bt_accept_dequeue);
217
218int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
Marcel Holtmannc4f912e2009-01-15 21:52:16 +0100219 struct msghdr *msg, size_t len, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220{
221 int noblock = flags & MSG_DONTWAIT;
222 struct sock *sk = sock->sk;
223 struct sk_buff *skb;
224 size_t copied;
225 int err;
226
Marcel Holtmanna418b892008-11-30 12:17:28 +0100227 BT_DBG("sock %p sk %p len %zu", sock, sk, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228
229 if (flags & (MSG_OOB))
230 return -EOPNOTSUPP;
231
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200232 skb = skb_recv_datagram(sk, flags, noblock, &err);
233 if (!skb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 if (sk->sk_shutdown & RCV_SHUTDOWN)
235 return 0;
236 return err;
237 }
238
239 msg->msg_namelen = 0;
240
241 copied = skb->len;
242 if (len < copied) {
243 msg->msg_flags |= MSG_TRUNC;
244 copied = len;
245 }
246
Arnaldo Carvalho de Melobadff6d2007-03-13 13:06:52 -0300247 skb_reset_transport_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200249 if (err == 0)
Neil Horman3b885782009-10-12 13:26:31 -0700250 sock_recv_ts_and_drops(msg, sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251
252 skb_free_datagram(sk, skb);
253
254 return err ? : copied;
255}
256EXPORT_SYMBOL(bt_sock_recvmsg);
257
Mat Martineau796c86e2010-09-08 10:05:27 -0700258static long bt_sock_data_wait(struct sock *sk, long timeo)
259{
260 DECLARE_WAITQUEUE(wait, current);
261
262 add_wait_queue(sk_sleep(sk), &wait);
263 for (;;) {
264 set_current_state(TASK_INTERRUPTIBLE);
265
266 if (!skb_queue_empty(&sk->sk_receive_queue))
267 break;
268
269 if (sk->sk_err || (sk->sk_shutdown & RCV_SHUTDOWN))
270 break;
271
272 if (signal_pending(current) || !timeo)
273 break;
274
275 set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
276 release_sock(sk);
277 timeo = schedule_timeout(timeo);
278 lock_sock(sk);
279 clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
280 }
281
282 __set_current_state(TASK_RUNNING);
283 remove_wait_queue(sk_sleep(sk), &wait);
284 return timeo;
285}
286
287int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
288 struct msghdr *msg, size_t size, int flags)
289{
290 struct sock *sk = sock->sk;
291 int err = 0;
292 size_t target, copied = 0;
293 long timeo;
294
295 if (flags & MSG_OOB)
296 return -EOPNOTSUPP;
297
298 msg->msg_namelen = 0;
299
300 BT_DBG("sk %p size %zu", sk, size);
301
302 lock_sock(sk);
303
304 target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
305 timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
306
307 do {
308 struct sk_buff *skb;
309 int chunk;
310
311 skb = skb_dequeue(&sk->sk_receive_queue);
312 if (!skb) {
313 if (copied >= target)
314 break;
315
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200316 err = sock_error(sk);
317 if (err)
Mat Martineau796c86e2010-09-08 10:05:27 -0700318 break;
319 if (sk->sk_shutdown & RCV_SHUTDOWN)
320 break;
321
322 err = -EAGAIN;
323 if (!timeo)
324 break;
325
326 timeo = bt_sock_data_wait(sk, timeo);
327
328 if (signal_pending(current)) {
329 err = sock_intr_errno(timeo);
330 goto out;
331 }
332 continue;
333 }
334
335 chunk = min_t(unsigned int, skb->len, size);
Mat Martineau5b668eb2011-07-22 14:53:59 -0700336 if (skb_copy_datagram_iovec(skb, 0, msg->msg_iov, chunk)) {
Mat Martineau796c86e2010-09-08 10:05:27 -0700337 skb_queue_head(&sk->sk_receive_queue, skb);
338 if (!copied)
339 copied = -EFAULT;
340 break;
341 }
342 copied += chunk;
343 size -= chunk;
344
345 sock_recv_ts_and_drops(msg, sk, skb);
346
347 if (!(flags & MSG_PEEK)) {
Mat Martineau5b668eb2011-07-22 14:53:59 -0700348 int skb_len = skb_headlen(skb);
349
350 if (chunk <= skb_len) {
351 __skb_pull(skb, chunk);
352 } else {
353 struct sk_buff *frag;
354
355 __skb_pull(skb, skb_len);
356 chunk -= skb_len;
357
358 skb_walk_frags(skb, frag) {
359 if (chunk <= frag->len) {
360 /* Pulling partial data */
361 skb->len -= chunk;
362 skb->data_len -= chunk;
363 __skb_pull(frag, chunk);
364 break;
365 } else if (frag->len) {
366 /* Pulling all frag data */
367 chunk -= frag->len;
368 skb->len -= frag->len;
369 skb->data_len -= frag->len;
370 __skb_pull(frag, frag->len);
371 }
372 }
373 }
374
Mat Martineau796c86e2010-09-08 10:05:27 -0700375 if (skb->len) {
376 skb_queue_head(&sk->sk_receive_queue, skb);
377 break;
378 }
379 kfree_skb(skb);
380
381 } else {
382 /* put message back and return */
383 skb_queue_head(&sk->sk_receive_queue, skb);
384 break;
385 }
386 } while (size);
387
388out:
389 release_sock(sk);
390 return copied ? : err;
391}
392EXPORT_SYMBOL(bt_sock_stream_recvmsg);
393
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394static inline unsigned int bt_accept_poll(struct sock *parent)
395{
396 struct list_head *p, *n;
397 struct sock *sk;
398
399 list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
400 sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
Marcel Holtmannd5f2d2b2009-02-16 02:57:30 +0100401 if (sk->sk_state == BT_CONNECTED ||
Gustavo Padovanc5daa682012-05-16 12:17:10 -0300402 (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags) &&
403 sk->sk_state == BT_CONNECT2))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404 return POLLIN | POLLRDNORM;
405 }
406
407 return 0;
408}
409
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300410unsigned int bt_sock_poll(struct file *file, struct socket *sock,
411 poll_table *wait)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412{
413 struct sock *sk = sock->sk;
414 unsigned int mask = 0;
415
416 BT_DBG("sock %p, sk %p", sock, sk);
417
Eric Dumazetaa395142010-04-20 13:03:51 +0000418 poll_wait(file, sk_sleep(sk), wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
420 if (sk->sk_state == BT_LISTEN)
421 return bt_accept_poll(sk);
422
423 if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
424 mask |= POLLERR;
425
Davide Libenzif348d702006-03-25 03:07:39 -0800426 if (sk->sk_shutdown & RCV_SHUTDOWN)
Eric Dumazetdb409802010-09-06 11:13:50 +0000427 mask |= POLLRDHUP | POLLIN | POLLRDNORM;
Davide Libenzif348d702006-03-25 03:07:39 -0800428
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 if (sk->sk_shutdown == SHUTDOWN_MASK)
430 mask |= POLLHUP;
431
Eric Dumazetdb409802010-09-06 11:13:50 +0000432 if (!skb_queue_empty(&sk->sk_receive_queue))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 mask |= POLLIN | POLLRDNORM;
434
435 if (sk->sk_state == BT_CLOSED)
436 mask |= POLLHUP;
437
438 if (sk->sk_state == BT_CONNECT ||
439 sk->sk_state == BT_CONNECT2 ||
440 sk->sk_state == BT_CONFIG)
441 return mask;
442
Gustavo Padovanc5daa682012-05-16 12:17:10 -0300443 if (!test_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags) && sock_writeable(sk))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
445 else
446 set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
447
448 return mask;
449}
450EXPORT_SYMBOL(bt_sock_poll);
451
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200452int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
453{
454 struct sock *sk = sock->sk;
Marcel Holtmann43cbeee2008-07-14 20:13:51 +0200455 struct sk_buff *skb;
456 long amount;
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200457 int err;
458
459 BT_DBG("sk %p cmd %x arg %lx", sk, cmd, arg);
460
461 switch (cmd) {
Marcel Holtmann43cbeee2008-07-14 20:13:51 +0200462 case TIOCOUTQ:
463 if (sk->sk_state == BT_LISTEN)
464 return -EINVAL;
465
Eric Dumazet31e6d362009-06-17 19:05:41 -0700466 amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
Marcel Holtmann43cbeee2008-07-14 20:13:51 +0200467 if (amount < 0)
468 amount = 0;
469 err = put_user(amount, (int __user *) arg);
470 break;
471
472 case TIOCINQ:
473 if (sk->sk_state == BT_LISTEN)
474 return -EINVAL;
475
476 lock_sock(sk);
477 skb = skb_peek(&sk->sk_receive_queue);
478 amount = skb ? skb->len : 0;
479 release_sock(sk);
480 err = put_user(amount, (int __user *) arg);
481 break;
482
Marcel Holtmann3241ad82008-07-14 20:13:50 +0200483 case SIOCGSTAMP:
484 err = sock_get_timestamp(sk, (struct timeval __user *) arg);
485 break;
486
487 case SIOCGSTAMPNS:
488 err = sock_get_timestampns(sk, (struct timespec __user *) arg);
489 break;
490
491 default:
492 err = -ENOIOCTLCMD;
493 break;
494 }
495
496 return err;
497}
498EXPORT_SYMBOL(bt_sock_ioctl);
499
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
501{
502 DECLARE_WAITQUEUE(wait, current);
503 int err = 0;
504
505 BT_DBG("sk %p", sk);
506
Eric Dumazetaa395142010-04-20 13:03:51 +0000507 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurley9be4e3f2011-07-24 00:10:46 -0400508 set_current_state(TASK_INTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 while (sk->sk_state != state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 if (!timeo) {
Marcel Holtmannb4c612a2006-09-23 09:54:38 +0200511 err = -EINPROGRESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 break;
513 }
514
515 if (signal_pending(current)) {
516 err = sock_intr_errno(timeo);
517 break;
518 }
519
520 release_sock(sk);
521 timeo = schedule_timeout(timeo);
522 lock_sock(sk);
Peter Hurley9be4e3f2011-07-24 00:10:46 -0400523 set_current_state(TASK_INTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524
Benjamin LaHaisec1cbe4b2005-12-13 23:22:19 -0800525 err = sock_error(sk);
526 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 }
Peter Hurley9be4e3f2011-07-24 00:10:46 -0400529 __set_current_state(TASK_RUNNING);
Eric Dumazetaa395142010-04-20 13:03:51 +0000530 remove_wait_queue(sk_sleep(sk), &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 return err;
532}
533EXPORT_SYMBOL(bt_sock_wait_state);
534
535static struct net_proto_family bt_sock_family_ops = {
536 .owner = THIS_MODULE,
537 .family = PF_BLUETOOTH,
538 .create = bt_sock_create,
539};
540
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541static int __init bt_init(void)
542{
Marcel Holtmann27d35282006-07-03 10:02:37 +0200543 int err;
544
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 BT_INFO("Core ver %s", VERSION);
546
Marcel Holtmann27d35282006-07-03 10:02:37 +0200547 err = bt_sysfs_init();
548 if (err < 0)
549 return err;
550
551 err = sock_register(&bt_sock_family_ops);
552 if (err < 0) {
553 bt_sysfs_cleanup();
554 return err;
555 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556
557 BT_INFO("HCI device and connection manager initialized");
558
Gustavo F. Padovan64274512011-02-07 20:08:52 -0200559 err = hci_sock_init();
560 if (err < 0)
561 goto error;
562
563 err = l2cap_init();
Anand Gadiyar0ed54da2011-02-22 12:43:26 +0530564 if (err < 0)
Gustavo F. Padovan64274512011-02-07 20:08:52 -0200565 goto sock_err;
Gustavo F. Padovan64274512011-02-07 20:08:52 -0200566
567 err = sco_init();
568 if (err < 0) {
569 l2cap_exit();
570 goto sock_err;
571 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572
573 return 0;
Gustavo F. Padovan64274512011-02-07 20:08:52 -0200574
575sock_err:
576 hci_sock_cleanup();
577
578error:
579 sock_unregister(PF_BLUETOOTH);
580 bt_sysfs_cleanup();
581
582 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583}
584
585static void __exit bt_exit(void)
586{
Gustavo F. Padovan64274512011-02-07 20:08:52 -0200587
588 sco_exit();
589
590 l2cap_exit();
591
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 hci_sock_cleanup();
593
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 sock_unregister(PF_BLUETOOTH);
Marcel Holtmann27d35282006-07-03 10:02:37 +0200595
596 bt_sysfs_cleanup();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597}
598
599subsys_initcall(bt_init);
600module_exit(bt_exit);
601
Marcel Holtmann63fbd242008-08-18 13:23:53 +0200602MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603MODULE_DESCRIPTION("Bluetooth Core ver " VERSION);
604MODULE_VERSION(VERSION);
605MODULE_LICENSE("GPL");
606MODULE_ALIAS_NETPROTO(PF_BLUETOOTH);