[Bluetooth] Read local version information on device init
authorMarcel Holtmann <marcel@holtmann.org>
Sat, 23 Sep 2006 07:57:20 +0000 (09:57 +0200)
committerDavid S. Miller <davem@sunset.davemloft.net>
Fri, 29 Sep 2006 01:01:32 +0000 (18:01 -0700)
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>
include/net/bluetooth/hci_core.h
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sysfs.c

index 263e42b68e8d00eb35f62e94e2fdfb085aa07c86..7451a9c92d9d5d06733498a6baaf43dd26ddc186 100644 (file)
@@ -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;
index 5ed47427790385fc335168857d02082deb2ab498..338ae977a31b2209fb39e1a97d644db185d4597a 100644 (file)
@@ -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);
 
index c6cd243939e611519fc3ef418a5f1e2da2974a60..7518bdbf34cd18df8fc28637a162ee57ab934545 100644 (file)
@@ -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;
 
index 09c61615e961b5d423b58bea608282a875705354..a5c4804b77f4ed5db70441320bd7e70fff33fe41 100644 (file)
@@ -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,