From 4d0eb0049ce94101f7f169f89216ba58475219e2 Mon Sep 17 00:00:00 2001
From: Marcel Holtmann <marcel@holtmann.org>
Date: Thu, 6 Jul 2006 12:34:41 +0200
Subject: [Bluetooth] Remove unused host controller attributes

This patch removes the unused device attribute entries for the Bluetooth
host controllers.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/hci_sysfs.c | 36 +++++++++++++++++++-----------------
 1 file changed, 19 insertions(+), 17 deletions(-)

(limited to 'net/bluetooth')

diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 3987d167f04e..3ccb4b0b8fc2 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -13,16 +13,30 @@
 #define BT_DBG(D...)
 #endif
 
-static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
+static inline char *typetostr(int type)
 {
-	struct hci_dev *hdev = dev_get_drvdata(dev);
-	return sprintf(buf, "%s\n", hdev->name);
+	switch (type) {
+	case HCI_VHCI:
+		return "VIRTUAL";
+	case HCI_USB:
+		return "USB";
+	case HCI_PCCARD:
+		return "PCCARD";
+	case HCI_UART:
+		return "UART";
+	case HCI_RS232:
+		return "RS232";
+	case HCI_PCI:
+		return "PCI";
+	default:
+		return "UNKNOWN";
+	}
 }
 
 static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct hci_dev *hdev = dev_get_drvdata(dev);
-	return sprintf(buf, "%d\n", hdev->type);
+	return sprintf(buf, "%s\n", typetostr(hdev->type));
 }
 
 static ssize_t show_address(struct device *dev, struct device_attribute *attr, char *buf)
@@ -33,12 +47,6 @@ static ssize_t show_address(struct device *dev, struct device_attribute *attr, c
 	return sprintf(buf, "%s\n", batostr(&bdaddr));
 }
 
-static ssize_t show_flags(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct hci_dev *hdev = dev_get_drvdata(dev);
-	return sprintf(buf, "0x%lx\n", hdev->flags);
-}
-
 static ssize_t show_inquiry_cache(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct hci_dev *hdev = dev_get_drvdata(dev);
@@ -141,10 +149,8 @@ static ssize_t store_sniff_min_interval(struct device *dev, struct device_attrib
 	return count;
 }
 
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
 static DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
-static DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL);
 static DEVICE_ATTR(inquiry_cache, S_IRUGO, show_inquiry_cache, NULL);
 
 static DEVICE_ATTR(idle_timeout, S_IRUGO | S_IWUSR,
@@ -155,10 +161,8 @@ static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR,
 				show_sniff_min_interval, store_sniff_min_interval);
 
 static struct device_attribute *bt_attrs[] = {
-	&dev_attr_name,
 	&dev_attr_type,
 	&dev_attr_address,
-	&dev_attr_flags,
 	&dev_attr_inquiry_cache,
 	&dev_attr_idle_timeout,
 	&dev_attr_sniff_max_interval,
@@ -214,11 +218,9 @@ int hci_register_sysfs(struct hci_dev *hdev)
 
 void hci_unregister_sysfs(struct hci_dev *hdev)
 {
-	struct device *dev = &hdev->dev;
-
 	BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
 
-	device_del(dev);
+	device_del(&hdev->dev);
 }
 
 int __init bt_sysfs_init(void)
-- 
cgit v1.2.3


From b219e3ac66183fc9771b94af931fb5fd41d586ec Mon Sep 17 00:00:00 2001
From: Marcel Holtmann <marcel@holtmann.org>
Date: Thu, 6 Jul 2006 12:38:46 +0200
Subject: [Bluetooth] Integrate low-level connections into the driver model

This patch integrates the low-level connections (ACL and SCO) into the
driver model. Every connection is presented as device with the parent
set to its host controller device.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/hci_conn.c  |  8 ++++-
 net/bluetooth/hci_sysfs.c | 79 +++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 84 insertions(+), 3 deletions(-)

(limited to 'net/bluetooth')

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 420ed4d7e57e..7e9515b41cc0 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -179,6 +179,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
 	if (hdev->notify)
 		hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
 
+	hci_conn_add_sysfs(conn);
+
 	tasklet_enable(&hdev->tx_task);
 
 	return conn;
@@ -211,6 +213,8 @@ int hci_conn_del(struct hci_conn *conn)
 
 	tasklet_disable(&hdev->tx_task);
 
+	hci_conn_del_sysfs(conn);
+
 	hci_conn_hash_del(hdev, conn);
 	if (hdev->notify)
 		hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
@@ -221,7 +225,9 @@ int hci_conn_del(struct hci_conn *conn)
 
 	hci_dev_put(hdev);
 
-	kfree(conn);
+	/* will free via device release */
+	put_device(&conn->dev);
+
 	return 0;
 }
 
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 3ccb4b0b8fc2..58df4360d242 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -170,6 +170,32 @@ static struct device_attribute *bt_attrs[] = {
 	NULL
 };
 
+static ssize_t show_conn_type(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct hci_conn *conn = dev_get_drvdata(dev);
+	return sprintf(buf, "%s\n", conn->type == ACL_LINK ? "ACL" : "SCO");
+}
+
+static ssize_t show_conn_address(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct hci_conn *conn = dev_get_drvdata(dev);
+	bdaddr_t bdaddr;
+	baswap(&bdaddr, &conn->dst);
+	return sprintf(buf, "%s\n", batostr(&bdaddr));
+}
+
+#define CONN_ATTR(_name,_mode,_show,_store) \
+struct device_attribute conn_attr_##_name = __ATTR(_name,_mode,_show,_store)
+
+static CONN_ATTR(type, S_IRUGO, show_conn_type, NULL);
+static CONN_ATTR(address, S_IRUGO, show_conn_address, NULL);
+
+static struct device_attribute *conn_attrs[] = {
+	&conn_attr_type,
+	&conn_attr_address,
+	NULL
+};
+
 struct class *bt_class = NULL;
 EXPORT_SYMBOL_GPL(bt_class);
 
@@ -181,8 +207,57 @@ static struct platform_device *bt_platform;
 
 static void bt_release(struct device *dev)
 {
-	struct hci_dev *hdev = dev_get_drvdata(dev);
-	kfree(hdev);
+	void *data = dev_get_drvdata(dev);
+	kfree(data);
+}
+
+static void add_conn(void *data)
+{
+	struct hci_conn *conn = data;
+	int i;
+
+	device_register(&conn->dev);
+
+	for (i = 0; conn_attrs[i]; i++)
+		device_create_file(&conn->dev, conn_attrs[i]);
+}
+
+void hci_conn_add_sysfs(struct hci_conn *conn)
+{
+	struct hci_dev *hdev = conn->hdev;
+	bdaddr_t *ba = &conn->dst;
+
+	BT_DBG("conn %p", conn);
+
+	conn->dev.parent  = &hdev->dev;
+	conn->dev.release = bt_release;
+
+	snprintf(conn->dev.bus_id, BUS_ID_SIZE,
+			"%s%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
+			conn->type == ACL_LINK ? "acl" : "sco",
+			ba->b[5], ba->b[4], ba->b[3],
+			ba->b[2], ba->b[1], ba->b[0]);
+
+	dev_set_drvdata(&conn->dev, conn);
+
+	INIT_WORK(&conn->work, add_conn, (void *) conn);
+
+	schedule_work(&conn->work);
+}
+
+static void del_conn(void *data)
+{
+	struct hci_conn *conn = data;
+	device_del(&conn->dev);
+}
+
+void hci_conn_del_sysfs(struct hci_conn *conn)
+{
+	BT_DBG("conn %p", conn);
+
+	INIT_WORK(&conn->work, del_conn, (void *) conn);
+
+	schedule_work(&conn->work);
 }
 
 int hci_register_sysfs(struct hci_dev *hdev)
-- 
cgit v1.2.3


From 0a85b964e141a4b8db6eaf500ceace12f8f52f93 Mon Sep 17 00:00:00 2001
From: Marcel Holtmann <marcel@holtmann.org>
Date: Thu, 6 Jul 2006 13:09:02 +0200
Subject: [Bluetooth] Integrate services into the driver model

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  | 26 ++++++++++++++++++++++++--
 net/bluetooth/hidp/core.c  | 23 +++++++++++++++++++++++
 net/bluetooth/rfcomm/tty.c | 21 ++++++++++++++++++++-
 3 files changed, 67 insertions(+), 3 deletions(-)

(limited to 'net/bluetooth')

diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index e620061fb50f..2312d050eeed 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -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;
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index c6e3a2c27c6e..03b5dadb4951 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -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);
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index bd8d671a0ba6..26f322737db0 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -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;
 }
-- 
cgit v1.2.3


From 0ac53939a06c610b394aeb0211b985804f2d2da3 Mon Sep 17 00:00:00 2001
From: Marcel Holtmann <marcel@holtmann.org>
Date: Sat, 8 Jul 2006 13:57:15 +0200
Subject: [Bluetooth] Add HCI device identifier for SDIO cards

This patch assigns the next free HCI device identifier to Bluetooth
devices based on the SDIO interface.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/hci_sysfs.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

(limited to 'net/bluetooth')

diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 58df4360d242..09c61615e961 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -16,7 +16,7 @@
 static inline char *typetostr(int type)
 {
 	switch (type) {
-	case HCI_VHCI:
+	case HCI_VIRTUAL:
 		return "VIRTUAL";
 	case HCI_USB:
 		return "USB";
@@ -28,6 +28,8 @@ static inline char *typetostr(int type)
 		return "RS232";
 	case HCI_PCI:
 		return "PCI";
+	case HCI_SDIO:
+		return "SDIO";
 	default:
 		return "UNKNOWN";
 	}
-- 
cgit v1.2.3


From defc761bc25643eeedee3abd6af0079ef214b55d Mon Sep 17 00:00:00 2001
From: Marcel Holtmann <marcel@holtmann.org>
Date: Thu, 21 Sep 2006 16:04:00 +0200
Subject: [Bluetooth] Handle command complete event for exit periodic inquiry

The command complete event of the exit periodic inquiry command must
clear the HCI_INQUIRY flag and finish the HCI request.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/hci_event.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'net/bluetooth')

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 3896dabab11d..c6cd243939e6 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -62,6 +62,7 @@ static void hci_cc_link_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb
 
 	switch (ocf) {
 	case OCF_INQUIRY_CANCEL:
+	case OCF_EXIT_PERIODIC_INQ:
 		status = *((__u8 *) skb->data);
 
 		if (status) {
-- 
cgit v1.2.3


From b4c612a473eb816dff6e5ab6820dff338057aa8d Mon Sep 17 00:00:00 2001
From: Marcel Holtmann <marcel@holtmann.org>
Date: Sat, 23 Sep 2006 09:54:38 +0200
Subject: [Bluetooth] Return EINPROGRESS for non-blocking socket calls

In case of non-blocking socket calls we should return EINPROGRESS
and not EAGAIN.

Signed-off-by: Ulisses Furquim <ulissesf@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/af_bluetooth.c | 2 +-
 net/bluetooth/rfcomm/core.c  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

(limited to 'net/bluetooth')

diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 788ea7a2b744..305a099b7477 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -276,7 +276,7 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
 		set_current_state(TASK_INTERRUPTIBLE);
 
 		if (!timeo) {
-			err = -EAGAIN;
+			err = -EINPROGRESS;
 			break;
 		}
 
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 332dd8f436ea..468df3b953f6 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -644,7 +644,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst
 	addr.l2_family = AF_BLUETOOTH;
 	addr.l2_psm    = htobs(RFCOMM_PSM);
 	*err = sock->ops->connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK);
-	if (*err == 0 || *err == -EAGAIN)
+	if (*err == 0 || *err == -EINPROGRESS)
 		return s;
 
 	rfcomm_session_del(s);
-- 
cgit v1.2.3


From 1143e5a6d4d69cd36d44e0184769aa2b17041a10 Mon Sep 17 00:00:00 2001
From: Marcel Holtmann <marcel@holtmann.org>
Date: Sat, 23 Sep 2006 09:57:20 +0200
Subject: [Bluetooth] Read local version information on device init

The local version information are needed to identify certain feature
sets of devices. They must be read on device init and stored for later
use. It is also possible to access them through the device model.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/hci_core.c  |  3 +++
 net/bluetooth/hci_event.c | 21 ++++++++++++++++++++-
 net/bluetooth/hci_sysfs.c | 24 ++++++++++++++++++++++++
 3 files changed, 47 insertions(+), 1 deletion(-)

(limited to 'net/bluetooth')

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 5ed474277903..338ae977a31b 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -206,6 +206,9 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
 	/* Read Local Supported Features */
 	hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_LOCAL_FEATURES, 0, NULL);
 
+	/* Read Local Version */
+	hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_LOCAL_VERSION, 0, NULL);
+
 	/* Read Buffer Size (ACL mtu, max pkt, etc.) */
 	hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_BUFFER_SIZE, 0, NULL);
 
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index c6cd243939e6..7518bdbf34cd 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -298,6 +298,7 @@ static void hci_cc_host_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb
 /* Command Complete OGF INFO_PARAM  */
 static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb)
 {
+	struct hci_rp_read_loc_version *lv;
 	struct hci_rp_read_local_features *lf;
 	struct hci_rp_read_buffer_size *bs;
 	struct hci_rp_read_bd_addr *ba;
@@ -305,6 +306,23 @@ static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *s
 	BT_DBG("%s ocf 0x%x", hdev->name, ocf);
 
 	switch (ocf) {
+	case OCF_READ_LOCAL_VERSION:
+		lv = (struct hci_rp_read_loc_version *) skb->data;
+
+		if (lv->status) {
+			BT_DBG("%s READ_LOCAL_VERSION failed %d", hdev->name, lf->status);
+			break;
+		}
+
+		hdev->hci_ver = lv->hci_ver;
+		hdev->hci_rev = btohs(lv->hci_rev);
+		hdev->manufacturer = btohs(lv->manufacturer);
+
+		BT_DBG("%s: manufacturer %d hci_ver %d hci_rev %d", hdev->name,
+				hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
+
+		break;
+
 	case OCF_READ_LOCAL_FEATURES:
 		lf = (struct hci_rp_read_local_features *) skb->data;
 
@@ -329,7 +347,8 @@ static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *s
 		if (hdev->features[1] & LMP_HV3)
 			hdev->pkt_type |= (HCI_HV3);
 
-		BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name, lf->features[0], lf->features[1], lf->features[2]);
+		BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name,
+				lf->features[0], lf->features[1], lf->features[2]);
 
 		break;
 
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 09c61615e961..a5c4804b77f4 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -49,6 +49,24 @@ static ssize_t show_address(struct device *dev, struct device_attribute *attr, c
 	return sprintf(buf, "%s\n", batostr(&bdaddr));
 }
 
+static ssize_t show_manufacturer(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct hci_dev *hdev = dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", hdev->manufacturer);
+}
+
+static ssize_t show_hci_version(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct hci_dev *hdev = dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", hdev->hci_ver);
+}
+
+static ssize_t show_hci_revision(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct hci_dev *hdev = dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", hdev->hci_rev);
+}
+
 static ssize_t show_inquiry_cache(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct hci_dev *hdev = dev_get_drvdata(dev);
@@ -153,6 +171,9 @@ static ssize_t store_sniff_min_interval(struct device *dev, struct device_attrib
 
 static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
 static DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
+static DEVICE_ATTR(manufacturer, S_IRUGO, show_manufacturer, NULL);
+static DEVICE_ATTR(hci_version, S_IRUGO, show_hci_version, NULL);
+static DEVICE_ATTR(hci_revision, S_IRUGO, show_hci_revision, NULL);
 static DEVICE_ATTR(inquiry_cache, S_IRUGO, show_inquiry_cache, NULL);
 
 static DEVICE_ATTR(idle_timeout, S_IRUGO | S_IWUSR,
@@ -165,6 +186,9 @@ static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR,
 static struct device_attribute *bt_attrs[] = {
 	&dev_attr_type,
 	&dev_attr_address,
+	&dev_attr_manufacturer,
+	&dev_attr_hci_version,
+	&dev_attr_hci_revision,
 	&dev_attr_inquiry_cache,
 	&dev_attr_idle_timeout,
 	&dev_attr_sniff_max_interval,
-- 
cgit v1.2.3


From 6ac59344ef25d5f0ebadb5663cf700d25d2a3886 Mon Sep 17 00:00:00 2001
From: Marcel Holtmann <marcel@holtmann.org>
Date: Tue, 26 Sep 2006 09:43:48 +0200
Subject: [Bluetooth] Support create connection cancel command

In case of non-blocking connects it is possible that the last user
of an ACL link quits before the connection has been fully established.
This will lead to a race condition where the internal state of a
connection is closed, but the actual link has been established and is
active. In case of Bluetooth 1.2 and later devices it is possible to
call create connection cancel to abort the connect. For older devices
the disconnect timer will be used to trigger the needed disconnect.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/hci_conn.c  | 31 +++++++++++++++++++++++++++----
 net/bluetooth/hci_event.c |  4 ++++
 2 files changed, 31 insertions(+), 4 deletions(-)

(limited to 'net/bluetooth')

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 7e9515b41cc0..90e3a285a17e 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -84,6 +84,20 @@ static void hci_acl_connect(struct hci_conn *conn)
 	hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp);
 }
 
+static void hci_acl_connect_cancel(struct hci_conn *conn)
+{
+	struct hci_cp_create_conn_cancel cp;
+
+	BT_DBG("%p", conn);
+
+	if (conn->hdev->hci_ver < 2)
+		return;
+
+	bacpy(&cp.bdaddr, &conn->dst);
+	hci_send_cmd(conn->hdev, OGF_LINK_CTL,
+				OCF_CREATE_CONN_CANCEL, sizeof(cp), &cp);
+}
+
 void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
 {
 	struct hci_cp_disconnect cp;
@@ -94,7 +108,8 @@ void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
 
 	cp.handle = __cpu_to_le16(conn->handle);
 	cp.reason = reason;
-	hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_DISCONNECT, sizeof(cp), &cp);
+	hci_send_cmd(conn->hdev, OGF_LINK_CTL,
+				OCF_DISCONNECT, sizeof(cp), &cp);
 }
 
 void hci_add_sco(struct hci_conn *conn, __u16 handle)
@@ -124,12 +139,20 @@ static void hci_conn_timeout(unsigned long arg)
 		return;
 
 	hci_dev_lock(hdev);
- 	if (conn->state == BT_CONNECTED)
+
+	switch (conn->state) {
+	case BT_CONNECT:
+		hci_acl_connect_cancel(conn);
+		break;
+ 	case BT_CONNECTED:
 		hci_acl_disconn(conn, 0x13);
-	else
+		break;
+	default:
 		conn->state = BT_CLOSED;
+		break;
+	}
+
 	hci_dev_unlock(hdev);
-	return;
 }
 
 static void hci_conn_idle(unsigned long arg)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 7518bdbf34cd..bb25484b8747 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -750,6 +750,8 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
 			conn->link_mode |= HCI_LM_ENCRYPT;
 
+		hci_conn_hold(conn);
+
 		/* Get remote features */
 		if (conn->type == ACL_LINK) {
 			struct hci_cp_read_remote_features cp;
@@ -778,6 +780,8 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
 			hci_send_cmd(hdev, OGF_LINK_CTL,
 				OCF_CHANGE_CONN_PTYPE, sizeof(cp), &cp);
 		}
+
+		hci_conn_put(conn);
 	} else
 		conn->state = BT_CLOSED;
 
-- 
cgit v1.2.3


From 37e97b4ef0d18b77a45a4714154daf3499206654 Mon Sep 17 00:00:00 2001
From: Marcel Holtmann <marcel@holtmann.org>
Date: Thu, 28 Sep 2006 15:29:09 -0700
Subject: [Bluetooth]: Don't update disconnect timer for incoming connections

In the case of device pairing the only safe method is to establish
a low-level ACL link. In this case, the remote side should not use
the disconnect timer to give the other side the chance to enter the
PIN code. If the disconnect timer is used, the connection will be
dropped to soon, because it is impossible to identify an actual user
of this link.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/bluetooth/hci_event.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'net/bluetooth')

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index bb25484b8747..d43d0c890975 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -750,8 +750,6 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
 		if (test_bit(HCI_ENCRYPT, &hdev->flags))
 			conn->link_mode |= HCI_LM_ENCRYPT;
 
-		hci_conn_hold(conn);
-
 		/* Get remote features */
 		if (conn->type == ACL_LINK) {
 			struct hci_cp_read_remote_features cp;
@@ -779,9 +777,11 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
 
 			hci_send_cmd(hdev, OGF_LINK_CTL,
 				OCF_CHANGE_CONN_PTYPE, sizeof(cp), &cp);
+		} else {
+			/* Update disconnect timer */
+			hci_conn_hold(conn);
+			hci_conn_put(conn);
 		}
-
-		hci_conn_put(conn);
 	} else
 		conn->state = BT_CLOSED;
 
-- 
cgit v1.2.3


From 860e13b5c591f1040b76fff57a6a3d6ca9633983 Mon Sep 17 00:00:00 2001
From: Arnaud Patard <arnaud.patard@rtp-net.org>
Date: Thu, 28 Sep 2006 15:29:37 -0700
Subject: [Bluetooth]: Fix section mismatch of bt_sysfs_cleanup()

The bt_sysfs_cleanup() is marked with __exit attribute, but it will
be called from an __init function in the error case. So the __exit
attribute must be removed.

Signed-off-by: Arnaud Patard <arnaud.patard@rtp-net.org>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/bluetooth/hci_sysfs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'net/bluetooth')

diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index a5c4804b77f4..989b22d9042e 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -348,7 +348,7 @@ int __init bt_sysfs_init(void)
 	return 0;
 }
 
-void __exit bt_sysfs_cleanup(void)
+void bt_sysfs_cleanup(void)
 {
 	class_destroy(bt_class);
 
-- 
cgit v1.2.3