Bluetooth: Add LE Local Features reading support
authorJohan Hedberg <johan.hedberg@intel.com>
Tue, 22 Jan 2013 12:01:59 +0000 (14:01 +0200)
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>
Wed, 23 Jan 2013 04:08:18 +0000 (02:08 -0200)
To be able to make the appropriate decisions for some LE procedures we
need to know the LE features that the local controller supports.
Therefore, it's important to have the LE Read Local Supported Features
HCI comand as part of the HCI init sequence.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
include/net/bluetooth/hci.h
include/net/bluetooth/hci_core.h
net/bluetooth/hci_event.c

index 45eee08157bb926b316519da7cbba8cae49d2e71..521eefa033e77bc747bd95c71cf3f97848eab314 100644 (file)
@@ -943,6 +943,12 @@ struct hci_rp_le_read_buffer_size {
        __u8     le_max_pkt;
 } __packed;
 
+#define HCI_OP_LE_READ_LOCAL_FEATURES  0x2003
+struct hci_rp_le_read_local_features {
+       __u8     status;
+       __u8     features[8];
+} __packed;
+
 #define HCI_OP_LE_READ_ADV_TX_POWER    0x2007
 struct hci_rp_le_read_adv_tx_power {
        __u8    status;
index 769a740c104c5c28eca38504eba3eded8a767758..3f607c94e21370f5d70cf47508bd0f7c4ffb0a71 100644 (file)
@@ -152,6 +152,7 @@ struct hci_dev {
        __u8            minor_class;
        __u8            features[8];
        __u8            host_features[8];
+       __u8            le_features[8];
        __u8            commands[64];
        __u8            hci_ver;
        __u16           hci_rev;
index 705078a0cc393c023054ad1d55aea1a548e3da1d..07c8c79a9fd17637512b457060f56afd380e54b0 100644 (file)
@@ -609,6 +609,9 @@ static void le_setup(struct hci_dev *hdev)
        /* Read LE Buffer Size */
        hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
 
+       /* Read LE Local Supported Features */
+       hci_send_cmd(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, 0, NULL);
+
        /* Read LE Advertising Channel TX Power */
        hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
 }
@@ -1090,6 +1093,19 @@ static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
        hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
 }
 
+static void hci_cc_le_read_local_features(struct hci_dev *hdev,
+                                         struct sk_buff *skb)
+{
+       struct hci_rp_le_read_local_features *rp = (void *) skb->data;
+
+       BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+
+       if (!rp->status)
+               memcpy(hdev->le_features, rp->features, 8);
+
+       hci_req_complete(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, rp->status);
+}
+
 static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
                                        struct sk_buff *skb)
 {
@@ -2628,6 +2644,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
                hci_cc_le_read_buffer_size(hdev, skb);
                break;
 
+       case HCI_OP_LE_READ_LOCAL_FEATURES:
+               hci_cc_le_read_local_features(hdev, skb);
+               break;
+
        case HCI_OP_LE_READ_ADV_TX_POWER:
                hci_cc_le_read_adv_tx_power(hdev, skb);
                break;