Bluetooth: trivial: Shorten variable scope
[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;
572 bdaddr_t src_baswapped, dst_baswapped;
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
MY
586 baswap(&src_baswapped, &bt->src);
587 baswap(&dst_baswapped, &bt->dst);
588
589 seq_printf(seq, "%pK %-6d %-6u %-6u %-6u %-6lu %pM %pM %-6lu",
590 sk,
591 atomic_read(&sk->sk_refcnt),
592 sk_rmem_alloc_get(sk),
593 sk_wmem_alloc_get(sk),
594 sock_i_uid(sk),
595 sock_i_ino(sk),
596 &src_baswapped,
597 &dst_baswapped,
598 bt->parent? sock_i_ino(bt->parent): 0LU);
599
600 if (l->custom_seq_show) {
601 seq_putc(seq, ' ');
602 l->custom_seq_show(seq, v);
603 }
604
605 seq_putc(seq, '\n');
606 }
607 return 0;
608}
609
610static struct seq_operations bt_seq_ops = {
611 .start = bt_seq_start,
612 .next = bt_seq_next,
613 .stop = bt_seq_stop,
614 .show = bt_seq_show,
615};
616
617static int bt_seq_open(struct inode *inode, struct file *file)
618{
619 struct bt_sock_list *sk_list;
620 struct bt_seq_state *s;
621
622 sk_list = PDE(inode)->data;
623 s = __seq_open_private(file, &bt_seq_ops,
624 sizeof(struct bt_seq_state));
625 if (s == NULL)
626 return -ENOMEM;
627
628 s->l = sk_list;
629 return 0;
630}
631
632int bt_procfs_init(struct module* module, struct net *net, const char *name,
633 struct bt_sock_list* sk_list,
634 int (* seq_show)(struct seq_file *, void *))
635{
636 struct proc_dir_entry * pde;
637
638 sk_list->custom_seq_show = seq_show;
639
640 sk_list->fops.owner = module;
641 sk_list->fops.open = bt_seq_open;
642 sk_list->fops.read = seq_read;
643 sk_list->fops.llseek = seq_lseek;
644 sk_list->fops.release = seq_release_private;
645
646 pde = proc_net_fops_create(net, name, 0, &sk_list->fops);
647 if (pde == NULL)
648 return -ENOMEM;
649
650 pde->data = sk_list;
651
652 return 0;
653}
654
655void bt_procfs_cleanup(struct net *net, const char *name)
656{
657 proc_net_remove(net, name);
658}
659#else
660int bt_procfs_init(struct module* module, struct net *net, const char *name,
661 struct bt_sock_list* sk_list,
662 int (* seq_show)(struct seq_file *, void *))
663{
664 return 0;
665}
666
667void bt_procfs_cleanup(struct net *net, const char *name)
668{
669}
670#endif
671EXPORT_SYMBOL(bt_procfs_init);
672EXPORT_SYMBOL(bt_procfs_cleanup);
673
1da177e4
LT
674static struct net_proto_family bt_sock_family_ops = {
675 .owner = THIS_MODULE,
676 .family = PF_BLUETOOTH,
677 .create = bt_sock_create,
678};
679
1da177e4
LT
680static int __init bt_init(void)
681{
27d35284
MH
682 int err;
683
1da177e4
LT
684 BT_INFO("Core ver %s", VERSION);
685
27d35284
MH
686 err = bt_sysfs_init();
687 if (err < 0)
688 return err;
1da177e4 689
27d35284
MH
690 err = sock_register(&bt_sock_family_ops);
691 if (err < 0) {
692 bt_sysfs_cleanup();
693 return err;
694 }
1da177e4 695
27d35284 696 BT_INFO("HCI device and connection manager initialized");
1da177e4 697
64274518
GP
698 err = hci_sock_init();
699 if (err < 0)
700 goto error;
701
702 err = l2cap_init();
0ed54dad 703 if (err < 0)
64274518 704 goto sock_err;
64274518
GP
705
706 err = sco_init();
707 if (err < 0) {
708 l2cap_exit();
709 goto sock_err;
710 }
1da177e4
LT
711
712 return 0;
64274518
GP
713
714sock_err:
715 hci_sock_cleanup();
716
717error:
718 sock_unregister(PF_BLUETOOTH);
719 bt_sysfs_cleanup();
720
721 return err;
1da177e4
LT
722}
723
724static void __exit bt_exit(void)
725{
64274518
GP
726
727 sco_exit();
728
729 l2cap_exit();
730
1da177e4
LT
731 hci_sock_cleanup();
732
1da177e4 733 sock_unregister(PF_BLUETOOTH);
27d35284
MH
734
735 bt_sysfs_cleanup();
1da177e4
LT
736}
737
738subsys_initcall(bt_init);
739module_exit(bt_exit);
740
63fbd24e 741MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
1da177e4
LT
742MODULE_DESCRIPTION("Bluetooth Core ver " VERSION);
743MODULE_VERSION(VERSION);
744MODULE_LICENSE("GPL");
745MODULE_ALIAS_NETPROTO(PF_BLUETOOTH);