aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/net/bluetooth/hci_core.h3
-rw-r--r--net/bluetooth/hci_core.c3
-rw-r--r--net/bluetooth/hci_event.c21
-rw-r--r--net/bluetooth/hci_sysfs.c24
4 files changed, 50 insertions, 1 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 263e42b68e8..7451a9c92d9 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -72,6 +72,9 @@ struct hci_dev {
__u8 type;
bdaddr_t bdaddr;
__u8 features[8];
+ __u8 hci_ver;
+ __u16 hci_rev;
+ __u16 manufacturer;
__u16 voice_setting;
__u16 pkt_type;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 5ed47427790..338ae977a31 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 c6cd243939e..7518bdbf34c 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 09c61615e96..a5c4804b77f 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,