Bluetooth: Use the updated key structures for handling LTKs
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / include / net / bluetooth / hci_core.h
index 5e2e984584968f0e6beea90c8657eb1639a1cba2..2649caf4db961f51161b211b078d6107c1f7dfc4 100644 (file)
@@ -44,14 +44,30 @@ struct inquiry_data {
 };
 
 struct inquiry_entry {
-       struct inquiry_entry    *next;
+       struct list_head        all;            /* inq_cache.all */
+       struct list_head        list;           /* unknown or resolve */
+       enum {
+               NAME_NOT_KNOWN,
+               NAME_NEEDED,
+               NAME_PENDING,
+               NAME_KNOWN,
+       } name_state;
        __u32                   timestamp;
        struct inquiry_data     data;
 };
 
-struct inquiry_cache {
-       __u32                   timestamp;
-       struct inquiry_entry    *list;
+struct discovery_state {
+       enum {
+               DISCOVERY_STOPPED,
+               DISCOVERY_STARTING,
+               DISCOVERY_INQUIRY,
+               DISCOVERY_RESOLVING,
+               DISCOVERY_STOPPING,
+       } state;
+       struct list_head all;           /* All devices found during inquiry */
+       struct list_head unknown;       /* Name state not known */
+       struct list_head resolve;       /* Name needs to be resolved */
+       __u32           timestamp;
 };
 
 struct hci_conn_hash {
@@ -72,6 +88,18 @@ struct bt_uuid {
        u8 svc_hint;
 };
 
+struct smp_ltk {
+       struct list_head list;
+       bdaddr_t bdaddr;
+       u8 bdaddr_type;
+       u8 authenticated;
+       u8 type;
+       u8 enc_size;
+       __le16 ediv;
+       u8 rand[8];
+       u8 val[16];
+} __packed;
+
 struct key_master_id {
        __le16 ediv;
        u8 rand[8];
@@ -113,7 +141,6 @@ struct adv_entry {
 struct hci_dev {
        struct list_head list;
        struct mutex    lock;
-       atomic_t        refcnt;
 
        char            name[8];
        unsigned long   flags;
@@ -127,9 +154,8 @@ struct hci_dev {
        __u8            major_class;
        __u8            minor_class;
        __u8            features[8];
-       __u8            extfeatures[8];
+       __u8            host_features[8];
        __u8            commands[64];
-       __u8            ssp_mode;
        __u8            hci_ver;
        __u16           hci_rev;
        __u8            lmp_ver;
@@ -217,7 +243,7 @@ struct hci_dev {
 
        struct list_head        mgmt_pending;
 
-       struct inquiry_cache    inq_cache;
+       struct discovery_state  discovery;
        struct hci_conn_hash    conn_hash;
        struct list_head        blacklist;
 
@@ -225,6 +251,8 @@ struct hci_dev {
 
        struct list_head        link_keys;
 
+       struct list_head        long_term_keys;
+
        struct list_head        remote_oob_data;
 
        struct list_head        adv_entries;
@@ -246,15 +274,12 @@ struct hci_dev {
 
        struct rfkill           *rfkill;
 
-       struct module           *owner;
-
        unsigned long           dev_flags;
 
        int (*open)(struct hci_dev *hdev);
        int (*close)(struct hci_dev *hdev);
        int (*flush)(struct hci_dev *hdev);
        int (*send)(struct sk_buff *skb);
-       void (*destruct)(struct hci_dev *hdev);
        void (*notify)(struct hci_dev *hdev, unsigned int evt);
        int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
 };
@@ -270,11 +295,10 @@ struct hci_conn {
        __u16           state;
        __u8            mode;
        __u8            type;
-       __u8            out;
+       bool            out;
        __u8            attempt;
        __u8            dev_class[3];
        __u8            features[8];
-       __u8            ssp_mode;
        __u16           interval;
        __u16           pkt_type;
        __u16           link_policy;
@@ -286,12 +310,10 @@ struct hci_conn {
        __u8            pin_length;
        __u8            enc_key_size;
        __u8            io_capability;
-       __u8            power_save;
        __u16           disc_timeout;
-       unsigned long   pend;
+       unsigned long   flags;
 
        __u8            remote_cap;
-       __u8            remote_oob;
        __u8            remote_auth;
 
        unsigned int    sent;
@@ -348,21 +370,26 @@ extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
 #define INQUIRY_CACHE_AGE_MAX   (HZ*30)   /* 30 seconds */
 #define INQUIRY_ENTRY_AGE_MAX   (HZ*60)   /* 60 seconds */
 
-static inline void inquiry_cache_init(struct hci_dev *hdev)
+static inline void discovery_init(struct hci_dev *hdev)
 {
-       struct inquiry_cache *c = &hdev->inq_cache;
-       c->list = NULL;
+       hdev->discovery.state = DISCOVERY_STOPPED;
+       INIT_LIST_HEAD(&hdev->discovery.all);
+       INIT_LIST_HEAD(&hdev->discovery.unknown);
+       INIT_LIST_HEAD(&hdev->discovery.resolve);
 }
 
+bool hci_discovery_active(struct hci_dev *hdev);
+
+void hci_discovery_set_state(struct hci_dev *hdev, int state);
+
 static inline int inquiry_cache_empty(struct hci_dev *hdev)
 {
-       struct inquiry_cache *c = &hdev->inq_cache;
-       return c->list == NULL;
+       return list_empty(&hdev->discovery.all);
 }
 
 static inline long inquiry_cache_age(struct hci_dev *hdev)
 {
-       struct inquiry_cache *c = &hdev->inq_cache;
+       struct discovery_state *c = &hdev->discovery;
        return jiffies - c->timestamp;
 }
 
@@ -373,7 +400,15 @@ static inline long inquiry_entry_age(struct inquiry_entry *e)
 
 struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev,
                                                        bdaddr_t *bdaddr);
-void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data);
+struct inquiry_entry *hci_inquiry_cache_lookup_unknown(struct hci_dev *hdev,
+                                                       bdaddr_t *bdaddr);
+struct inquiry_entry *hci_inquiry_cache_lookup_resolve(struct hci_dev *hdev,
+                                                       bdaddr_t *bdaddr,
+                                                       int state);
+void hci_inquiry_cache_update_resolve(struct hci_dev *hdev,
+                                               struct inquiry_entry *ie);
+bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
+                                                       bool name_known);
 
 /* ----- HCI Connections ----- */
 enum {
@@ -384,8 +419,19 @@ enum {
        HCI_CONN_MODE_CHANGE_PEND,
        HCI_CONN_SCO_SETUP_PEND,
        HCI_CONN_LE_SMP_PEND,
+       HCI_CONN_MGMT_CONNECTED,
+       HCI_CONN_SSP_ENABLED,
+       HCI_CONN_POWER_SAVE,
+       HCI_CONN_REMOTE_OOB,
 };
 
+static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
+{
+       struct hci_dev *hdev = conn->hdev;
+       return (test_bit(HCI_SSP_ENABLED, &hdev->flags) &&
+                               test_bit(HCI_CONN_SSP_ENABLED, &conn->flags));
+}
+
 static inline void hci_conn_hash_init(struct hci_dev *hdev)
 {
        struct hci_conn_hash *h = &hdev->conn_hash;
@@ -540,7 +586,7 @@ void hci_conn_put_device(struct hci_conn *conn);
 static inline void hci_conn_hold(struct hci_conn *conn)
 {
        atomic_inc(&conn->refcnt);
-       cancel_delayed_work_sync(&conn->disc_work);
+       cancel_delayed_work(&conn->disc_work);
 }
 
 static inline void hci_conn_put(struct hci_conn *conn)
@@ -559,40 +605,24 @@ static inline void hci_conn_put(struct hci_conn *conn)
                } else {
                        timeo = msecs_to_jiffies(10);
                }
-               cancel_delayed_work_sync(&conn->disc_work);
+               cancel_delayed_work(&conn->disc_work);
                queue_delayed_work(conn->hdev->workqueue,
-                                       &conn->disc_work, jiffies + timeo);
+                                       &conn->disc_work, timeo);
        }
 }
 
 /* ----- HCI Devices ----- */
-static inline void __hci_dev_put(struct hci_dev *d)
+static inline void hci_dev_put(struct hci_dev *d)
 {
-       if (atomic_dec_and_test(&d->refcnt))
-               d->destruct(d);
+       put_device(&d->dev);
 }
 
-/*
- * hci_dev_put and hci_dev_hold are macros to avoid dragging all the
- * overhead of all the modular infrastructure into this header.
- */
-#define hci_dev_put(d)         \
-do {                           \
-       __hci_dev_put(d);       \
-       module_put(d->owner);   \
-} while (0)
-
-static inline struct hci_dev *__hci_dev_hold(struct hci_dev *d)
+static inline struct hci_dev *hci_dev_hold(struct hci_dev *d)
 {
-       atomic_inc(&d->refcnt);
+       get_device(&d->dev);
        return d;
 }
 
-#define hci_dev_hold(d)                                                \
-({                                                             \
-       try_module_get(d->owner) ? __hci_dev_hold(d) : NULL;    \
-})
-
 #define hci_dev_lock(d)                mutex_lock(&d->lock)
 #define hci_dev_unlock(d)      mutex_unlock(&d->lock)
 
@@ -628,11 +658,14 @@ int hci_link_keys_clear(struct hci_dev *hdev);
 struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
 int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
                        bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len);
-struct link_key *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]);
-struct link_key *hci_find_link_key_type(struct hci_dev *hdev,
-                                       bdaddr_t *bdaddr, u8 type);
-int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
-                       u8 key_size, __le16 ediv, u8 rand[8], u8 ltk[16]);
+struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]);
+int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type,
+                               int new_key, u8 authenticated, u8 tk[16],
+                               u8 enc_size, u16 ediv, u8 rand[8]);
+struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
+                                                               u8 addr_type);
+int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int hci_smp_ltks_clear(struct hci_dev *hdev);
 int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
 
 int hci_remote_oob_data_clear(struct hci_dev *hdev);
@@ -676,7 +709,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define lmp_le_capable(dev)        ((dev)->features[4] & LMP_LE)
 
 /* ----- Extended LMP capabilities ----- */
-#define lmp_host_le_capable(dev)   ((dev)->extfeatures[0] & LMP_HOST_LE)
+#define lmp_host_le_capable(dev)   ((dev)->host_features[0] & LMP_HOST_LE)
 
 /* ----- HCI protocols ----- */
 static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
@@ -755,7 +788,7 @@ static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
        if (conn->type != ACL_LINK && conn->type != LE_LINK)
                return;
 
-       if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
+       if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
                return;
 
        encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;
@@ -796,7 +829,7 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
 
        hci_proto_auth_cfm(conn, status);
 
-       if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
+       if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
                return;
 
        encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;
@@ -859,6 +892,42 @@ static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
        read_unlock(&hci_cb_list_lock);
 }
 
+static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type)
+{
+       u8 field_len;
+       size_t parsed;
+
+       for (parsed = 0; parsed < data_len - 1; parsed += field_len) {
+               field_len = data[0];
+
+               if (field_len == 0)
+                       break;
+
+               parsed += field_len + 1;
+
+               if (parsed > data_len)
+                       break;
+
+               if (data[1] == type)
+                       return true;
+
+               data += field_len + 1;
+       }
+
+       return false;
+}
+
+static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
+                                                               u8 data_len)
+{
+       eir[eir_len++] = sizeof(type) + data_len;
+       eir[eir_len++] = type;
+       memcpy(&eir[eir_len], data, data_len);
+       eir_len += data_len;
+
+       return eir_len;
+}
+
 int hci_register_cb(struct hci_cb *hcb);
 int hci_unregister_cb(struct hci_cb *hcb);
 
@@ -887,10 +956,11 @@ int mgmt_connectable(struct hci_dev *hdev, u8 connectable);
 int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status);
 int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
                                                                u8 persistent);
-int mgmt_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
-                                                               u8 addr_type);
-int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
-                                                               u8 addr_type);
+int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
+                                       u8 addr_type, u8 *name, u8 name_len,
+                                       u8 *dev_class);
+int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
+                                               u8 link_type, u8 addr_type);
 int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status);
 int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
                                                u8 addr_type, u8 status);
@@ -915,8 +985,10 @@ int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status);
 int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
                                                u8 *randomizer, u8 status);
 int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
-                               u8 addr_type, u8 *dev_class, s8 rssi, u8 *eir);
-int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *name);
+                                       u8 addr_type, u8 *dev_class, s8 rssi,
+                                       u8 cfm_name, u8 *eir, u16 eir_len);
+int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
+                       u8 addr_type, s8 rssi, u8 *name, u8 name_len);
 int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status);
 int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status);
 int mgmt_discovering(struct hci_dev *hdev, u8 discovering);