[Bluetooth] Integrate services into the driver model
authorMarcel Holtmann <marcel@holtmann.org>
Thu, 6 Jul 2006 11:09:02 +0000 (13:09 +0200)
committerDavid S. Miller <davem@sunset.davemloft.net>
Fri, 29 Sep 2006 01:01:26 +0000 (18:01 -0700)
This patch integrates the services of the Bluetooth protocols RFCOMM,
BNEP and HIDP into the driver model. This makes it possible to assign
the virtual TTY, network and input devices to a specific Bluetooth
connection.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
net/bluetooth/bnep/core.c
net/bluetooth/hidp/core.c
net/bluetooth/rfcomm/tty.c

index e620061fb50fd83cd530167d863b1745f3f7a3fd..2312d050eeedfb66ed382108f0703f6d2dfc5b9d 100644 (file)
@@ -51,6 +51,7 @@
 #include <asm/unaligned.h>
 
 #include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
 
 #include "bnep.h"
@@ -515,6 +516,26 @@ static int bnep_session(void *arg)
        return 0;
 }
 
+static struct device *bnep_get_device(struct bnep_session *session)
+{
+       bdaddr_t *src = &bt_sk(session->sock->sk)->src;
+       bdaddr_t *dst = &bt_sk(session->sock->sk)->dst;
+       struct hci_dev *hdev;
+       struct hci_conn *conn;
+
+       hdev = hci_get_route(dst, src);
+       if (!hdev)
+               return NULL;
+
+       conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
+       if (!conn)
+               return NULL;
+
+       hci_dev_put(hdev);
+
+       return &conn->dev;
+}
+
 int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
 {
        struct net_device *dev;
@@ -534,7 +555,6 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
        if (!dev)
                return -ENOMEM;
 
-
        down_write(&bnep_session_sem);
 
        ss = __bnep_get_session(dst);
@@ -551,7 +571,7 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
        memcpy(s->eh.h_source, &dst, ETH_ALEN);
        memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN);
 
-       s->dev = dev;
+       s->dev   = dev;
        s->sock  = sock;
        s->role  = req->role;
        s->state = BT_CONNECTED;
@@ -568,6 +588,8 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
        bnep_set_default_proto_filter(s);
 #endif
 
+       SET_NETDEV_DEV(dev, bnep_get_device(s));
+
        err = register_netdev(dev);
        if (err) {
                goto failed;
index c6e3a2c27c6ecc864dfa85153b1b42f557957f69..03b5dadb49511f90b0c57ee6d9d677d580c5ef18 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/input.h>
 
 #include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
 
 #include "hidp.h"
@@ -528,6 +529,26 @@ static int hidp_session(void *arg)
        return 0;
 }
 
+static struct device *hidp_get_device(struct hidp_session *session)
+{
+       bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
+       bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
+       struct hci_dev *hdev;
+       struct hci_conn *conn;
+
+       hdev = hci_get_route(dst, src);
+       if (!hdev)
+               return NULL;
+
+       conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
+       if (!conn)
+               return NULL;
+
+       hci_dev_put(hdev);
+
+       return &conn->dev;
+}
+
 static inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req)
 {
        struct input_dev *input = session->input;
@@ -566,6 +587,8 @@ static inline void hidp_setup_input(struct hidp_session *session, struct hidp_co
                input->relbit[0] |= BIT(REL_WHEEL);
        }
 
+       input->cdev.dev = hidp_get_device(session);
+
        input->event = hidp_input_event;
 
        input_register_device(input);
index bd8d671a0ba6f1622ee54e463c2d393b0a6a8943..26f322737db0c83702267b25190dca8fa925c324 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/skbuff.h>
 
 #include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/rfcomm.h>
 
 #ifndef CONFIG_BT_RFCOMM_DEBUG
@@ -161,6 +162,24 @@ static inline struct rfcomm_dev *rfcomm_dev_get(int id)
        return dev;
 }
 
+static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
+{
+       struct hci_dev *hdev;
+       struct hci_conn *conn;
+
+       hdev = hci_get_route(&dev->dst, &dev->src);
+       if (!hdev)
+               return NULL;
+
+       conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
+       if (!conn)
+               return NULL;
+
+       hci_dev_put(hdev);
+
+       return &conn->dev;
+}
+
 static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
 {
        struct rfcomm_dev *dev;
@@ -244,7 +263,7 @@ out:
                return err;
        }
 
-       tty_register_device(rfcomm_tty_driver, dev->id, NULL);
+       tty_register_device(rfcomm_tty_driver, dev->id, rfcomm_get_device(dev));
 
        return dev->id;
 }