diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /net/bluetooth/sco.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'net/bluetooth/sco.c')
-rw-r--r-- | net/bluetooth/sco.c | 1071 |
1 files changed, 1071 insertions, 0 deletions
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c new file mode 100644 index 000000000000..3e750ef09e60 --- /dev/null +++ b/net/bluetooth/sco.c | |||
@@ -0,0 +1,1071 @@ | |||
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 SCO sockets. */ | ||
26 | |||
27 | #include <linux/config.h> | ||
28 | #include <linux/module.h> | ||
29 | |||
30 | #include <linux/types.h> | ||
31 | #include <linux/errno.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/major.h> | ||
34 | #include <linux/sched.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/poll.h> | ||
37 | #include <linux/fcntl.h> | ||
38 | #include <linux/init.h> | ||
39 | #include <linux/interrupt.h> | ||
40 | #include <linux/socket.h> | ||
41 | #include <linux/skbuff.h> | ||
42 | #include <linux/proc_fs.h> | ||
43 | #include <linux/seq_file.h> | ||
44 | #include <linux/list.h> | ||
45 | #include <net/sock.h> | ||
46 | |||
47 | #include <asm/system.h> | ||
48 | #include <asm/uaccess.h> | ||
49 | |||
50 | #include <net/bluetooth/bluetooth.h> | ||
51 | #include <net/bluetooth/hci_core.h> | ||
52 | #include <net/bluetooth/sco.h> | ||
53 | |||
54 | #ifndef CONFIG_BT_SCO_DEBUG | ||
55 | #undef BT_DBG | ||
56 | #define BT_DBG(D...) | ||
57 | #endif | ||
58 | |||
59 | #define VERSION "0.4" | ||
60 | |||
61 | static struct proto_ops sco_sock_ops; | ||
62 | |||
63 | static struct bt_sock_list sco_sk_list = { | ||
64 | .lock = RW_LOCK_UNLOCKED | ||
65 | }; | ||
66 | |||
67 | static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent); | ||
68 | static void sco_chan_del(struct sock *sk, int err); | ||
69 | |||
70 | static int sco_conn_del(struct hci_conn *conn, int err); | ||
71 | |||
72 | static void sco_sock_close(struct sock *sk); | ||
73 | static void sco_sock_kill(struct sock *sk); | ||
74 | |||
75 | /* ---- SCO timers ---- */ | ||
76 | static void sco_sock_timeout(unsigned long arg) | ||
77 | { | ||
78 | struct sock *sk = (struct sock *) arg; | ||
79 | |||
80 | BT_DBG("sock %p state %d", sk, sk->sk_state); | ||
81 | |||
82 | bh_lock_sock(sk); | ||
83 | sk->sk_err = ETIMEDOUT; | ||
84 | sk->sk_state_change(sk); | ||
85 | bh_unlock_sock(sk); | ||
86 | |||
87 | sco_sock_kill(sk); | ||
88 | sock_put(sk); | ||
89 | } | ||
90 | |||
91 | static void sco_sock_set_timer(struct sock *sk, long timeout) | ||
92 | { | ||
93 | BT_DBG("sock %p state %d timeout %ld", sk, sk->sk_state, timeout); | ||
94 | sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout); | ||
95 | } | ||
96 | |||
97 | static void sco_sock_clear_timer(struct sock *sk) | ||
98 | { | ||
99 | BT_DBG("sock %p state %d", sk, sk->sk_state); | ||
100 | sk_stop_timer(sk, &sk->sk_timer); | ||
101 | } | ||
102 | |||
103 | static void sco_sock_init_timer(struct sock *sk) | ||
104 | { | ||
105 | init_timer(&sk->sk_timer); | ||
106 | sk->sk_timer.function = sco_sock_timeout; | ||
107 | sk->sk_timer.data = (unsigned long)sk; | ||
108 | } | ||
109 | |||
110 | /* ---- SCO connections ---- */ | ||
111 | static struct sco_conn *sco_conn_add(struct hci_conn *hcon, __u8 status) | ||
112 | { | ||
113 | struct hci_dev *hdev = hcon->hdev; | ||
114 | struct sco_conn *conn; | ||
115 | |||
116 | if ((conn = hcon->sco_data)) | ||
117 | return conn; | ||
118 | |||
119 | if (status) | ||
120 | return conn; | ||
121 | |||
122 | if (!(conn = kmalloc(sizeof(struct sco_conn), GFP_ATOMIC))) | ||
123 | return NULL; | ||
124 | memset(conn, 0, sizeof(struct sco_conn)); | ||
125 | |||
126 | spin_lock_init(&conn->lock); | ||
127 | |||
128 | hcon->sco_data = conn; | ||
129 | conn->hcon = hcon; | ||
130 | |||
131 | conn->src = &hdev->bdaddr; | ||
132 | conn->dst = &hcon->dst; | ||
133 | |||
134 | if (hdev->sco_mtu > 0) | ||
135 | conn->mtu = hdev->sco_mtu; | ||
136 | else | ||
137 | conn->mtu = 60; | ||
138 | |||
139 | BT_DBG("hcon %p conn %p", hcon, conn); | ||
140 | return conn; | ||
141 | } | ||
142 | |||
143 | static inline struct sock *sco_chan_get(struct sco_conn *conn) | ||
144 | { | ||
145 | struct sock *sk = NULL; | ||
146 | sco_conn_lock(conn); | ||
147 | sk = conn->sk; | ||
148 | sco_conn_unlock(conn); | ||
149 | return sk; | ||
150 | } | ||
151 | |||
152 | static int sco_conn_del(struct hci_conn *hcon, int err) | ||
153 | { | ||
154 | struct sco_conn *conn; | ||
155 | struct sock *sk; | ||
156 | |||
157 | if (!(conn = hcon->sco_data)) | ||
158 | return 0; | ||
159 | |||
160 | BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); | ||
161 | |||
162 | /* Kill socket */ | ||
163 | if ((sk = sco_chan_get(conn))) { | ||
164 | bh_lock_sock(sk); | ||
165 | sco_sock_clear_timer(sk); | ||
166 | sco_chan_del(sk, err); | ||
167 | bh_unlock_sock(sk); | ||
168 | sco_sock_kill(sk); | ||
169 | } | ||
170 | |||
171 | hcon->sco_data = NULL; | ||
172 | kfree(conn); | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static inline int sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent) | ||
177 | { | ||
178 | int err = 0; | ||
179 | |||
180 | sco_conn_lock(conn); | ||
181 | if (conn->sk) { | ||
182 | err = -EBUSY; | ||
183 | } else { | ||
184 | __sco_chan_add(conn, sk, parent); | ||
185 | } | ||
186 | sco_conn_unlock(conn); | ||
187 | return err; | ||
188 | } | ||
189 | |||
190 | static int sco_connect(struct sock *sk) | ||
191 | { | ||
192 | bdaddr_t *src = &bt_sk(sk)->src; | ||
193 | bdaddr_t *dst = &bt_sk(sk)->dst; | ||
194 | struct sco_conn *conn; | ||
195 | struct hci_conn *hcon; | ||
196 | struct hci_dev *hdev; | ||
197 | int err = 0; | ||
198 | |||
199 | BT_DBG("%s -> %s", batostr(src), batostr(dst)); | ||
200 | |||
201 | if (!(hdev = hci_get_route(dst, src))) | ||
202 | return -EHOSTUNREACH; | ||
203 | |||
204 | hci_dev_lock_bh(hdev); | ||
205 | |||
206 | err = -ENOMEM; | ||
207 | |||
208 | hcon = hci_connect(hdev, SCO_LINK, dst); | ||
209 | if (!hcon) | ||
210 | goto done; | ||
211 | |||
212 | conn = sco_conn_add(hcon, 0); | ||
213 | if (!conn) { | ||
214 | hci_conn_put(hcon); | ||
215 | goto done; | ||
216 | } | ||
217 | |||
218 | /* Update source addr of the socket */ | ||
219 | bacpy(src, conn->src); | ||
220 | |||
221 | err = sco_chan_add(conn, sk, NULL); | ||
222 | if (err) | ||
223 | goto done; | ||
224 | |||
225 | if (hcon->state == BT_CONNECTED) { | ||
226 | sco_sock_clear_timer(sk); | ||
227 | sk->sk_state = BT_CONNECTED; | ||
228 | } else { | ||
229 | sk->sk_state = BT_CONNECT; | ||
230 | sco_sock_set_timer(sk, sk->sk_sndtimeo); | ||
231 | } | ||
232 | done: | ||
233 | hci_dev_unlock_bh(hdev); | ||
234 | hci_dev_put(hdev); | ||
235 | return err; | ||
236 | } | ||
237 | |||
238 | static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len) | ||
239 | { | ||
240 | struct sco_conn *conn = sco_pi(sk)->conn; | ||
241 | struct sk_buff *skb; | ||
242 | int err, count; | ||
243 | |||
244 | /* Check outgoing MTU */ | ||
245 | if (len > conn->mtu) | ||
246 | return -EINVAL; | ||
247 | |||
248 | BT_DBG("sk %p len %d", sk, len); | ||
249 | |||
250 | count = min_t(unsigned int, conn->mtu, len); | ||
251 | if (!(skb = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err))) | ||
252 | return err; | ||
253 | |||
254 | if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) { | ||
255 | err = -EFAULT; | ||
256 | goto fail; | ||
257 | } | ||
258 | |||
259 | if ((err = hci_send_sco(conn->hcon, skb)) < 0) | ||
260 | goto fail; | ||
261 | |||
262 | return count; | ||
263 | |||
264 | fail: | ||
265 | kfree_skb(skb); | ||
266 | return err; | ||
267 | } | ||
268 | |||
269 | static inline void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) | ||
270 | { | ||
271 | struct sock *sk = sco_chan_get(conn); | ||
272 | |||
273 | if (!sk) | ||
274 | goto drop; | ||
275 | |||
276 | BT_DBG("sk %p len %d", sk, skb->len); | ||
277 | |||
278 | if (sk->sk_state != BT_CONNECTED) | ||
279 | goto drop; | ||
280 | |||
281 | if (!sock_queue_rcv_skb(sk, skb)) | ||
282 | return; | ||
283 | |||
284 | drop: | ||
285 | kfree_skb(skb); | ||
286 | return; | ||
287 | } | ||
288 | |||
289 | /* -------- Socket interface ---------- */ | ||
290 | static struct sock *__sco_get_sock_by_addr(bdaddr_t *ba) | ||
291 | { | ||
292 | struct sock *sk; | ||
293 | struct hlist_node *node; | ||
294 | |||
295 | sk_for_each(sk, node, &sco_sk_list.head) | ||
296 | if (!bacmp(&bt_sk(sk)->src, ba)) | ||
297 | goto found; | ||
298 | sk = NULL; | ||
299 | found: | ||
300 | return sk; | ||
301 | } | ||
302 | |||
303 | /* Find socket listening on source bdaddr. | ||
304 | * Returns closest match. | ||
305 | */ | ||
306 | static struct sock *sco_get_sock_listen(bdaddr_t *src) | ||
307 | { | ||
308 | struct sock *sk = NULL, *sk1 = NULL; | ||
309 | struct hlist_node *node; | ||
310 | |||
311 | read_lock(&sco_sk_list.lock); | ||
312 | |||
313 | sk_for_each(sk, node, &sco_sk_list.head) { | ||
314 | if (sk->sk_state != BT_LISTEN) | ||
315 | continue; | ||
316 | |||
317 | /* Exact match. */ | ||
318 | if (!bacmp(&bt_sk(sk)->src, src)) | ||
319 | break; | ||
320 | |||
321 | /* Closest match */ | ||
322 | if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) | ||
323 | sk1 = sk; | ||
324 | } | ||
325 | |||
326 | read_unlock(&sco_sk_list.lock); | ||
327 | |||
328 | return node ? sk : sk1; | ||
329 | } | ||
330 | |||
331 | static void sco_sock_destruct(struct sock *sk) | ||
332 | { | ||
333 | BT_DBG("sk %p", sk); | ||
334 | |||
335 | skb_queue_purge(&sk->sk_receive_queue); | ||
336 | skb_queue_purge(&sk->sk_write_queue); | ||
337 | } | ||
338 | |||
339 | static void sco_sock_cleanup_listen(struct sock *parent) | ||
340 | { | ||
341 | struct sock *sk; | ||
342 | |||
343 | BT_DBG("parent %p", parent); | ||
344 | |||
345 | /* Close not yet accepted channels */ | ||
346 | while ((sk = bt_accept_dequeue(parent, NULL))) { | ||
347 | sco_sock_close(sk); | ||
348 | sco_sock_kill(sk); | ||
349 | } | ||
350 | |||
351 | parent->sk_state = BT_CLOSED; | ||
352 | sock_set_flag(parent, SOCK_ZAPPED); | ||
353 | } | ||
354 | |||
355 | /* Kill socket (only if zapped and orphan) | ||
356 | * Must be called on unlocked socket. | ||
357 | */ | ||
358 | static void sco_sock_kill(struct sock *sk) | ||
359 | { | ||
360 | if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket) | ||
361 | return; | ||
362 | |||
363 | BT_DBG("sk %p state %d", sk, sk->sk_state); | ||
364 | |||
365 | /* Kill poor orphan */ | ||
366 | bt_sock_unlink(&sco_sk_list, sk); | ||
367 | sock_set_flag(sk, SOCK_DEAD); | ||
368 | sock_put(sk); | ||
369 | } | ||
370 | |||
371 | /* Close socket. | ||
372 | * Must be called on unlocked socket. | ||
373 | */ | ||
374 | static void sco_sock_close(struct sock *sk) | ||
375 | { | ||
376 | struct sco_conn *conn; | ||
377 | |||
378 | sco_sock_clear_timer(sk); | ||
379 | |||
380 | lock_sock(sk); | ||
381 | |||
382 | conn = sco_pi(sk)->conn; | ||
383 | |||
384 | BT_DBG("sk %p state %d conn %p socket %p", sk, sk->sk_state, conn, sk->sk_socket); | ||
385 | |||
386 | switch (sk->sk_state) { | ||
387 | case BT_LISTEN: | ||
388 | sco_sock_cleanup_listen(sk); | ||
389 | break; | ||
390 | |||
391 | case BT_CONNECTED: | ||
392 | case BT_CONFIG: | ||
393 | case BT_CONNECT: | ||
394 | case BT_DISCONN: | ||
395 | sco_chan_del(sk, ECONNRESET); | ||
396 | break; | ||
397 | |||
398 | default: | ||
399 | sock_set_flag(sk, SOCK_ZAPPED); | ||
400 | break; | ||
401 | }; | ||
402 | |||
403 | release_sock(sk); | ||
404 | |||
405 | sco_sock_kill(sk); | ||
406 | } | ||
407 | |||
408 | static void sco_sock_init(struct sock *sk, struct sock *parent) | ||
409 | { | ||
410 | BT_DBG("sk %p", sk); | ||
411 | |||
412 | if (parent) | ||
413 | sk->sk_type = parent->sk_type; | ||
414 | } | ||
415 | |||
416 | static struct proto sco_proto = { | ||
417 | .name = "SCO", | ||
418 | .owner = THIS_MODULE, | ||
419 | .obj_size = sizeof(struct sco_pinfo) | ||
420 | }; | ||
421 | |||
422 | static struct sock *sco_sock_alloc(struct socket *sock, int proto, int prio) | ||
423 | { | ||
424 | struct sock *sk; | ||
425 | |||
426 | sk = sk_alloc(PF_BLUETOOTH, prio, &sco_proto, 1); | ||
427 | if (!sk) | ||
428 | return NULL; | ||
429 | |||
430 | sock_init_data(sock, sk); | ||
431 | INIT_LIST_HEAD(&bt_sk(sk)->accept_q); | ||
432 | |||
433 | sk->sk_destruct = sco_sock_destruct; | ||
434 | sk->sk_sndtimeo = SCO_CONN_TIMEOUT; | ||
435 | |||
436 | sock_reset_flag(sk, SOCK_ZAPPED); | ||
437 | |||
438 | sk->sk_protocol = proto; | ||
439 | sk->sk_state = BT_OPEN; | ||
440 | |||
441 | sco_sock_init_timer(sk); | ||
442 | |||
443 | bt_sock_link(&sco_sk_list, sk); | ||
444 | return sk; | ||
445 | } | ||
446 | |||
447 | static int sco_sock_create(struct socket *sock, int protocol) | ||
448 | { | ||
449 | struct sock *sk; | ||
450 | |||
451 | BT_DBG("sock %p", sock); | ||
452 | |||
453 | sock->state = SS_UNCONNECTED; | ||
454 | |||
455 | if (sock->type != SOCK_SEQPACKET) | ||
456 | return -ESOCKTNOSUPPORT; | ||
457 | |||
458 | sock->ops = &sco_sock_ops; | ||
459 | |||
460 | if (!(sk = sco_sock_alloc(sock, protocol, GFP_KERNEL))) | ||
461 | return -ENOMEM; | ||
462 | |||
463 | sco_sock_init(sk, NULL); | ||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len) | ||
468 | { | ||
469 | struct sockaddr_sco *sa = (struct sockaddr_sco *) addr; | ||
470 | struct sock *sk = sock->sk; | ||
471 | bdaddr_t *src = &sa->sco_bdaddr; | ||
472 | int err = 0; | ||
473 | |||
474 | BT_DBG("sk %p %s", sk, batostr(&sa->sco_bdaddr)); | ||
475 | |||
476 | if (!addr || addr->sa_family != AF_BLUETOOTH) | ||
477 | return -EINVAL; | ||
478 | |||
479 | lock_sock(sk); | ||
480 | |||
481 | if (sk->sk_state != BT_OPEN) { | ||
482 | err = -EBADFD; | ||
483 | goto done; | ||
484 | } | ||
485 | |||
486 | write_lock_bh(&sco_sk_list.lock); | ||
487 | |||
488 | if (bacmp(src, BDADDR_ANY) && __sco_get_sock_by_addr(src)) { | ||
489 | err = -EADDRINUSE; | ||
490 | } else { | ||
491 | /* Save source address */ | ||
492 | bacpy(&bt_sk(sk)->src, &sa->sco_bdaddr); | ||
493 | sk->sk_state = BT_BOUND; | ||
494 | } | ||
495 | |||
496 | write_unlock_bh(&sco_sk_list.lock); | ||
497 | |||
498 | done: | ||
499 | release_sock(sk); | ||
500 | return err; | ||
501 | } | ||
502 | |||
503 | static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags) | ||
504 | { | ||
505 | struct sockaddr_sco *sa = (struct sockaddr_sco *) addr; | ||
506 | struct sock *sk = sock->sk; | ||
507 | int err = 0; | ||
508 | |||
509 | |||
510 | BT_DBG("sk %p", sk); | ||
511 | |||
512 | if (addr->sa_family != AF_BLUETOOTH || alen < sizeof(struct sockaddr_sco)) | ||
513 | return -EINVAL; | ||
514 | |||
515 | if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) | ||
516 | return -EBADFD; | ||
517 | |||
518 | if (sk->sk_type != SOCK_SEQPACKET) | ||
519 | return -EINVAL; | ||
520 | |||
521 | lock_sock(sk); | ||
522 | |||
523 | /* Set destination address and psm */ | ||
524 | bacpy(&bt_sk(sk)->dst, &sa->sco_bdaddr); | ||
525 | |||
526 | if ((err = sco_connect(sk))) | ||
527 | goto done; | ||
528 | |||
529 | err = bt_sock_wait_state(sk, BT_CONNECTED, | ||
530 | sock_sndtimeo(sk, flags & O_NONBLOCK)); | ||
531 | |||
532 | done: | ||
533 | release_sock(sk); | ||
534 | return err; | ||
535 | } | ||
536 | |||
537 | static int sco_sock_listen(struct socket *sock, int backlog) | ||
538 | { | ||
539 | struct sock *sk = sock->sk; | ||
540 | int err = 0; | ||
541 | |||
542 | BT_DBG("sk %p backlog %d", sk, backlog); | ||
543 | |||
544 | lock_sock(sk); | ||
545 | |||
546 | if (sk->sk_state != BT_BOUND || sock->type != SOCK_SEQPACKET) { | ||
547 | err = -EBADFD; | ||
548 | goto done; | ||
549 | } | ||
550 | |||
551 | sk->sk_max_ack_backlog = backlog; | ||
552 | sk->sk_ack_backlog = 0; | ||
553 | sk->sk_state = BT_LISTEN; | ||
554 | |||
555 | done: | ||
556 | release_sock(sk); | ||
557 | return err; | ||
558 | } | ||
559 | |||
560 | static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flags) | ||
561 | { | ||
562 | DECLARE_WAITQUEUE(wait, current); | ||
563 | struct sock *sk = sock->sk, *ch; | ||
564 | long timeo; | ||
565 | int err = 0; | ||
566 | |||
567 | lock_sock(sk); | ||
568 | |||
569 | if (sk->sk_state != BT_LISTEN) { | ||
570 | err = -EBADFD; | ||
571 | goto done; | ||
572 | } | ||
573 | |||
574 | timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); | ||
575 | |||
576 | BT_DBG("sk %p timeo %ld", sk, timeo); | ||
577 | |||
578 | /* Wait for an incoming connection. (wake-one). */ | ||
579 | add_wait_queue_exclusive(sk->sk_sleep, &wait); | ||
580 | while (!(ch = bt_accept_dequeue(sk, newsock))) { | ||
581 | set_current_state(TASK_INTERRUPTIBLE); | ||
582 | if (!timeo) { | ||
583 | err = -EAGAIN; | ||
584 | break; | ||
585 | } | ||
586 | |||
587 | release_sock(sk); | ||
588 | timeo = schedule_timeout(timeo); | ||
589 | lock_sock(sk); | ||
590 | |||
591 | if (sk->sk_state != BT_LISTEN) { | ||
592 | err = -EBADFD; | ||
593 | break; | ||
594 | } | ||
595 | |||
596 | if (signal_pending(current)) { | ||
597 | err = sock_intr_errno(timeo); | ||
598 | break; | ||
599 | } | ||
600 | } | ||
601 | set_current_state(TASK_RUNNING); | ||
602 | remove_wait_queue(sk->sk_sleep, &wait); | ||
603 | |||
604 | if (err) | ||
605 | goto done; | ||
606 | |||
607 | newsock->state = SS_CONNECTED; | ||
608 | |||
609 | BT_DBG("new socket %p", ch); | ||
610 | |||
611 | done: | ||
612 | release_sock(sk); | ||
613 | return err; | ||
614 | } | ||
615 | |||
616 | static int sco_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer) | ||
617 | { | ||
618 | struct sockaddr_sco *sa = (struct sockaddr_sco *) addr; | ||
619 | struct sock *sk = sock->sk; | ||
620 | |||
621 | BT_DBG("sock %p, sk %p", sock, sk); | ||
622 | |||
623 | addr->sa_family = AF_BLUETOOTH; | ||
624 | *len = sizeof(struct sockaddr_sco); | ||
625 | |||
626 | if (peer) | ||
627 | bacpy(&sa->sco_bdaddr, &bt_sk(sk)->dst); | ||
628 | else | ||
629 | bacpy(&sa->sco_bdaddr, &bt_sk(sk)->src); | ||
630 | |||
631 | return 0; | ||
632 | } | ||
633 | |||
634 | static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | ||
635 | struct msghdr *msg, size_t len) | ||
636 | { | ||
637 | struct sock *sk = sock->sk; | ||
638 | int err = 0; | ||
639 | |||
640 | BT_DBG("sock %p, sk %p", sock, sk); | ||
641 | |||
642 | if (sk->sk_err) | ||
643 | return sock_error(sk); | ||
644 | |||
645 | if (msg->msg_flags & MSG_OOB) | ||
646 | return -EOPNOTSUPP; | ||
647 | |||
648 | lock_sock(sk); | ||
649 | |||
650 | if (sk->sk_state == BT_CONNECTED) | ||
651 | err = sco_send_frame(sk, msg, len); | ||
652 | else | ||
653 | err = -ENOTCONN; | ||
654 | |||
655 | release_sock(sk); | ||
656 | return err; | ||
657 | } | ||
658 | |||
659 | static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen) | ||
660 | { | ||
661 | struct sock *sk = sock->sk; | ||
662 | int err = 0; | ||
663 | |||
664 | BT_DBG("sk %p", sk); | ||
665 | |||
666 | lock_sock(sk); | ||
667 | |||
668 | switch (optname) { | ||
669 | default: | ||
670 | err = -ENOPROTOOPT; | ||
671 | break; | ||
672 | } | ||
673 | |||
674 | release_sock(sk); | ||
675 | return err; | ||
676 | } | ||
677 | |||
678 | static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) | ||
679 | { | ||
680 | struct sock *sk = sock->sk; | ||
681 | struct sco_options opts; | ||
682 | struct sco_conninfo cinfo; | ||
683 | int len, err = 0; | ||
684 | |||
685 | BT_DBG("sk %p", sk); | ||
686 | |||
687 | if (get_user(len, optlen)) | ||
688 | return -EFAULT; | ||
689 | |||
690 | lock_sock(sk); | ||
691 | |||
692 | switch (optname) { | ||
693 | case SCO_OPTIONS: | ||
694 | if (sk->sk_state != BT_CONNECTED) { | ||
695 | err = -ENOTCONN; | ||
696 | break; | ||
697 | } | ||
698 | |||
699 | opts.mtu = sco_pi(sk)->conn->mtu; | ||
700 | |||
701 | BT_DBG("mtu %d", opts.mtu); | ||
702 | |||
703 | len = min_t(unsigned int, len, sizeof(opts)); | ||
704 | if (copy_to_user(optval, (char *)&opts, len)) | ||
705 | err = -EFAULT; | ||
706 | |||
707 | break; | ||
708 | |||
709 | case SCO_CONNINFO: | ||
710 | if (sk->sk_state != BT_CONNECTED) { | ||
711 | err = -ENOTCONN; | ||
712 | break; | ||
713 | } | ||
714 | |||
715 | cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle; | ||
716 | memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3); | ||
717 | |||
718 | len = min_t(unsigned int, len, sizeof(cinfo)); | ||
719 | if (copy_to_user(optval, (char *)&cinfo, len)) | ||
720 | err = -EFAULT; | ||
721 | |||
722 | break; | ||
723 | |||
724 | default: | ||
725 | err = -ENOPROTOOPT; | ||
726 | break; | ||
727 | } | ||
728 | |||
729 | release_sock(sk); | ||
730 | return err; | ||
731 | } | ||
732 | |||
733 | static int sco_sock_release(struct socket *sock) | ||
734 | { | ||
735 | struct sock *sk = sock->sk; | ||
736 | int err = 0; | ||
737 | |||
738 | BT_DBG("sock %p, sk %p", sock, sk); | ||
739 | |||
740 | if (!sk) | ||
741 | return 0; | ||
742 | |||
743 | sco_sock_close(sk); | ||
744 | |||
745 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) { | ||
746 | lock_sock(sk); | ||
747 | err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime); | ||
748 | release_sock(sk); | ||
749 | } | ||
750 | |||
751 | sock_orphan(sk); | ||
752 | sco_sock_kill(sk); | ||
753 | return err; | ||
754 | } | ||
755 | |||
756 | static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent) | ||
757 | { | ||
758 | BT_DBG("conn %p", conn); | ||
759 | |||
760 | sco_pi(sk)->conn = conn; | ||
761 | conn->sk = sk; | ||
762 | |||
763 | if (parent) | ||
764 | bt_accept_enqueue(parent, sk); | ||
765 | } | ||
766 | |||
767 | /* Delete channel. | ||
768 | * Must be called on the locked socket. */ | ||
769 | static void sco_chan_del(struct sock *sk, int err) | ||
770 | { | ||
771 | struct sco_conn *conn; | ||
772 | |||
773 | conn = sco_pi(sk)->conn; | ||
774 | |||
775 | BT_DBG("sk %p, conn %p, err %d", sk, conn, err); | ||
776 | |||
777 | if (conn) { | ||
778 | sco_conn_lock(conn); | ||
779 | conn->sk = NULL; | ||
780 | sco_pi(sk)->conn = NULL; | ||
781 | sco_conn_unlock(conn); | ||
782 | hci_conn_put(conn->hcon); | ||
783 | } | ||
784 | |||
785 | sk->sk_state = BT_CLOSED; | ||
786 | sk->sk_err = err; | ||
787 | sk->sk_state_change(sk); | ||
788 | |||
789 | sock_set_flag(sk, SOCK_ZAPPED); | ||
790 | } | ||
791 | |||
792 | static void sco_conn_ready(struct sco_conn *conn) | ||
793 | { | ||
794 | struct sock *parent, *sk; | ||
795 | |||
796 | BT_DBG("conn %p", conn); | ||
797 | |||
798 | sco_conn_lock(conn); | ||
799 | |||
800 | if ((sk = conn->sk)) { | ||
801 | sco_sock_clear_timer(sk); | ||
802 | bh_lock_sock(sk); | ||
803 | sk->sk_state = BT_CONNECTED; | ||
804 | sk->sk_state_change(sk); | ||
805 | bh_unlock_sock(sk); | ||
806 | } else { | ||
807 | parent = sco_get_sock_listen(conn->src); | ||
808 | if (!parent) | ||
809 | goto done; | ||
810 | |||
811 | bh_lock_sock(parent); | ||
812 | |||
813 | sk = sco_sock_alloc(NULL, BTPROTO_SCO, GFP_ATOMIC); | ||
814 | if (!sk) { | ||
815 | bh_unlock_sock(parent); | ||
816 | goto done; | ||
817 | } | ||
818 | |||
819 | sco_sock_init(sk, parent); | ||
820 | |||
821 | bacpy(&bt_sk(sk)->src, conn->src); | ||
822 | bacpy(&bt_sk(sk)->dst, conn->dst); | ||
823 | |||
824 | hci_conn_hold(conn->hcon); | ||
825 | __sco_chan_add(conn, sk, parent); | ||
826 | |||
827 | sk->sk_state = BT_CONNECTED; | ||
828 | |||
829 | /* Wake up parent */ | ||
830 | parent->sk_data_ready(parent, 1); | ||
831 | |||
832 | bh_unlock_sock(parent); | ||
833 | } | ||
834 | |||
835 | done: | ||
836 | sco_conn_unlock(conn); | ||
837 | } | ||
838 | |||
839 | /* ----- SCO interface with lower layer (HCI) ----- */ | ||
840 | static int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type) | ||
841 | { | ||
842 | BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); | ||
843 | |||
844 | /* Always accept connection */ | ||
845 | return HCI_LM_ACCEPT; | ||
846 | } | ||
847 | |||
848 | static int sco_connect_cfm(struct hci_conn *hcon, __u8 status) | ||
849 | { | ||
850 | BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); | ||
851 | |||
852 | if (hcon->type != SCO_LINK) | ||
853 | return 0; | ||
854 | |||
855 | if (!status) { | ||
856 | struct sco_conn *conn; | ||
857 | |||
858 | conn = sco_conn_add(hcon, status); | ||
859 | if (conn) | ||
860 | sco_conn_ready(conn); | ||
861 | } else | ||
862 | sco_conn_del(hcon, bt_err(status)); | ||
863 | |||
864 | return 0; | ||
865 | } | ||
866 | |||
867 | static int sco_disconn_ind(struct hci_conn *hcon, __u8 reason) | ||
868 | { | ||
869 | BT_DBG("hcon %p reason %d", hcon, reason); | ||
870 | |||
871 | if (hcon->type != SCO_LINK) | ||
872 | return 0; | ||
873 | |||
874 | sco_conn_del(hcon, bt_err(reason)); | ||
875 | return 0; | ||
876 | } | ||
877 | |||
878 | static int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb) | ||
879 | { | ||
880 | struct sco_conn *conn = hcon->sco_data; | ||
881 | |||
882 | if (!conn) | ||
883 | goto drop; | ||
884 | |||
885 | BT_DBG("conn %p len %d", conn, skb->len); | ||
886 | |||
887 | if (skb->len) { | ||
888 | sco_recv_frame(conn, skb); | ||
889 | return 0; | ||
890 | } | ||
891 | |||
892 | drop: | ||
893 | kfree_skb(skb); | ||
894 | return 0; | ||
895 | } | ||
896 | |||
897 | /* ---- Proc fs support ---- */ | ||
898 | #ifdef CONFIG_PROC_FS | ||
899 | static void *sco_seq_start(struct seq_file *seq, loff_t *pos) | ||
900 | { | ||
901 | struct sock *sk; | ||
902 | struct hlist_node *node; | ||
903 | loff_t l = *pos; | ||
904 | |||
905 | read_lock_bh(&sco_sk_list.lock); | ||
906 | |||
907 | sk_for_each(sk, node, &sco_sk_list.head) | ||
908 | if (!l--) | ||
909 | goto found; | ||
910 | sk = NULL; | ||
911 | found: | ||
912 | return sk; | ||
913 | } | ||
914 | |||
915 | static void *sco_seq_next(struct seq_file *seq, void *e, loff_t *pos) | ||
916 | { | ||
917 | struct sock *sk = e; | ||
918 | (*pos)++; | ||
919 | return sk_next(sk); | ||
920 | } | ||
921 | |||
922 | static void sco_seq_stop(struct seq_file *seq, void *e) | ||
923 | { | ||
924 | read_unlock_bh(&sco_sk_list.lock); | ||
925 | } | ||
926 | |||
927 | static int sco_seq_show(struct seq_file *seq, void *e) | ||
928 | { | ||
929 | struct sock *sk = e; | ||
930 | seq_printf(seq, "%s %s %d\n", | ||
931 | batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), sk->sk_state); | ||
932 | return 0; | ||
933 | } | ||
934 | |||
935 | static struct seq_operations sco_seq_ops = { | ||
936 | .start = sco_seq_start, | ||
937 | .next = sco_seq_next, | ||
938 | .stop = sco_seq_stop, | ||
939 | .show = sco_seq_show | ||
940 | }; | ||
941 | |||
942 | static int sco_seq_open(struct inode *inode, struct file *file) | ||
943 | { | ||
944 | return seq_open(file, &sco_seq_ops); | ||
945 | } | ||
946 | |||
947 | static struct file_operations sco_seq_fops = { | ||
948 | .owner = THIS_MODULE, | ||
949 | .open = sco_seq_open, | ||
950 | .read = seq_read, | ||
951 | .llseek = seq_lseek, | ||
952 | .release = seq_release, | ||
953 | }; | ||
954 | |||
955 | static int __init sco_proc_init(void) | ||
956 | { | ||
957 | struct proc_dir_entry *p = create_proc_entry("sco", S_IRUGO, proc_bt); | ||
958 | if (!p) | ||
959 | return -ENOMEM; | ||
960 | p->owner = THIS_MODULE; | ||
961 | p->proc_fops = &sco_seq_fops; | ||
962 | return 0; | ||
963 | } | ||
964 | |||
965 | static void __exit sco_proc_cleanup(void) | ||
966 | { | ||
967 | remove_proc_entry("sco", proc_bt); | ||
968 | } | ||
969 | |||
970 | #else /* CONFIG_PROC_FS */ | ||
971 | |||
972 | static int __init sco_proc_init(void) | ||
973 | { | ||
974 | return 0; | ||
975 | } | ||
976 | |||
977 | static void __exit sco_proc_cleanup(void) | ||
978 | { | ||
979 | return; | ||
980 | } | ||
981 | #endif /* CONFIG_PROC_FS */ | ||
982 | |||
983 | static struct proto_ops sco_sock_ops = { | ||
984 | .family = PF_BLUETOOTH, | ||
985 | .owner = THIS_MODULE, | ||
986 | .release = sco_sock_release, | ||
987 | .bind = sco_sock_bind, | ||
988 | .connect = sco_sock_connect, | ||
989 | .listen = sco_sock_listen, | ||
990 | .accept = sco_sock_accept, | ||
991 | .getname = sco_sock_getname, | ||
992 | .sendmsg = sco_sock_sendmsg, | ||
993 | .recvmsg = bt_sock_recvmsg, | ||
994 | .poll = bt_sock_poll, | ||
995 | .ioctl = sock_no_ioctl, | ||
996 | .mmap = sock_no_mmap, | ||
997 | .socketpair = sock_no_socketpair, | ||
998 | .shutdown = sock_no_shutdown, | ||
999 | .setsockopt = sco_sock_setsockopt, | ||
1000 | .getsockopt = sco_sock_getsockopt | ||
1001 | }; | ||
1002 | |||
1003 | static struct net_proto_family sco_sock_family_ops = { | ||
1004 | .family = PF_BLUETOOTH, | ||
1005 | .owner = THIS_MODULE, | ||
1006 | .create = sco_sock_create, | ||
1007 | }; | ||
1008 | |||
1009 | static struct hci_proto sco_hci_proto = { | ||
1010 | .name = "SCO", | ||
1011 | .id = HCI_PROTO_SCO, | ||
1012 | .connect_ind = sco_connect_ind, | ||
1013 | .connect_cfm = sco_connect_cfm, | ||
1014 | .disconn_ind = sco_disconn_ind, | ||
1015 | .recv_scodata = sco_recv_scodata | ||
1016 | }; | ||
1017 | |||
1018 | static int __init sco_init(void) | ||
1019 | { | ||
1020 | int err; | ||
1021 | |||
1022 | err = proto_register(&sco_proto, 0); | ||
1023 | if (err < 0) | ||
1024 | return err; | ||
1025 | |||
1026 | err = bt_sock_register(BTPROTO_SCO, &sco_sock_family_ops); | ||
1027 | if (err < 0) { | ||
1028 | BT_ERR("SCO socket registration failed"); | ||
1029 | goto error; | ||
1030 | } | ||
1031 | |||
1032 | err = hci_register_proto(&sco_hci_proto); | ||
1033 | if (err < 0) { | ||
1034 | BT_ERR("SCO protocol registration failed"); | ||
1035 | bt_sock_unregister(BTPROTO_SCO); | ||
1036 | goto error; | ||
1037 | } | ||
1038 | |||
1039 | sco_proc_init(); | ||
1040 | |||
1041 | BT_INFO("SCO (Voice Link) ver %s", VERSION); | ||
1042 | BT_INFO("SCO socket layer initialized"); | ||
1043 | |||
1044 | return 0; | ||
1045 | |||
1046 | error: | ||
1047 | proto_unregister(&sco_proto); | ||
1048 | return err; | ||
1049 | } | ||
1050 | |||
1051 | static void __exit sco_exit(void) | ||
1052 | { | ||
1053 | sco_proc_cleanup(); | ||
1054 | |||
1055 | if (bt_sock_unregister(BTPROTO_SCO) < 0) | ||
1056 | BT_ERR("SCO socket unregistration failed"); | ||
1057 | |||
1058 | if (hci_unregister_proto(&sco_hci_proto) < 0) | ||
1059 | BT_ERR("SCO protocol unregistration failed"); | ||
1060 | |||
1061 | proto_unregister(&sco_proto); | ||
1062 | } | ||
1063 | |||
1064 | module_init(sco_init); | ||
1065 | module_exit(sco_exit); | ||
1066 | |||
1067 | MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"); | ||
1068 | MODULE_DESCRIPTION("Bluetooth SCO ver " VERSION); | ||
1069 | MODULE_VERSION(VERSION); | ||
1070 | MODULE_LICENSE("GPL"); | ||
1071 | MODULE_ALIAS("bt-proto-2"); | ||