linux/net/bluetooth/af_bluetooth.c
<<
>>
Prefs
   1/*
   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
  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
  18   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  19
  20   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
  21   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
  22   SOFTWARE IS DISCLAIMED.
  23*/
  24
  25/* Bluetooth address family and sockets. */
  26
  27#include <linux/module.h>
  28#include <asm/ioctls.h>
  29
  30#include <net/bluetooth/bluetooth.h>
  31#include <linux/proc_fs.h>
  32
  33#define VERSION "2.16"
  34
  35/* Bluetooth sockets */
  36#define BT_MAX_PROTO    8
  37static const struct net_proto_family *bt_proto[BT_MAX_PROTO];
  38static DEFINE_RWLOCK(bt_proto_lock);
  39
  40static struct lock_class_key bt_lock_key[BT_MAX_PROTO];
  41static const char *const bt_key_strings[BT_MAX_PROTO] = {
  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
  52static struct lock_class_key bt_slock_key[BT_MAX_PROTO];
  53static const char *const bt_slock_key_strings[BT_MAX_PROTO] = {
  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};
  63
  64void bt_sock_reclassify_lock(struct sock *sk, int proto)
  65{
  66        BUG_ON(!sk);
  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}
  73EXPORT_SYMBOL(bt_sock_reclassify_lock);
  74
  75int bt_sock_register(int proto, const struct net_proto_family *ops)
  76{
  77        int err = 0;
  78
  79        if (proto < 0 || proto >= BT_MAX_PROTO)
  80                return -EINVAL;
  81
  82        write_lock(&bt_proto_lock);
  83
  84        if (bt_proto[proto])
  85                err = -EEXIST;
  86        else
  87                bt_proto[proto] = ops;
  88
  89        write_unlock(&bt_proto_lock);
  90
  91        return err;
  92}
  93EXPORT_SYMBOL(bt_sock_register);
  94
  95int bt_sock_unregister(int proto)
  96{
  97        int err = 0;
  98
  99        if (proto < 0 || proto >= BT_MAX_PROTO)
 100                return -EINVAL;
 101
 102        write_lock(&bt_proto_lock);
 103
 104        if (!bt_proto[proto])
 105                err = -ENOENT;
 106        else
 107                bt_proto[proto] = NULL;
 108
 109        write_unlock(&bt_proto_lock);
 110
 111        return err;
 112}
 113EXPORT_SYMBOL(bt_sock_unregister);
 114
 115static int bt_sock_create(struct net *net, struct socket *sock, int proto,
 116                          int kern)
 117{
 118        int err;
 119
 120        if (net != &init_net)
 121                return -EAFNOSUPPORT;
 122
 123        if (proto < 0 || proto >= BT_MAX_PROTO)
 124                return -EINVAL;
 125
 126        if (!bt_proto[proto])
 127                request_module("bt-proto-%d", proto);
 128
 129        err = -EPROTONOSUPPORT;
 130
 131        read_lock(&bt_proto_lock);
 132
 133        if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
 134                err = bt_proto[proto]->create(net, sock, proto, kern);
 135                if (!err)
 136                        bt_sock_reclassify_lock(sock->sk, proto);
 137                module_put(bt_proto[proto]->owner);
 138        }
 139
 140        read_unlock(&bt_proto_lock);
 141
 142        return err;
 143}
 144
 145void bt_sock_link(struct bt_sock_list *l, struct sock *sk)
 146{
 147        write_lock(&l->lock);
 148        sk_add_node(sk, &l->head);
 149        write_unlock(&l->lock);
 150}
 151EXPORT_SYMBOL(bt_sock_link);
 152
 153void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk)
 154{
 155        write_lock(&l->lock);
 156        sk_del_node_init(sk);
 157        write_unlock(&l->lock);
 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
 193                lock_sock(sk);
 194
 195                /* FIXME: Is this check still needed */
 196                if (sk->sk_state == BT_CLOSED) {
 197                        release_sock(sk);
 198                        bt_accept_unlink(sk);
 199                        continue;
 200                }
 201
 202                if (sk->sk_state == BT_CONNECTED || !newsock ||
 203                    test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags)) {
 204                        bt_accept_unlink(sk);
 205                        if (newsock)
 206                                sock_graft(sk, newsock);
 207
 208                        release_sock(sk);
 209                        return sk;
 210                }
 211
 212                release_sock(sk);
 213        }
 214
 215        return NULL;
 216}
 217EXPORT_SYMBOL(bt_accept_dequeue);
 218
 219int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 220                                struct msghdr *msg, size_t len, int flags)
 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
 228        BT_DBG("sock %p sk %p len %zu", sock, sk, len);
 229
 230        if (flags & (MSG_OOB))
 231                return -EOPNOTSUPP;
 232
 233        skb = skb_recv_datagram(sk, flags, noblock, &err);
 234        if (!skb) {
 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
 248        skb_reset_transport_header(skb);
 249        err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 250        if (err == 0)
 251                sock_recv_ts_and_drops(msg, sk, skb);
 252
 253        skb_free_datagram(sk, skb);
 254
 255        return err ? : copied;
 256}
 257EXPORT_SYMBOL(bt_sock_recvmsg);
 258
 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
 317                        err = sock_error(sk);
 318                        if (err)
 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);
 337                if (skb_copy_datagram_iovec(skb, 0, msg->msg_iov, chunk)) {
 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)) {
 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
 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
 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);
 402                if (sk->sk_state == BT_CONNECTED ||
 403                    (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags) &&
 404                     sk->sk_state == BT_CONNECT2))
 405                        return POLLIN | POLLRDNORM;
 406        }
 407
 408        return 0;
 409}
 410
 411unsigned int bt_sock_poll(struct file *file, struct socket *sock,
 412                          poll_table *wait)
 413{
 414        struct sock *sk = sock->sk;
 415        unsigned int mask = 0;
 416
 417        BT_DBG("sock %p, sk %p", sock, sk);
 418
 419        poll_wait(file, sk_sleep(sk), wait);
 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
 427        if (sk->sk_shutdown & RCV_SHUTDOWN)
 428                mask |= POLLRDHUP | POLLIN | POLLRDNORM;
 429
 430        if (sk->sk_shutdown == SHUTDOWN_MASK)
 431                mask |= POLLHUP;
 432
 433        if (!skb_queue_empty(&sk->sk_receive_queue))
 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
 444        if (!test_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags) && sock_writeable(sk))
 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
 453int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 454{
 455        struct sock *sk = sock->sk;
 456        struct sk_buff *skb;
 457        long amount;
 458        int err;
 459
 460        BT_DBG("sk %p cmd %x arg %lx", sk, cmd, arg);
 461
 462        switch (cmd) {
 463        case TIOCOUTQ:
 464                if (sk->sk_state == BT_LISTEN)
 465                        return -EINVAL;
 466
 467                amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
 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
 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
 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
 508        add_wait_queue(sk_sleep(sk), &wait);
 509        set_current_state(TASK_INTERRUPTIBLE);
 510        while (sk->sk_state != state) {
 511                if (!timeo) {
 512                        err = -EINPROGRESS;
 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);
 524                set_current_state(TASK_INTERRUPTIBLE);
 525
 526                err = sock_error(sk);
 527                if (err)
 528                        break;
 529        }
 530        __set_current_state(TASK_RUNNING);
 531        remove_wait_queue(sk_sleep(sk), &wait);
 532        return err;
 533}
 534EXPORT_SYMBOL(bt_sock_wait_state);
 535
 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{
 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 {
 584                struct sock *sk = sk_entry(v);
 585                struct bt_sock *bt = bt_sk(sk);
 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                           from_kuid(seq_user_ns(seq), 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)
 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)
 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
 674static struct net_proto_family bt_sock_family_ops = {
 675        .owner  = THIS_MODULE,
 676        .family = PF_BLUETOOTH,
 677        .create = bt_sock_create,
 678};
 679
 680static int __init bt_init(void)
 681{
 682        int err;
 683
 684        BT_INFO("Core ver %s", VERSION);
 685
 686        err = bt_sysfs_init();
 687        if (err < 0)
 688                return err;
 689
 690        err = sock_register(&bt_sock_family_ops);
 691        if (err < 0) {
 692                bt_sysfs_cleanup();
 693                return err;
 694        }
 695
 696        BT_INFO("HCI device and connection manager initialized");
 697
 698        err = hci_sock_init();
 699        if (err < 0)
 700                goto error;
 701
 702        err = l2cap_init();
 703        if (err < 0)
 704                goto sock_err;
 705
 706        err = sco_init();
 707        if (err < 0) {
 708                l2cap_exit();
 709                goto sock_err;
 710        }
 711
 712        return 0;
 713
 714sock_err:
 715        hci_sock_cleanup();
 716
 717error:
 718        sock_unregister(PF_BLUETOOTH);
 719        bt_sysfs_cleanup();
 720
 721        return err;
 722}
 723
 724static void __exit bt_exit(void)
 725{
 726
 727        sco_exit();
 728
 729        l2cap_exit();
 730
 731        hci_sock_cleanup();
 732
 733        sock_unregister(PF_BLUETOOTH);
 734
 735        bt_sysfs_cleanup();
 736}
 737
 738subsys_initcall(bt_init);
 739module_exit(bt_exit);
 740
 741MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
 742MODULE_DESCRIPTION("Bluetooth Core ver " VERSION);
 743MODULE_VERSION(VERSION);
 744MODULE_LICENSE("GPL");
 745MODULE_ALIAS_NETPROTO(PF_BLUETOOTH);
 746
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.