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