diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 263e42b68e8d..7451a9c92d9d 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 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,