Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.29-rc3 457 lines 10 kB view raw
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 29#include <linux/types.h> 30#include <linux/list.h> 31#include <linux/errno.h> 32#include <linux/kernel.h> 33#include <linux/sched.h> 34#include <linux/slab.h> 35#include <linux/skbuff.h> 36#include <linux/init.h> 37#include <linux/poll.h> 38#include <net/sock.h> 39#include <asm/ioctls.h> 40#include <linux/kmod.h> 41 42#include <net/bluetooth/bluetooth.h> 43 44#define VERSION "2.14" 45 46/* Bluetooth sockets */ 47#define BT_MAX_PROTO 8 48static struct net_proto_family *bt_proto[BT_MAX_PROTO]; 49static DEFINE_RWLOCK(bt_proto_lock); 50 51#ifdef CONFIG_DEBUG_LOCK_ALLOC 52static struct lock_class_key bt_lock_key[BT_MAX_PROTO]; 53static const char *bt_key_strings[BT_MAX_PROTO] = { 54 "sk_lock-AF_BLUETOOTH-BTPROTO_L2CAP", 55 "sk_lock-AF_BLUETOOTH-BTPROTO_HCI", 56 "sk_lock-AF_BLUETOOTH-BTPROTO_SCO", 57 "sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM", 58 "sk_lock-AF_BLUETOOTH-BTPROTO_BNEP", 59 "sk_lock-AF_BLUETOOTH-BTPROTO_CMTP", 60 "sk_lock-AF_BLUETOOTH-BTPROTO_HIDP", 61 "sk_lock-AF_BLUETOOTH-BTPROTO_AVDTP", 62}; 63 64static struct lock_class_key bt_slock_key[BT_MAX_PROTO]; 65static const char *bt_slock_key_strings[BT_MAX_PROTO] = { 66 "slock-AF_BLUETOOTH-BTPROTO_L2CAP", 67 "slock-AF_BLUETOOTH-BTPROTO_HCI", 68 "slock-AF_BLUETOOTH-BTPROTO_SCO", 69 "slock-AF_BLUETOOTH-BTPROTO_RFCOMM", 70 "slock-AF_BLUETOOTH-BTPROTO_BNEP", 71 "slock-AF_BLUETOOTH-BTPROTO_CMTP", 72 "slock-AF_BLUETOOTH-BTPROTO_HIDP", 73 "slock-AF_BLUETOOTH-BTPROTO_AVDTP", 74}; 75 76static inline void bt_sock_reclassify_lock(struct socket *sock, int proto) 77{ 78 struct sock *sk = sock->sk; 79 80 if (!sk) 81 return; 82 83 BUG_ON(sock_owned_by_user(sk)); 84 85 sock_lock_init_class_and_name(sk, 86 bt_slock_key_strings[proto], &bt_slock_key[proto], 87 bt_key_strings[proto], &bt_lock_key[proto]); 88} 89#else 90static inline void bt_sock_reclassify_lock(struct socket *sock, int proto) 91{ 92} 93#endif 94 95int bt_sock_register(int proto, struct net_proto_family *ops) 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 = -EEXIST; 106 else 107 bt_proto[proto] = ops; 108 109 write_unlock(&bt_proto_lock); 110 111 return err; 112} 113EXPORT_SYMBOL(bt_sock_register); 114 115int bt_sock_unregister(int proto) 116{ 117 int err = 0; 118 119 if (proto < 0 || proto >= BT_MAX_PROTO) 120 return -EINVAL; 121 122 write_lock(&bt_proto_lock); 123 124 if (!bt_proto[proto]) 125 err = -ENOENT; 126 else 127 bt_proto[proto] = NULL; 128 129 write_unlock(&bt_proto_lock); 130 131 return err; 132} 133EXPORT_SYMBOL(bt_sock_unregister); 134 135static int bt_sock_create(struct net *net, struct socket *sock, int proto) 136{ 137 int err; 138 139 if (net != &init_net) 140 return -EAFNOSUPPORT; 141 142 if (proto < 0 || proto >= BT_MAX_PROTO) 143 return -EINVAL; 144 145 if (!bt_proto[proto]) 146 request_module("bt-proto-%d", proto); 147 148 err = -EPROTONOSUPPORT; 149 150 read_lock(&bt_proto_lock); 151 152 if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) { 153 err = bt_proto[proto]->create(net, sock, proto); 154 bt_sock_reclassify_lock(sock, proto); 155 module_put(bt_proto[proto]->owner); 156 } 157 158 read_unlock(&bt_proto_lock); 159 160 return err; 161} 162 163void bt_sock_link(struct bt_sock_list *l, struct sock *sk) 164{ 165 write_lock_bh(&l->lock); 166 sk_add_node(sk, &l->head); 167 write_unlock_bh(&l->lock); 168} 169EXPORT_SYMBOL(bt_sock_link); 170 171void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk) 172{ 173 write_lock_bh(&l->lock); 174 sk_del_node_init(sk); 175 write_unlock_bh(&l->lock); 176} 177EXPORT_SYMBOL(bt_sock_unlink); 178 179void bt_accept_enqueue(struct sock *parent, struct sock *sk) 180{ 181 BT_DBG("parent %p, sk %p", parent, sk); 182 183 sock_hold(sk); 184 list_add_tail(&bt_sk(sk)->accept_q, &bt_sk(parent)->accept_q); 185 bt_sk(sk)->parent = parent; 186 parent->sk_ack_backlog++; 187} 188EXPORT_SYMBOL(bt_accept_enqueue); 189 190void bt_accept_unlink(struct sock *sk) 191{ 192 BT_DBG("sk %p state %d", sk, sk->sk_state); 193 194 list_del_init(&bt_sk(sk)->accept_q); 195 bt_sk(sk)->parent->sk_ack_backlog--; 196 bt_sk(sk)->parent = NULL; 197 sock_put(sk); 198} 199EXPORT_SYMBOL(bt_accept_unlink); 200 201struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock) 202{ 203 struct list_head *p, *n; 204 struct sock *sk; 205 206 BT_DBG("parent %p", parent); 207 208 list_for_each_safe(p, n, &bt_sk(parent)->accept_q) { 209 sk = (struct sock *) list_entry(p, struct bt_sock, accept_q); 210 211 lock_sock(sk); 212 213 /* FIXME: Is this check still needed */ 214 if (sk->sk_state == BT_CLOSED) { 215 release_sock(sk); 216 bt_accept_unlink(sk); 217 continue; 218 } 219 220 if (sk->sk_state == BT_CONNECTED || !newsock) { 221 bt_accept_unlink(sk); 222 if (newsock) 223 sock_graft(sk, newsock); 224 release_sock(sk); 225 return sk; 226 } 227 228 release_sock(sk); 229 } 230 return NULL; 231} 232EXPORT_SYMBOL(bt_accept_dequeue); 233 234int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, 235 struct msghdr *msg, size_t len, int flags) 236{ 237 int noblock = flags & MSG_DONTWAIT; 238 struct sock *sk = sock->sk; 239 struct sk_buff *skb; 240 size_t copied; 241 int err; 242 243 BT_DBG("sock %p sk %p len %zu", sock, sk, len); 244 245 if (flags & (MSG_OOB)) 246 return -EOPNOTSUPP; 247 248 if (!(skb = skb_recv_datagram(sk, flags, noblock, &err))) { 249 if (sk->sk_shutdown & RCV_SHUTDOWN) 250 return 0; 251 return err; 252 } 253 254 msg->msg_namelen = 0; 255 256 copied = skb->len; 257 if (len < copied) { 258 msg->msg_flags |= MSG_TRUNC; 259 copied = len; 260 } 261 262 skb_reset_transport_header(skb); 263 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); 264 if (err == 0) 265 sock_recv_timestamp(msg, sk, skb); 266 267 skb_free_datagram(sk, skb); 268 269 return err ? : copied; 270} 271EXPORT_SYMBOL(bt_sock_recvmsg); 272 273static inline unsigned int bt_accept_poll(struct sock *parent) 274{ 275 struct list_head *p, *n; 276 struct sock *sk; 277 278 list_for_each_safe(p, n, &bt_sk(parent)->accept_q) { 279 sk = (struct sock *) list_entry(p, struct bt_sock, accept_q); 280 if (sk->sk_state == BT_CONNECTED) 281 return POLLIN | POLLRDNORM; 282 } 283 284 return 0; 285} 286 287unsigned int bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait) 288{ 289 struct sock *sk = sock->sk; 290 unsigned int mask = 0; 291 292 BT_DBG("sock %p, sk %p", sock, sk); 293 294 poll_wait(file, sk->sk_sleep, wait); 295 296 if (sk->sk_state == BT_LISTEN) 297 return bt_accept_poll(sk); 298 299 if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) 300 mask |= POLLERR; 301 302 if (sk->sk_shutdown & RCV_SHUTDOWN) 303 mask |= POLLRDHUP; 304 305 if (sk->sk_shutdown == SHUTDOWN_MASK) 306 mask |= POLLHUP; 307 308 if (!skb_queue_empty(&sk->sk_receive_queue) || 309 (sk->sk_shutdown & RCV_SHUTDOWN)) 310 mask |= POLLIN | POLLRDNORM; 311 312 if (sk->sk_state == BT_CLOSED) 313 mask |= POLLHUP; 314 315 if (sk->sk_state == BT_CONNECT || 316 sk->sk_state == BT_CONNECT2 || 317 sk->sk_state == BT_CONFIG) 318 return mask; 319 320 if (sock_writeable(sk)) 321 mask |= POLLOUT | POLLWRNORM | POLLWRBAND; 322 else 323 set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); 324 325 return mask; 326} 327EXPORT_SYMBOL(bt_sock_poll); 328 329int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) 330{ 331 struct sock *sk = sock->sk; 332 struct sk_buff *skb; 333 long amount; 334 int err; 335 336 BT_DBG("sk %p cmd %x arg %lx", sk, cmd, arg); 337 338 switch (cmd) { 339 case TIOCOUTQ: 340 if (sk->sk_state == BT_LISTEN) 341 return -EINVAL; 342 343 amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc); 344 if (amount < 0) 345 amount = 0; 346 err = put_user(amount, (int __user *) arg); 347 break; 348 349 case TIOCINQ: 350 if (sk->sk_state == BT_LISTEN) 351 return -EINVAL; 352 353 lock_sock(sk); 354 skb = skb_peek(&sk->sk_receive_queue); 355 amount = skb ? skb->len : 0; 356 release_sock(sk); 357 err = put_user(amount, (int __user *) arg); 358 break; 359 360 case SIOCGSTAMP: 361 err = sock_get_timestamp(sk, (struct timeval __user *) arg); 362 break; 363 364 case SIOCGSTAMPNS: 365 err = sock_get_timestampns(sk, (struct timespec __user *) arg); 366 break; 367 368 default: 369 err = -ENOIOCTLCMD; 370 break; 371 } 372 373 return err; 374} 375EXPORT_SYMBOL(bt_sock_ioctl); 376 377int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo) 378{ 379 DECLARE_WAITQUEUE(wait, current); 380 int err = 0; 381 382 BT_DBG("sk %p", sk); 383 384 add_wait_queue(sk->sk_sleep, &wait); 385 while (sk->sk_state != state) { 386 set_current_state(TASK_INTERRUPTIBLE); 387 388 if (!timeo) { 389 err = -EINPROGRESS; 390 break; 391 } 392 393 if (signal_pending(current)) { 394 err = sock_intr_errno(timeo); 395 break; 396 } 397 398 release_sock(sk); 399 timeo = schedule_timeout(timeo); 400 lock_sock(sk); 401 402 err = sock_error(sk); 403 if (err) 404 break; 405 } 406 set_current_state(TASK_RUNNING); 407 remove_wait_queue(sk->sk_sleep, &wait); 408 return err; 409} 410EXPORT_SYMBOL(bt_sock_wait_state); 411 412static struct net_proto_family bt_sock_family_ops = { 413 .owner = THIS_MODULE, 414 .family = PF_BLUETOOTH, 415 .create = bt_sock_create, 416}; 417 418static int __init bt_init(void) 419{ 420 int err; 421 422 BT_INFO("Core ver %s", VERSION); 423 424 err = bt_sysfs_init(); 425 if (err < 0) 426 return err; 427 428 err = sock_register(&bt_sock_family_ops); 429 if (err < 0) { 430 bt_sysfs_cleanup(); 431 return err; 432 } 433 434 BT_INFO("HCI device and connection manager initialized"); 435 436 hci_sock_init(); 437 438 return 0; 439} 440 441static void __exit bt_exit(void) 442{ 443 hci_sock_cleanup(); 444 445 sock_unregister(PF_BLUETOOTH); 446 447 bt_sysfs_cleanup(); 448} 449 450subsys_initcall(bt_init); 451module_exit(bt_exit); 452 453MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); 454MODULE_DESCRIPTION("Bluetooth Core ver " VERSION); 455MODULE_VERSION(VERSION); 456MODULE_LICENSE("GPL"); 457MODULE_ALIAS_NETPROTO(PF_BLUETOOTH);