Bluetooth: Preparation for usage of SOL_BLUETOOTH
[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
LT
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>
1da177e4
LT
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>
1da177e4 38#include <net/sock.h>
3241ad82 39#include <asm/ioctls.h>
1da177e4 40#include <linux/kmod.h>
1da177e4
LT
41
42#include <net/bluetooth/bluetooth.h>
43
7a9d4020 44#define VERSION "2.14"
1da177e4
LT
45
46/* Bluetooth sockets */
47#define BT_MAX_PROTO 8
48static struct net_proto_family *bt_proto[BT_MAX_PROTO];
db7aa1c2 49static DEFINE_RWLOCK(bt_proto_lock);
68845cb2 50
db7aa1c2 51#ifdef CONFIG_DEBUG_LOCK_ALLOC
68845cb2
DY
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
db7aa1c2 64static struct lock_class_key bt_slock_key[BT_MAX_PROTO];
68845cb2
DY
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};
db7aa1c2
MH
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
1da177e4
LT
94
95int bt_sock_register(int proto, struct net_proto_family *ops)
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 = -EEXIST;
106 else
107 bt_proto[proto] = ops;
108
109 write_unlock(&bt_proto_lock);
1da177e4 110
74da626a 111 return err;
1da177e4
LT
112}
113EXPORT_SYMBOL(bt_sock_register);
114
115int bt_sock_unregister(int proto)
116{
74da626a
MH
117 int err = 0;
118
1da177e4
LT
119 if (proto < 0 || proto >= BT_MAX_PROTO)
120 return -EINVAL;
121
74da626a
MH
122 write_lock(&bt_proto_lock);
123
1da177e4 124 if (!bt_proto[proto])
74da626a
MH
125 err = -ENOENT;
126 else
127 bt_proto[proto] = NULL;
1da177e4 128
74da626a
MH
129 write_unlock(&bt_proto_lock);
130
131 return err;
1da177e4
LT
132}
133EXPORT_SYMBOL(bt_sock_unregister);
134
1b8d7ae4 135static int bt_sock_create(struct net *net, struct socket *sock, int proto)
1da177e4 136{
74da626a 137 int err;
1da177e4 138
1b8d7ae4
EB
139 if (net != &init_net)
140 return -EAFNOSUPPORT;
141
1da177e4
LT
142 if (proto < 0 || proto >= BT_MAX_PROTO)
143 return -EINVAL;
144
95a5afca 145 if (!bt_proto[proto])
1da177e4 146 request_module("bt-proto-%d", proto);
74da626a 147
1da177e4 148 err = -EPROTONOSUPPORT;
74da626a
MH
149
150 read_lock(&bt_proto_lock);
151
1da177e4 152 if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
1b8d7ae4 153 err = bt_proto[proto]->create(net, sock, proto);
db7aa1c2 154 bt_sock_reclassify_lock(sock, proto);
1da177e4
LT
155 module_put(bt_proto[proto]->owner);
156 }
74da626a
MH
157
158 read_unlock(&bt_proto_lock);
159
8e87d142 160 return err;
1da177e4
LT
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
a418b893 243 BT_DBG("sock %p sk %p len %zu", sock, sk, len);
1da177e4
LT
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
badff6d0 262 skb_reset_transport_header(skb);
1da177e4 263 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
3241ad82
MH
264 if (err == 0)
265 sock_recv_timestamp(msg, sk, skb);
1da177e4
LT
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
f348d70a
DL
302 if (sk->sk_shutdown & RCV_SHUTDOWN)
303 mask |= POLLRDHUP;
304
1da177e4
LT
305 if (sk->sk_shutdown == SHUTDOWN_MASK)
306 mask |= POLLHUP;
307
8e87d142 308 if (!skb_queue_empty(&sk->sk_receive_queue) ||
1da177e4
LT
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
3241ad82
MH
329int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
330{
331 struct sock *sk = sock->sk;
43cbeee9
MH
332 struct sk_buff *skb;
333 long amount;
3241ad82
MH
334 int err;
335
336 BT_DBG("sk %p cmd %x arg %lx", sk, cmd, arg);
337
338 switch (cmd) {
43cbeee9
MH
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
3241ad82
MH
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
1da177e4
LT
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) {
b4c612a4 389 err = -EINPROGRESS;
1da177e4
LT
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
c1cbe4b7
BL
402 err = sock_error(sk);
403 if (err)
1da177e4 404 break;
1da177e4
LT
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
1da177e4
LT
418static int __init bt_init(void)
419{
27d35284
MH
420 int err;
421
1da177e4
LT
422 BT_INFO("Core ver %s", VERSION);
423
27d35284
MH
424 err = bt_sysfs_init();
425 if (err < 0)
426 return err;
1da177e4 427
27d35284
MH
428 err = sock_register(&bt_sock_family_ops);
429 if (err < 0) {
430 bt_sysfs_cleanup();
431 return err;
432 }
1da177e4 433
27d35284 434 BT_INFO("HCI device and connection manager initialized");
1da177e4
LT
435
436 hci_sock_init();
437
438 return 0;
439}
440
441static void __exit bt_exit(void)
442{
443 hci_sock_cleanup();
444
1da177e4 445 sock_unregister(PF_BLUETOOTH);
27d35284
MH
446
447 bt_sysfs_cleanup();
1da177e4
LT
448}
449
450subsys_initcall(bt_init);
451module_exit(bt_exit);
452
63fbd24e 453MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
1da177e4
LT
454MODULE_DESCRIPTION("Bluetooth Core ver " VERSION);
455MODULE_VERSION(VERSION);
456MODULE_LICENSE("GPL");
457MODULE_ALIAS_NETPROTO(PF_BLUETOOTH);