bluetooth: kill unused 'module' argument of bt_procfs_init()
[GitHub/mt8127/android_kernel_alcatel_ttab.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))
425 mask |= POLLERR;
426
f348d70a 427 if (sk->sk_shutdown & RCV_SHUTDOWN)
db40980f 428 mask |= POLLRDHUP | POLLIN | POLLRDNORM;
f348d70a 429
1da177e4
LT
430 if (sk->sk_shutdown == SHUTDOWN_MASK)
431 mask |= POLLHUP;
432
db40980f 433 if (!skb_queue_empty(&sk->sk_receive_queue))
1da177e4
LT
434 mask |= POLLIN | POLLRDNORM;
435
436 if (sk->sk_state == BT_CLOSED)
437 mask |= POLLHUP;
438
439 if (sk->sk_state == BT_CONNECT ||
440 sk->sk_state == BT_CONNECT2 ||
441 sk->sk_state == BT_CONFIG)
442 return mask;
443
c5daa683 444 if (!test_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags) && sock_writeable(sk))
1da177e4
LT
445 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
446 else
447 set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
448
449 return mask;
450}
451EXPORT_SYMBOL(bt_sock_poll);
452
3241ad82
MH
453int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
454{
455 struct sock *sk = sock->sk;
43cbeee9
MH
456 struct sk_buff *skb;
457 long amount;
3241ad82
MH
458 int err;
459
460 BT_DBG("sk %p cmd %x arg %lx", sk, cmd, arg);
461
462 switch (cmd) {
43cbeee9
MH
463 case TIOCOUTQ:
464 if (sk->sk_state == BT_LISTEN)
465 return -EINVAL;
466
31e6d363 467 amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
43cbeee9
MH
468 if (amount < 0)
469 amount = 0;
470 err = put_user(amount, (int __user *) arg);
471 break;
472
473 case TIOCINQ:
474 if (sk->sk_state == BT_LISTEN)
475 return -EINVAL;
476
477 lock_sock(sk);
478 skb = skb_peek(&sk->sk_receive_queue);
479 amount = skb ? skb->len : 0;
480 release_sock(sk);
481 err = put_user(amount, (int __user *) arg);
482 break;
483
3241ad82
MH
484 case SIOCGSTAMP:
485 err = sock_get_timestamp(sk, (struct timeval __user *) arg);
486 break;
487
488 case SIOCGSTAMPNS:
489 err = sock_get_timestampns(sk, (struct timespec __user *) arg);
490 break;
491
492 default:
493 err = -ENOIOCTLCMD;
494 break;
495 }
496
497 return err;
498}
499EXPORT_SYMBOL(bt_sock_ioctl);
500
1da177e4
LT
501int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
502{
503 DECLARE_WAITQUEUE(wait, current);
504 int err = 0;
505
506 BT_DBG("sk %p", sk);
507
aa395145 508 add_wait_queue(sk_sleep(sk), &wait);
9be4e3fb 509 set_current_state(TASK_INTERRUPTIBLE);
1da177e4 510 while (sk->sk_state != state) {
1da177e4 511 if (!timeo) {
b4c612a4 512 err = -EINPROGRESS;
1da177e4
LT
513 break;
514 }
515
516 if (signal_pending(current)) {
517 err = sock_intr_errno(timeo);
518 break;
519 }
520
521 release_sock(sk);
522 timeo = schedule_timeout(timeo);
523 lock_sock(sk);
9be4e3fb 524 set_current_state(TASK_INTERRUPTIBLE);
1da177e4 525
c1cbe4b7
BL
526 err = sock_error(sk);
527 if (err)
1da177e4 528 break;
1da177e4 529 }
9be4e3fb 530 __set_current_state(TASK_RUNNING);
aa395145 531 remove_wait_queue(sk_sleep(sk), &wait);
1da177e4
LT
532 return err;
533}
534EXPORT_SYMBOL(bt_sock_wait_state);
535
256a06c8
MY
536#ifdef CONFIG_PROC_FS
537struct bt_seq_state {
538 struct bt_sock_list *l;
539};
540
541static void *bt_seq_start(struct seq_file *seq, loff_t *pos)
542 __acquires(seq->private->l->lock)
543{
544 struct bt_seq_state *s = seq->private;
545 struct bt_sock_list *l = s->l;
546
547 read_lock(&l->lock);
548 return seq_hlist_start_head(&l->head, *pos);
549}
550
551static void *bt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
552{
553 struct bt_seq_state *s = seq->private;
554 struct bt_sock_list *l = s->l;
555
556 return seq_hlist_next(v, &l->head, pos);
557}
558
559static void bt_seq_stop(struct seq_file *seq, void *v)
560 __releases(seq->private->l->lock)
561{
562 struct bt_seq_state *s = seq->private;
563 struct bt_sock_list *l = s->l;
564
565 read_unlock(&l->lock);
566}
567
568static int bt_seq_show(struct seq_file *seq, void *v)
569{
256a06c8
MY
570 struct bt_seq_state *s = seq->private;
571 struct bt_sock_list *l = s->l;
256a06c8
MY
572
573 if (v == SEQ_START_TOKEN) {
574 seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent");
575
576 if (l->custom_seq_show) {
577 seq_putc(seq, ' ');
578 l->custom_seq_show(seq, v);
579 }
580
581 seq_putc(seq, '\n');
582 } else {
09d5d4aa
AE
583 struct sock *sk = sk_entry(v);
584 struct bt_sock *bt = bt_sk(sk);
256a06c8 585
7028a886
AE
586 seq_printf(seq,
587 "%pK %-6d %-6u %-6u %-6u %-6lu %pMR %pMR %-6lu",
256a06c8
MY
588 sk,
589 atomic_read(&sk->sk_refcnt),
590 sk_rmem_alloc_get(sk),
591 sk_wmem_alloc_get(sk),
1bbb3095 592 from_kuid(seq_user_ns(seq), sock_i_uid(sk)),
256a06c8 593 sock_i_ino(sk),
7028a886
AE
594 &bt->src,
595 &bt->dst,
256a06c8
MY
596 bt->parent? sock_i_ino(bt->parent): 0LU);
597
598 if (l->custom_seq_show) {
599 seq_putc(seq, ' ');
600 l->custom_seq_show(seq, v);
601 }
602
603 seq_putc(seq, '\n');
604 }
605 return 0;
606}
607
608static struct seq_operations bt_seq_ops = {
609 .start = bt_seq_start,
610 .next = bt_seq_next,
611 .stop = bt_seq_stop,
612 .show = bt_seq_show,
613};
614
615static int bt_seq_open(struct inode *inode, struct file *file)
616{
617 struct bt_sock_list *sk_list;
618 struct bt_seq_state *s;
619
d9dda78b 620 sk_list = PDE_DATA(inode);
256a06c8
MY
621 s = __seq_open_private(file, &bt_seq_ops,
622 sizeof(struct bt_seq_state));
31f47073 623 if (!s)
256a06c8
MY
624 return -ENOMEM;
625
626 s->l = sk_list;
627 return 0;
628}
629
14805359
AV
630static const struct file_operations bt_fops = {
631 .open = bt_seq_open,
632 .read = seq_read,
633 .llseek = seq_lseek,
634 .release = seq_release_private
635};
636
b0316615 637int bt_procfs_init(struct net *net, const char *name,
256a06c8
MY
638 struct bt_sock_list* sk_list,
639 int (* seq_show)(struct seq_file *, void *))
640{
641 struct proc_dir_entry * pde;
642
643 sk_list->custom_seq_show = seq_show;
644
14805359 645 pde = proc_create(name, 0, net->proc_net, &bt_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
b0316615 659int bt_procfs_init(struct net *net, const char *name,
256a06c8
MY
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);