net: add option to enable error queue packets waking select
[deliverable/linux.git] / net / bluetooth / af_bluetooth.c
CommitLineData
8e87d142 1/*
1da177e4
LT
2 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
8e87d142
YH
15 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
1da177e4
LT
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
8e87d142
YH
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
1da177e4
LT
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth address family and sockets. */
26
1da177e4 27#include <linux/module.h>
3241ad82 28#include <asm/ioctls.h>
1da177e4
LT
29
30#include <net/bluetooth/bluetooth.h>
256a06c8 31#include <linux/proc_fs.h>
1da177e4 32
64274518 33#define VERSION "2.16"
1da177e4
LT
34
35/* Bluetooth sockets */
36#define BT_MAX_PROTO 8
ec1b4cf7 37static const struct net_proto_family *bt_proto[BT_MAX_PROTO];
db7aa1c2 38static DEFINE_RWLOCK(bt_proto_lock);
68845cb2 39
68845cb2 40static struct lock_class_key bt_lock_key[BT_MAX_PROTO];
36cbd3dc 41static const char *const bt_key_strings[BT_MAX_PROTO] = {
68845cb2
DY
42 "sk_lock-AF_BLUETOOTH-BTPROTO_L2CAP",
43 "sk_lock-AF_BLUETOOTH-BTPROTO_HCI",
44 "sk_lock-AF_BLUETOOTH-BTPROTO_SCO",
45 "sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM",
46 "sk_lock-AF_BLUETOOTH-BTPROTO_BNEP",
47 "sk_lock-AF_BLUETOOTH-BTPROTO_CMTP",
48 "sk_lock-AF_BLUETOOTH-BTPROTO_HIDP",
49 "sk_lock-AF_BLUETOOTH-BTPROTO_AVDTP",
50};
51
db7aa1c2 52static struct lock_class_key bt_slock_key[BT_MAX_PROTO];
36cbd3dc 53static const char *const bt_slock_key_strings[BT_MAX_PROTO] = {
68845cb2
DY
54 "slock-AF_BLUETOOTH-BTPROTO_L2CAP",
55 "slock-AF_BLUETOOTH-BTPROTO_HCI",
56 "slock-AF_BLUETOOTH-BTPROTO_SCO",
57 "slock-AF_BLUETOOTH-BTPROTO_RFCOMM",
58 "slock-AF_BLUETOOTH-BTPROTO_BNEP",
59 "slock-AF_BLUETOOTH-BTPROTO_CMTP",
60 "slock-AF_BLUETOOTH-BTPROTO_HIDP",
61 "slock-AF_BLUETOOTH-BTPROTO_AVDTP",
62};
db7aa1c2 63
b5a30dda 64void bt_sock_reclassify_lock(struct sock *sk, int proto)
db7aa1c2 65{
b5a30dda 66 BUG_ON(!sk);
db7aa1c2
MH
67 BUG_ON(sock_owned_by_user(sk));
68
69 sock_lock_init_class_and_name(sk,
70 bt_slock_key_strings[proto], &bt_slock_key[proto],
71 bt_key_strings[proto], &bt_lock_key[proto]);
72}
b5a30dda 73EXPORT_SYMBOL(bt_sock_reclassify_lock);
1da177e4 74
ec1b4cf7 75int bt_sock_register(int proto, const struct net_proto_family *ops)
1da177e4 76{
74da626a
MH
77 int err = 0;
78
1da177e4
LT
79 if (proto < 0 || proto >= BT_MAX_PROTO)
80 return -EINVAL;
81
74da626a
MH
82 write_lock(&bt_proto_lock);
83
1da177e4 84 if (bt_proto[proto])
74da626a
MH
85 err = -EEXIST;
86 else
87 bt_proto[proto] = ops;
88
89 write_unlock(&bt_proto_lock);
1da177e4 90
74da626a 91 return err;
1da177e4
LT
92}
93EXPORT_SYMBOL(bt_sock_register);
94
95int bt_sock_unregister(int proto)
96{
74da626a
MH
97 int err = 0;
98
1da177e4
LT
99 if (proto < 0 || proto >= BT_MAX_PROTO)
100 return -EINVAL;
101
74da626a
MH
102 write_lock(&bt_proto_lock);
103
1da177e4 104 if (!bt_proto[proto])
74da626a
MH
105 err = -ENOENT;
106 else
107 bt_proto[proto] = NULL;
1da177e4 108
74da626a
MH
109 write_unlock(&bt_proto_lock);
110
111 return err;
1da177e4
LT
112}
113EXPORT_SYMBOL(bt_sock_unregister);
114
3f378b68
EP
115static int bt_sock_create(struct net *net, struct socket *sock, int proto,
116 int kern)
1da177e4 117{
74da626a 118 int err;
1da177e4 119
1b8d7ae4
EB
120 if (net != &init_net)
121 return -EAFNOSUPPORT;
122
1da177e4
LT
123 if (proto < 0 || proto >= BT_MAX_PROTO)
124 return -EINVAL;
125
95a5afca 126 if (!bt_proto[proto])
1da177e4 127 request_module("bt-proto-%d", proto);
74da626a 128
1da177e4 129 err = -EPROTONOSUPPORT;
74da626a
MH
130
131 read_lock(&bt_proto_lock);
132
1da177e4 133 if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
3f378b68 134 err = bt_proto[proto]->create(net, sock, proto, kern);
b5a30dda
OP
135 if (!err)
136 bt_sock_reclassify_lock(sock->sk, proto);
1da177e4
LT
137 module_put(bt_proto[proto]->owner);
138 }
74da626a
MH
139
140 read_unlock(&bt_proto_lock);
141
8e87d142 142 return err;
1da177e4
LT
143}
144
145void bt_sock_link(struct bt_sock_list *l, struct sock *sk)
146{
94f5bfb8 147 write_lock(&l->lock);
1da177e4 148 sk_add_node(sk, &l->head);
94f5bfb8 149 write_unlock(&l->lock);
1da177e4
LT
150}
151EXPORT_SYMBOL(bt_sock_link);
152
153void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk)
154{
94f5bfb8 155 write_lock(&l->lock);
1da177e4 156 sk_del_node_init(sk);
94f5bfb8 157 write_unlock(&l->lock);
1da177e4
LT
158}
159EXPORT_SYMBOL(bt_sock_unlink);
160
161void bt_accept_enqueue(struct sock *parent, struct sock *sk)
162{
163 BT_DBG("parent %p, sk %p", parent, sk);
164
165 sock_hold(sk);
166 list_add_tail(&bt_sk(sk)->accept_q, &bt_sk(parent)->accept_q);
167 bt_sk(sk)->parent = parent;
168 parent->sk_ack_backlog++;
169}
170EXPORT_SYMBOL(bt_accept_enqueue);
171
172void bt_accept_unlink(struct sock *sk)
173{
174 BT_DBG("sk %p state %d", sk, sk->sk_state);
175
176 list_del_init(&bt_sk(sk)->accept_q);
177 bt_sk(sk)->parent->sk_ack_backlog--;
178 bt_sk(sk)->parent = NULL;
179 sock_put(sk);
180}
181EXPORT_SYMBOL(bt_accept_unlink);
182
183struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
184{
185 struct list_head *p, *n;
186 struct sock *sk;
187
188 BT_DBG("parent %p", parent);
189
190 list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
191 sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
192
8a154a8f 193 lock_sock(sk);
1da177e4
LT
194
195 /* FIXME: Is this check still needed */
196 if (sk->sk_state == BT_CLOSED) {
8a154a8f 197 release_sock(sk);
1da177e4
LT
198 bt_accept_unlink(sk);
199 continue;
200 }
201
c4f912e1 202 if (sk->sk_state == BT_CONNECTED || !newsock ||
d060991f 203 test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags)) {
1da177e4
LT
204 bt_accept_unlink(sk);
205 if (newsock)
206 sock_graft(sk, newsock);
d37f50e1 207
8a154a8f 208 release_sock(sk);
1da177e4
LT
209 return sk;
210 }
211
8a154a8f 212 release_sock(sk);
1da177e4 213 }
d37f50e1 214
1da177e4
LT
215 return NULL;
216}
217EXPORT_SYMBOL(bt_accept_dequeue);
218
219int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
c4f912e1 220 struct msghdr *msg, size_t len, int flags)
1da177e4
LT
221{
222 int noblock = flags & MSG_DONTWAIT;
223 struct sock *sk = sock->sk;
224 struct sk_buff *skb;
225 size_t copied;
226 int err;
227
a418b893 228 BT_DBG("sock %p sk %p len %zu", sock, sk, len);
1da177e4
LT
229
230 if (flags & (MSG_OOB))
231 return -EOPNOTSUPP;
232
5a08ecce
AE
233 skb = skb_recv_datagram(sk, flags, noblock, &err);
234 if (!skb) {
1da177e4
LT
235 if (sk->sk_shutdown & RCV_SHUTDOWN)
236 return 0;
237 return err;
238 }
239
240 msg->msg_namelen = 0;
241
242 copied = skb->len;
243 if (len < copied) {
244 msg->msg_flags |= MSG_TRUNC;
245 copied = len;
246 }
247
badff6d0 248 skb_reset_transport_header(skb);
1da177e4 249 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
3241ad82 250 if (err == 0)
3b885787 251 sock_recv_ts_and_drops(msg, sk, skb);
1da177e4
LT
252
253 skb_free_datagram(sk, skb);
254
255 return err ? : copied;
256}
257EXPORT_SYMBOL(bt_sock_recvmsg);
258
796c86ee
MM
259static long bt_sock_data_wait(struct sock *sk, long timeo)
260{
261 DECLARE_WAITQUEUE(wait, current);
262
263 add_wait_queue(sk_sleep(sk), &wait);
264 for (;;) {
265 set_current_state(TASK_INTERRUPTIBLE);
266
267 if (!skb_queue_empty(&sk->sk_receive_queue))
268 break;
269
270 if (sk->sk_err || (sk->sk_shutdown & RCV_SHUTDOWN))
271 break;
272
273 if (signal_pending(current) || !timeo)
274 break;
275
276 set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
277 release_sock(sk);
278 timeo = schedule_timeout(timeo);
279 lock_sock(sk);
280 clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
281 }
282
283 __set_current_state(TASK_RUNNING);
284 remove_wait_queue(sk_sleep(sk), &wait);
285 return timeo;
286}
287
288int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
289 struct msghdr *msg, size_t size, int flags)
290{
291 struct sock *sk = sock->sk;
292 int err = 0;
293 size_t target, copied = 0;
294 long timeo;
295
296 if (flags & MSG_OOB)
297 return -EOPNOTSUPP;
298
299 msg->msg_namelen = 0;
300
301 BT_DBG("sk %p size %zu", sk, size);
302
303 lock_sock(sk);
304
305 target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
306 timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
307
308 do {
309 struct sk_buff *skb;
310 int chunk;
311
312 skb = skb_dequeue(&sk->sk_receive_queue);
313 if (!skb) {
314 if (copied >= target)
315 break;
316
5a08ecce
AE
317 err = sock_error(sk);
318 if (err)
796c86ee
MM
319 break;
320 if (sk->sk_shutdown & RCV_SHUTDOWN)
321 break;
322
323 err = -EAGAIN;
324 if (!timeo)
325 break;
326
327 timeo = bt_sock_data_wait(sk, timeo);
328
329 if (signal_pending(current)) {
330 err = sock_intr_errno(timeo);
331 goto out;
332 }
333 continue;
334 }
335
336 chunk = min_t(unsigned int, skb->len, size);
5b668eb3 337 if (skb_copy_datagram_iovec(skb, 0, msg->msg_iov, chunk)) {
796c86ee
MM
338 skb_queue_head(&sk->sk_receive_queue, skb);
339 if (!copied)
340 copied = -EFAULT;
341 break;
342 }
343 copied += chunk;
344 size -= chunk;
345
346 sock_recv_ts_and_drops(msg, sk, skb);
347
348 if (!(flags & MSG_PEEK)) {
5b668eb3
MM
349 int skb_len = skb_headlen(skb);
350
351 if (chunk <= skb_len) {
352 __skb_pull(skb, chunk);
353 } else {
354 struct sk_buff *frag;
355
356 __skb_pull(skb, skb_len);
357 chunk -= skb_len;
358
359 skb_walk_frags(skb, frag) {
360 if (chunk <= frag->len) {
361 /* Pulling partial data */
362 skb->len -= chunk;
363 skb->data_len -= chunk;
364 __skb_pull(frag, chunk);
365 break;
366 } else if (frag->len) {
367 /* Pulling all frag data */
368 chunk -= frag->len;
369 skb->len -= frag->len;
370 skb->data_len -= frag->len;
371 __skb_pull(frag, frag->len);
372 }
373 }
374 }
375
796c86ee
MM
376 if (skb->len) {
377 skb_queue_head(&sk->sk_receive_queue, skb);
378 break;
379 }
380 kfree_skb(skb);
381
382 } else {
383 /* put message back and return */
384 skb_queue_head(&sk->sk_receive_queue, skb);
385 break;
386 }
387 } while (size);
388
389out:
390 release_sock(sk);
391 return copied ? : err;
392}
393EXPORT_SYMBOL(bt_sock_stream_recvmsg);
394
1da177e4
LT
395static inline unsigned int bt_accept_poll(struct sock *parent)
396{
397 struct list_head *p, *n;
398 struct sock *sk;
399
400 list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
401 sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
d5f2d2be 402 if (sk->sk_state == BT_CONNECTED ||
c5daa683
GP
403 (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags) &&
404 sk->sk_state == BT_CONNECT2))
1da177e4
LT
405 return POLLIN | POLLRDNORM;
406 }
407
408 return 0;
409}
410
8fc9ced3
GP
411unsigned int bt_sock_poll(struct file *file, struct socket *sock,
412 poll_table *wait)
1da177e4
LT
413{
414 struct sock *sk = sock->sk;
415 unsigned int mask = 0;
416
417 BT_DBG("sock %p, sk %p", sock, sk);
418
aa395145 419 poll_wait(file, sk_sleep(sk), wait);
1da177e4
LT
420
421 if (sk->sk_state == BT_LISTEN)
422 return bt_accept_poll(sk);
423
424 if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
7d4c04fc
KJ
425 mask |= POLLERR |
426 sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0;
1da177e4 427
f348d70a 428 if (sk->sk_shutdown & RCV_SHUTDOWN)
db40980f 429 mask |= POLLRDHUP | POLLIN | POLLRDNORM;
f348d70a 430
1da177e4
LT
431 if (sk->sk_shutdown == SHUTDOWN_MASK)
432 mask |= POLLHUP;
433
db40980f 434 if (!skb_queue_empty(&sk->sk_receive_queue))
1da177e4
LT
435 mask |= POLLIN | POLLRDNORM;
436
437 if (sk->sk_state == BT_CLOSED)
438 mask |= POLLHUP;
439
440 if (sk->sk_state == BT_CONNECT ||
441 sk->sk_state == BT_CONNECT2 ||
442 sk->sk_state == BT_CONFIG)
443 return mask;
444
c5daa683 445 if (!test_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags) && sock_writeable(sk))
1da177e4
LT
446 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
447 else
448 set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
449
450 return mask;
451}
452EXPORT_SYMBOL(bt_sock_poll);
453
3241ad82
MH
454int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
455{
456 struct sock *sk = sock->sk;
43cbeee9
MH
457 struct sk_buff *skb;
458 long amount;
3241ad82
MH
459 int err;
460
461 BT_DBG("sk %p cmd %x arg %lx", sk, cmd, arg);
462
463 switch (cmd) {
43cbeee9
MH
464 case TIOCOUTQ:
465 if (sk->sk_state == BT_LISTEN)
466 return -EINVAL;
467
31e6d363 468 amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
43cbeee9
MH
469 if (amount < 0)
470 amount = 0;
471 err = put_user(amount, (int __user *) arg);
472 break;
473
474 case TIOCINQ:
475 if (sk->sk_state == BT_LISTEN)
476 return -EINVAL;
477
478 lock_sock(sk);
479 skb = skb_peek(&sk->sk_receive_queue);
480 amount = skb ? skb->len : 0;
481 release_sock(sk);
482 err = put_user(amount, (int __user *) arg);
483 break;
484
3241ad82
MH
485 case SIOCGSTAMP:
486 err = sock_get_timestamp(sk, (struct timeval __user *) arg);
487 break;
488
489 case SIOCGSTAMPNS:
490 err = sock_get_timestampns(sk, (struct timespec __user *) arg);
491 break;
492
493 default:
494 err = -ENOIOCTLCMD;
495 break;
496 }
497
498 return err;
499}
500EXPORT_SYMBOL(bt_sock_ioctl);
501
1da177e4
LT
502int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
503{
504 DECLARE_WAITQUEUE(wait, current);
505 int err = 0;
506
507 BT_DBG("sk %p", sk);
508
aa395145 509 add_wait_queue(sk_sleep(sk), &wait);
9be4e3fb 510 set_current_state(TASK_INTERRUPTIBLE);
1da177e4 511 while (sk->sk_state != state) {
1da177e4 512 if (!timeo) {
b4c612a4 513 err = -EINPROGRESS;
1da177e4
LT
514 break;
515 }
516
517 if (signal_pending(current)) {
518 err = sock_intr_errno(timeo);
519 break;
520 }
521
522 release_sock(sk);
523 timeo = schedule_timeout(timeo);
524 lock_sock(sk);
9be4e3fb 525 set_current_state(TASK_INTERRUPTIBLE);
1da177e4 526
c1cbe4b7
BL
527 err = sock_error(sk);
528 if (err)
1da177e4 529 break;
1da177e4 530 }
9be4e3fb 531 __set_current_state(TASK_RUNNING);
aa395145 532 remove_wait_queue(sk_sleep(sk), &wait);
1da177e4
LT
533 return err;
534}
535EXPORT_SYMBOL(bt_sock_wait_state);
536
256a06c8
MY
537#ifdef CONFIG_PROC_FS
538struct bt_seq_state {
539 struct bt_sock_list *l;
540};
541
542static void *bt_seq_start(struct seq_file *seq, loff_t *pos)
543 __acquires(seq->private->l->lock)
544{
545 struct bt_seq_state *s = seq->private;
546 struct bt_sock_list *l = s->l;
547
548 read_lock(&l->lock);
549 return seq_hlist_start_head(&l->head, *pos);
550}
551
552static void *bt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
553{
554 struct bt_seq_state *s = seq->private;
555 struct bt_sock_list *l = s->l;
556
557 return seq_hlist_next(v, &l->head, pos);
558}
559
560static void bt_seq_stop(struct seq_file *seq, void *v)
561 __releases(seq->private->l->lock)
562{
563 struct bt_seq_state *s = seq->private;
564 struct bt_sock_list *l = s->l;
565
566 read_unlock(&l->lock);
567}
568
569static int bt_seq_show(struct seq_file *seq, void *v)
570{
256a06c8
MY
571 struct bt_seq_state *s = seq->private;
572 struct bt_sock_list *l = s->l;
256a06c8
MY
573
574 if (v == SEQ_START_TOKEN) {
575 seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent");
576
577 if (l->custom_seq_show) {
578 seq_putc(seq, ' ');
579 l->custom_seq_show(seq, v);
580 }
581
582 seq_putc(seq, '\n');
583 } else {
09d5d4aa
AE
584 struct sock *sk = sk_entry(v);
585 struct bt_sock *bt = bt_sk(sk);
256a06c8 586
7028a886
AE
587 seq_printf(seq,
588 "%pK %-6d %-6u %-6u %-6u %-6lu %pMR %pMR %-6lu",
256a06c8
MY
589 sk,
590 atomic_read(&sk->sk_refcnt),
591 sk_rmem_alloc_get(sk),
592 sk_wmem_alloc_get(sk),
1bbb3095 593 from_kuid(seq_user_ns(seq), sock_i_uid(sk)),
256a06c8 594 sock_i_ino(sk),
7028a886
AE
595 &bt->src,
596 &bt->dst,
256a06c8
MY
597 bt->parent? sock_i_ino(bt->parent): 0LU);
598
599 if (l->custom_seq_show) {
600 seq_putc(seq, ' ');
601 l->custom_seq_show(seq, v);
602 }
603
604 seq_putc(seq, '\n');
605 }
606 return 0;
607}
608
609static struct seq_operations bt_seq_ops = {
610 .start = bt_seq_start,
611 .next = bt_seq_next,
612 .stop = bt_seq_stop,
613 .show = bt_seq_show,
614};
615
616static int bt_seq_open(struct inode *inode, struct file *file)
617{
618 struct bt_sock_list *sk_list;
619 struct bt_seq_state *s;
620
621 sk_list = PDE(inode)->data;
622 s = __seq_open_private(file, &bt_seq_ops,
623 sizeof(struct bt_seq_state));
31f47073 624 if (!s)
256a06c8
MY
625 return -ENOMEM;
626
627 s->l = sk_list;
628 return 0;
629}
630
631int bt_procfs_init(struct module* module, struct net *net, const char *name,
632 struct bt_sock_list* sk_list,
633 int (* seq_show)(struct seq_file *, void *))
634{
635 struct proc_dir_entry * pde;
636
637 sk_list->custom_seq_show = seq_show;
638
639 sk_list->fops.owner = module;
640 sk_list->fops.open = bt_seq_open;
641 sk_list->fops.read = seq_read;
642 sk_list->fops.llseek = seq_lseek;
643 sk_list->fops.release = seq_release_private;
644
d4beaa66 645 pde = proc_create(name, 0, net->proc_net, &sk_list->fops);
31f47073 646 if (!pde)
256a06c8
MY
647 return -ENOMEM;
648
649 pde->data = sk_list;
650
651 return 0;
652}
653
654void bt_procfs_cleanup(struct net *net, const char *name)
655{
ece31ffd 656 remove_proc_entry(name, net->proc_net);
256a06c8
MY
657}
658#else
659int bt_procfs_init(struct module* module, struct net *net, const char *name,
660 struct bt_sock_list* sk_list,
661 int (* seq_show)(struct seq_file *, void *))
662{
663 return 0;
664}
665
666void bt_procfs_cleanup(struct net *net, const char *name)
667{
668}
669#endif
670EXPORT_SYMBOL(bt_procfs_init);
671EXPORT_SYMBOL(bt_procfs_cleanup);
672
1da177e4
LT
673static struct net_proto_family bt_sock_family_ops = {
674 .owner = THIS_MODULE,
675 .family = PF_BLUETOOTH,
676 .create = bt_sock_create,
677};
678
1da177e4
LT
679static int __init bt_init(void)
680{
27d35284
MH
681 int err;
682
1da177e4
LT
683 BT_INFO("Core ver %s", VERSION);
684
27d35284
MH
685 err = bt_sysfs_init();
686 if (err < 0)
687 return err;
1da177e4 688
27d35284
MH
689 err = sock_register(&bt_sock_family_ops);
690 if (err < 0) {
691 bt_sysfs_cleanup();
692 return err;
693 }
1da177e4 694
27d35284 695 BT_INFO("HCI device and connection manager initialized");
1da177e4 696
64274518
GP
697 err = hci_sock_init();
698 if (err < 0)
699 goto error;
700
701 err = l2cap_init();
0ed54dad 702 if (err < 0)
64274518 703 goto sock_err;
64274518
GP
704
705 err = sco_init();
706 if (err < 0) {
707 l2cap_exit();
708 goto sock_err;
709 }
1da177e4
LT
710
711 return 0;
64274518
GP
712
713sock_err:
714 hci_sock_cleanup();
715
716error:
717 sock_unregister(PF_BLUETOOTH);
718 bt_sysfs_cleanup();
719
720 return err;
1da177e4
LT
721}
722
723static void __exit bt_exit(void)
724{
64274518
GP
725
726 sco_exit();
727
728 l2cap_exit();
729
1da177e4
LT
730 hci_sock_cleanup();
731
1da177e4 732 sock_unregister(PF_BLUETOOTH);
27d35284
MH
733
734 bt_sysfs_cleanup();
1da177e4
LT
735}
736
737subsys_initcall(bt_init);
738module_exit(bt_exit);
739
63fbd24e 740MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
1da177e4
LT
741MODULE_DESCRIPTION("Bluetooth Core ver " VERSION);
742MODULE_VERSION(VERSION);
743MODULE_LICENSE("GPL");
744MODULE_ALIAS_NETPROTO(PF_BLUETOOTH);
This page took 1.093004 seconds and 5 git commands to generate.