[Bluetooth]: Add endian annotations to the core
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / bluetooth / af_bluetooth.c
CommitLineData
1da177e4
LT
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/config.h>
28#include <linux/module.h>
29
30#include <linux/types.h>
31#include <linux/list.h>
32#include <linux/errno.h>
33#include <linux/kernel.h>
1da177e4
LT
34#include <linux/sched.h>
35#include <linux/slab.h>
36#include <linux/skbuff.h>
37#include <linux/init.h>
38#include <linux/poll.h>
39#include <linux/proc_fs.h>
40#include <net/sock.h>
41
42#if defined(CONFIG_KMOD)
43#include <linux/kmod.h>
44#endif
45
46#include <net/bluetooth/bluetooth.h>
47
48#ifndef CONFIG_BT_SOCK_DEBUG
49#undef BT_DBG
50#define BT_DBG(D...)
51#endif
52
53#define VERSION "2.7"
54
55struct proc_dir_entry *proc_bt;
56EXPORT_SYMBOL(proc_bt);
57
58/* Bluetooth sockets */
59#define BT_MAX_PROTO 8
60static struct net_proto_family *bt_proto[BT_MAX_PROTO];
61
62int bt_sock_register(int proto, struct net_proto_family *ops)
63{
64 if (proto < 0 || proto >= BT_MAX_PROTO)
65 return -EINVAL;
66
67 if (bt_proto[proto])
68 return -EEXIST;
69
70 bt_proto[proto] = ops;
71 return 0;
72}
73EXPORT_SYMBOL(bt_sock_register);
74
75int bt_sock_unregister(int proto)
76{
77 if (proto < 0 || proto >= BT_MAX_PROTO)
78 return -EINVAL;
79
80 if (!bt_proto[proto])
81 return -ENOENT;
82
83 bt_proto[proto] = NULL;
84 return 0;
85}
86EXPORT_SYMBOL(bt_sock_unregister);
87
88static int bt_sock_create(struct socket *sock, int proto)
89{
90 int err = 0;
91
92 if (proto < 0 || proto >= BT_MAX_PROTO)
93 return -EINVAL;
94
95#if defined(CONFIG_KMOD)
96 if (!bt_proto[proto]) {
97 request_module("bt-proto-%d", proto);
98 }
99#endif
100 err = -EPROTONOSUPPORT;
101 if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
102 err = bt_proto[proto]->create(sock, proto);
103 module_put(bt_proto[proto]->owner);
104 }
105 return err;
106}
107
108void bt_sock_link(struct bt_sock_list *l, struct sock *sk)
109{
110 write_lock_bh(&l->lock);
111 sk_add_node(sk, &l->head);
112 write_unlock_bh(&l->lock);
113}
114EXPORT_SYMBOL(bt_sock_link);
115
116void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk)
117{
118 write_lock_bh(&l->lock);
119 sk_del_node_init(sk);
120 write_unlock_bh(&l->lock);
121}
122EXPORT_SYMBOL(bt_sock_unlink);
123
124void bt_accept_enqueue(struct sock *parent, struct sock *sk)
125{
126 BT_DBG("parent %p, sk %p", parent, sk);
127
128 sock_hold(sk);
129 list_add_tail(&bt_sk(sk)->accept_q, &bt_sk(parent)->accept_q);
130 bt_sk(sk)->parent = parent;
131 parent->sk_ack_backlog++;
132}
133EXPORT_SYMBOL(bt_accept_enqueue);
134
135void bt_accept_unlink(struct sock *sk)
136{
137 BT_DBG("sk %p state %d", sk, sk->sk_state);
138
139 list_del_init(&bt_sk(sk)->accept_q);
140 bt_sk(sk)->parent->sk_ack_backlog--;
141 bt_sk(sk)->parent = NULL;
142 sock_put(sk);
143}
144EXPORT_SYMBOL(bt_accept_unlink);
145
146struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
147{
148 struct list_head *p, *n;
149 struct sock *sk;
150
151 BT_DBG("parent %p", parent);
152
153 list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
154 sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
155
156 lock_sock(sk);
157
158 /* FIXME: Is this check still needed */
159 if (sk->sk_state == BT_CLOSED) {
160 release_sock(sk);
161 bt_accept_unlink(sk);
162 continue;
163 }
164
165 if (sk->sk_state == BT_CONNECTED || !newsock) {
166 bt_accept_unlink(sk);
167 if (newsock)
168 sock_graft(sk, newsock);
169 release_sock(sk);
170 return sk;
171 }
172
173 release_sock(sk);
174 }
175 return NULL;
176}
177EXPORT_SYMBOL(bt_accept_dequeue);
178
179int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
180 struct msghdr *msg, size_t len, int flags)
181{
182 int noblock = flags & MSG_DONTWAIT;
183 struct sock *sk = sock->sk;
184 struct sk_buff *skb;
185 size_t copied;
186 int err;
187
188 BT_DBG("sock %p sk %p len %d", sock, sk, len);
189
190 if (flags & (MSG_OOB))
191 return -EOPNOTSUPP;
192
193 if (!(skb = skb_recv_datagram(sk, flags, noblock, &err))) {
194 if (sk->sk_shutdown & RCV_SHUTDOWN)
195 return 0;
196 return err;
197 }
198
199 msg->msg_namelen = 0;
200
201 copied = skb->len;
202 if (len < copied) {
203 msg->msg_flags |= MSG_TRUNC;
204 copied = len;
205 }
206
207 skb->h.raw = skb->data;
208 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
209
210 skb_free_datagram(sk, skb);
211
212 return err ? : copied;
213}
214EXPORT_SYMBOL(bt_sock_recvmsg);
215
216static inline unsigned int bt_accept_poll(struct sock *parent)
217{
218 struct list_head *p, *n;
219 struct sock *sk;
220
221 list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
222 sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
223 if (sk->sk_state == BT_CONNECTED)
224 return POLLIN | POLLRDNORM;
225 }
226
227 return 0;
228}
229
230unsigned int bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait)
231{
232 struct sock *sk = sock->sk;
233 unsigned int mask = 0;
234
235 BT_DBG("sock %p, sk %p", sock, sk);
236
237 poll_wait(file, sk->sk_sleep, wait);
238
239 if (sk->sk_state == BT_LISTEN)
240 return bt_accept_poll(sk);
241
242 if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
243 mask |= POLLERR;
244
245 if (sk->sk_shutdown == SHUTDOWN_MASK)
246 mask |= POLLHUP;
247
248 if (!skb_queue_empty(&sk->sk_receive_queue) ||
249 (sk->sk_shutdown & RCV_SHUTDOWN))
250 mask |= POLLIN | POLLRDNORM;
251
252 if (sk->sk_state == BT_CLOSED)
253 mask |= POLLHUP;
254
255 if (sk->sk_state == BT_CONNECT ||
256 sk->sk_state == BT_CONNECT2 ||
257 sk->sk_state == BT_CONFIG)
258 return mask;
259
260 if (sock_writeable(sk))
261 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
262 else
263 set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
264
265 return mask;
266}
267EXPORT_SYMBOL(bt_sock_poll);
268
269int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
270{
271 DECLARE_WAITQUEUE(wait, current);
272 int err = 0;
273
274 BT_DBG("sk %p", sk);
275
276 add_wait_queue(sk->sk_sleep, &wait);
277 while (sk->sk_state != state) {
278 set_current_state(TASK_INTERRUPTIBLE);
279
280 if (!timeo) {
281 err = -EAGAIN;
282 break;
283 }
284
285 if (signal_pending(current)) {
286 err = sock_intr_errno(timeo);
287 break;
288 }
289
290 release_sock(sk);
291 timeo = schedule_timeout(timeo);
292 lock_sock(sk);
293
294 if (sk->sk_err) {
295 err = sock_error(sk);
296 break;
297 }
298 }
299 set_current_state(TASK_RUNNING);
300 remove_wait_queue(sk->sk_sleep, &wait);
301 return err;
302}
303EXPORT_SYMBOL(bt_sock_wait_state);
304
305static struct net_proto_family bt_sock_family_ops = {
306 .owner = THIS_MODULE,
307 .family = PF_BLUETOOTH,
308 .create = bt_sock_create,
309};
310
1da177e4
LT
311static int __init bt_init(void)
312{
313 BT_INFO("Core ver %s", VERSION);
314
315 proc_bt = proc_mkdir("bluetooth", NULL);
316 if (proc_bt)
317 proc_bt->owner = THIS_MODULE;
318
319 sock_register(&bt_sock_family_ops);
320
321 BT_INFO("HCI device and connection manager initialized");
322
323 bt_sysfs_init();
324
325 hci_sock_init();
326
327 return 0;
328}
329
330static void __exit bt_exit(void)
331{
332 hci_sock_cleanup();
333
334 bt_sysfs_cleanup();
335
336 sock_unregister(PF_BLUETOOTH);
337
338 remove_proc_entry("bluetooth", NULL);
339}
340
341subsys_initcall(bt_init);
342module_exit(bt_exit);
343
344MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
345MODULE_DESCRIPTION("Bluetooth Core ver " VERSION);
346MODULE_VERSION(VERSION);
347MODULE_LICENSE("GPL");
348MODULE_ALIAS_NETPROTO(PF_BLUETOOTH);