patch-2.4.19 linux-2.4.19/net/bluetooth/af_bluetooth.c
Next file: linux-2.4.19/net/bluetooth/hci_conn.c
Previous file: linux-2.4.19/net/bluetooth/Makefile
Back to the patch index
Back to the overall index
- Lines: 295
- Date:
Fri Aug 2 17:39:46 2002
- Orig file:
linux-2.4.18/net/bluetooth/af_bluetooth.c
- Orig date:
Fri Sep 7 09:28:38 2001
diff -urN linux-2.4.18/net/bluetooth/af_bluetooth.c linux-2.4.19/net/bluetooth/af_bluetooth.c
@@ -25,14 +25,15 @@
/*
* BlueZ Bluetooth address family and sockets.
*
- * $Id: af_bluetooth.c,v 1.4 2001/07/05 18:42:44 maxk Exp $
+ * $Id: af_bluetooth.c,v 1.6 2002/06/25 22:03:39 maxk Exp $
*/
-#define VERSION "1.1"
+#define VERSION "2.1"
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
+#include <linux/list.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/major.h>
@@ -40,6 +41,7 @@
#include <linux/slab.h>
#include <linux/skbuff.h>
#include <linux/init.h>
+#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <net/sock.h>
@@ -48,62 +50,71 @@
#endif
#include <net/bluetooth/bluetooth.h>
-#include <net/bluetooth/bluez.h>
+
+#ifndef AF_BLUETOOTH_DEBUG
+#undef BT_DBG
+#define BT_DBG( A... )
+#endif
/* Bluetooth sockets */
-static struct net_proto_family *bluez_sock[BLUEZ_MAX_PROTO];
+#define BLUEZ_MAX_PROTO 5
+static struct net_proto_family *bluez_proto[BLUEZ_MAX_PROTO];
int bluez_sock_register(int proto, struct net_proto_family *ops)
{
- if (proto > BLUEZ_MAX_PROTO)
+ if (proto >= BLUEZ_MAX_PROTO)
return -EINVAL;
- if (bluez_sock[proto])
+ if (bluez_proto[proto])
return -EEXIST;
- bluez_sock[proto] = ops;
+ bluez_proto[proto] = ops;
return 0;
}
int bluez_sock_unregister(int proto)
{
- if (proto > BLUEZ_MAX_PROTO)
+ if (proto >= BLUEZ_MAX_PROTO)
return -EINVAL;
- if (!bluez_sock[proto])
+ if (!bluez_proto[proto])
return -ENOENT;
- bluez_sock[proto] = NULL;
+ bluez_proto[proto] = NULL;
return 0;
}
static int bluez_sock_create(struct socket *sock, int proto)
{
- if (proto > BLUEZ_MAX_PROTO)
+ if (proto >= BLUEZ_MAX_PROTO)
return -EINVAL;
#if defined(CONFIG_KMOD)
- if (!bluez_sock[proto]) {
+ if (!bluez_proto[proto]) {
char module_name[30];
sprintf(module_name, "bt-proto-%d", proto);
request_module(module_name);
}
#endif
- if (!bluez_sock[proto])
+ if (!bluez_proto[proto])
return -ENOENT;
- return bluez_sock[proto]->create(sock, proto);
+ return bluez_proto[proto]->create(sock, proto);
+}
+
+void bluez_sock_init(struct socket *sock, struct sock *sk)
+{
+ sock_init_data(sock, sk);
+ INIT_LIST_HEAD(&bluez_pi(sk)->accept_q);
}
void bluez_sock_link(struct bluez_sock_list *l, struct sock *sk)
{
write_lock(&l->lock);
-
sk->next = l->head;
l->head = sk;
sock_hold(sk);
-
write_unlock(&l->lock);
}
@@ -122,6 +133,162 @@
write_unlock(&l->lock);
}
+void bluez_accept_enqueue(struct sock *parent, struct sock *sk)
+{
+ BT_DBG("parent %p, sk %p", parent, sk);
+
+ sock_hold(sk);
+ list_add_tail(&bluez_pi(sk)->accept_q, &bluez_pi(parent)->accept_q);
+ bluez_pi(sk)->parent = parent;
+ parent->ack_backlog++;
+}
+
+static void bluez_accept_unlink(struct sock *sk)
+{
+ BT_DBG("sk %p state %d", sk, sk->state);
+
+ list_del_init(&bluez_pi(sk)->accept_q);
+ bluez_pi(sk)->parent->ack_backlog--;
+ bluez_pi(sk)->parent = NULL;
+ sock_put(sk);
+}
+
+struct sock *bluez_accept_dequeue(struct sock *parent, struct socket *newsock)
+{
+ struct list_head *p, *n;
+ struct bluez_pinfo *pi;
+ struct sock *sk;
+
+ BT_DBG("parent %p", parent);
+
+ list_for_each_safe(p, n, &bluez_pi(parent)->accept_q) {
+ pi = list_entry(p, struct bluez_pinfo, accept_q);
+ sk = bluez_sk(pi);
+
+ lock_sock(sk);
+ if (sk->state == BT_CLOSED) {
+ release_sock(sk);
+ bluez_accept_unlink(sk);
+ continue;
+ }
+
+ if (sk->state == BT_CONNECTED || !newsock) {
+ bluez_accept_unlink(sk);
+ if (newsock)
+ sock_graft(sk, newsock);
+ release_sock(sk);
+ return sk;
+ }
+ release_sock(sk);
+ }
+ return NULL;
+}
+
+int bluez_sock_recvmsg(struct socket *sock, struct msghdr *msg, int len, int flags, struct scm_cookie *scm)
+{
+ int noblock = flags & MSG_DONTWAIT;
+ struct sock *sk = sock->sk;
+ struct sk_buff *skb;
+ int copied, err;
+
+ BT_DBG("sock %p sk %p len %d", sock, sk, len);
+
+ if (flags & (MSG_OOB))
+ return -EOPNOTSUPP;
+
+ if (!(skb = skb_recv_datagram(sk, flags, noblock, &err))) {
+ if (sk->shutdown & RCV_SHUTDOWN)
+ return 0;
+ return err;
+ }
+
+ msg->msg_namelen = 0;
+
+ copied = skb->len;
+ if (len < copied) {
+ msg->msg_flags |= MSG_TRUNC;
+ copied = len;
+ }
+
+ skb->h.raw = skb->data;
+ err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+
+ skb_free_datagram(sk, skb);
+
+ return err ? : copied;
+}
+
+unsigned int bluez_sock_poll(struct file * file, struct socket *sock, poll_table *wait)
+{
+ struct sock *sk = sock->sk;
+ unsigned int mask;
+
+ BT_DBG("sock %p, sk %p", sock, sk);
+
+ poll_wait(file, sk->sleep, wait);
+ mask = 0;
+
+ if (sk->err || !skb_queue_empty(&sk->error_queue))
+ mask |= POLLERR;
+
+ if (sk->shutdown == SHUTDOWN_MASK)
+ mask |= POLLHUP;
+
+ if (!skb_queue_empty(&sk->receive_queue) ||
+ !list_empty(&bluez_pi(sk)->accept_q) ||
+ (sk->shutdown & RCV_SHUTDOWN))
+ mask |= POLLIN | POLLRDNORM;
+
+ if (sk->state == BT_CLOSED)
+ mask |= POLLHUP;
+
+ if (sock_writeable(sk))
+ mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
+ else
+ set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);
+
+ return mask;
+}
+
+int bluez_sock_w4_connect(struct sock *sk, int flags)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ long timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
+ int err = 0;
+
+ BT_DBG("sk %p", sk);
+
+ add_wait_queue(sk->sleep, &wait);
+ while (sk->state != BT_CONNECTED) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (!timeo) {
+ err = -EAGAIN;
+ break;
+ }
+
+ release_sock(sk);
+ timeo = schedule_timeout(timeo);
+ lock_sock(sk);
+
+ err = 0;
+ if (sk->state == BT_CONNECTED)
+ break;
+
+ if (sk->err) {
+ err = sock_error(sk);
+ break;
+ }
+
+ if (signal_pending(current)) {
+ err = sock_intr_errno(timeo);
+ break;
+ }
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(sk->sleep, &wait);
+ return err;
+}
+
struct net_proto_family bluez_sock_family_ops =
{
PF_BLUETOOTH, bluez_sock_create
@@ -129,9 +296,9 @@
int bluez_init(void)
{
- INF("BlueZ HCI Core ver %s Copyright (C) 2000,2001 Qualcomm Inc",
+ BT_INFO("BlueZ Core ver %s Copyright (C) 2000,2001 Qualcomm Inc",
VERSION);
- INF("Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>");
+ BT_INFO("Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>");
proc_mkdir("bluetooth", NULL);
@@ -164,5 +331,6 @@
module_exit(bluez_cleanup);
MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>");
-MODULE_DESCRIPTION("BlueZ HCI Core ver " VERSION);
+MODULE_DESCRIPTION("BlueZ Core ver " VERSION);
+MODULE_LICENSE("GPL");
#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)