nl80211: Event notifications for MLME events
[safe/jmp/linux-2.6] / include / net / bluetooth / hci_core.h
index 0db89ed..01f9316 100644 (file)
@@ -40,6 +40,7 @@ struct inquiry_data {
        __u8            dev_class[3];
        __le16          clock_offset;
        __s8            rssi;
+       __u8            ssp_mode;
 };
 
 struct inquiry_entry {
@@ -75,6 +76,7 @@ struct hci_dev {
        __u8            dev_class[3];
        __u8            features[8];
        __u8            commands[64];
+       __u8            ssp_mode;
        __u8            hci_ver;
        __u16           hci_rev;
        __u16           manufacturer;
@@ -161,9 +163,13 @@ struct hci_conn {
        __u8             attempt;
        __u8             dev_class[3];
        __u8             features[8];
+       __u8             ssp_mode;
        __u16            interval;
+       __u16            pkt_type;
        __u16            link_policy;
        __u32            link_mode;
+       __u8             auth_type;
+       __u8             sec_level;
        __u8             power_save;
        unsigned long    pend;
 
@@ -313,17 +319,18 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
 void hci_acl_connect(struct hci_conn *conn);
 void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
 void hci_add_sco(struct hci_conn *conn, __u16 handle);
+void hci_setup_sync(struct hci_conn *conn, __u16 handle);
 
 struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);
 int hci_conn_del(struct hci_conn *conn);
 void hci_conn_hash_flush(struct hci_dev *hdev);
 void hci_conn_check_pending(struct hci_dev *hdev);
 
-struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *src);
-int hci_conn_auth(struct hci_conn *conn);
-int hci_conn_encrypt(struct hci_conn *conn);
+struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type);
+int hci_conn_check_link_mode(struct hci_conn *conn);
+int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type);
 int hci_conn_change_link_key(struct hci_conn *conn);
-int hci_conn_switch_role(struct hci_conn *conn, uint8_t role);
+int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
 
 void hci_conn_enter_active_mode(struct hci_conn *conn);
 void hci_conn_enter_sniff_mode(struct hci_conn *conn);
@@ -343,7 +350,7 @@ static inline void hci_conn_put(struct hci_conn *conn)
                        if (conn->state == BT_CONNECTED) {
                                timeo = msecs_to_jiffies(HCI_DISCONN_TIMEOUT);
                                if (!conn->out)
-                                       timeo *= 2;
+                                       timeo *= 5;
                        } else
                                timeo = msecs_to_jiffies(10);
                } else
@@ -417,6 +424,7 @@ int hci_get_dev_list(void __user *arg);
 int hci_get_dev_info(void __user *arg);
 int hci_get_conn_list(void __user *arg);
 int hci_get_conn_info(struct hci_dev *hdev, void __user *arg);
+int hci_get_auth_info(struct hci_dev *hdev, void __user *arg);
 int hci_inquiry(void __user *arg);
 
 void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
@@ -458,29 +466,30 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define lmp_sniff_capable(dev)     ((dev)->features[0] & LMP_SNIFF)
 #define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
 #define lmp_esco_capable(dev)      ((dev)->features[3] & LMP_ESCO)
+#define lmp_ssp_capable(dev)       ((dev)->features[6] & LMP_SIMPLE_PAIR)
 
 /* ----- HCI protocols ----- */
 struct hci_proto {
-       char            *name;
+       char            *name;
        unsigned int    id;
        unsigned long   flags;
 
        void            *priv;
 
-       int (*connect_ind)      (struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type);
+       int (*connect_ind)      (struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type);
        int (*connect_cfm)      (struct hci_conn *conn, __u8 status);
-       int (*disconn_ind)      (struct hci_conn *conn, __u8 reason);
+       int (*disconn_ind)      (struct hci_conn *conn);
+       int (*disconn_cfm)      (struct hci_conn *conn, __u8 reason);
        int (*recv_acldata)     (struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
        int (*recv_scodata)     (struct hci_conn *conn, struct sk_buff *skb);
-       int (*auth_cfm)         (struct hci_conn *conn, __u8 status);
-       int (*encrypt_cfm)      (struct hci_conn *conn, __u8 status);
+       int (*security_cfm)     (struct hci_conn *conn, __u8 status, __u8 encrypt);
 };
 
 static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
 {
        register struct hci_proto *hp;
        int mask = 0;
-       
+
        hp = hci_proto[HCI_PROTO_L2CAP];
        if (hp && hp->connect_ind)
                mask |= hp->connect_ind(hdev, bdaddr, type);
@@ -505,43 +514,65 @@ static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status)
                hp->connect_cfm(conn, status);
 }
 
-static inline void hci_proto_disconn_ind(struct hci_conn *conn, __u8 reason)
+static inline int hci_proto_disconn_ind(struct hci_conn *conn)
 {
        register struct hci_proto *hp;
+       int reason = 0x13;
 
        hp = hci_proto[HCI_PROTO_L2CAP];
        if (hp && hp->disconn_ind)
-               hp->disconn_ind(conn, reason);
+               reason = hp->disconn_ind(conn);
 
        hp = hci_proto[HCI_PROTO_SCO];
        if (hp && hp->disconn_ind)
-               hp->disconn_ind(conn, reason);
+               reason = hp->disconn_ind(conn);
+
+       return reason;
+}
+
+static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason)
+{
+       register struct hci_proto *hp;
+
+       hp = hci_proto[HCI_PROTO_L2CAP];
+       if (hp && hp->disconn_cfm)
+               hp->disconn_cfm(conn, reason);
+
+       hp = hci_proto[HCI_PROTO_SCO];
+       if (hp && hp->disconn_cfm)
+               hp->disconn_cfm(conn, reason);
 }
 
 static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
 {
        register struct hci_proto *hp;
+       __u8 encrypt;
+
+       if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
+               return;
+
+       encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;
 
        hp = hci_proto[HCI_PROTO_L2CAP];
-       if (hp && hp->auth_cfm)
-               hp->auth_cfm(conn, status);
+       if (hp && hp->security_cfm)
+               hp->security_cfm(conn, status, encrypt);
 
        hp = hci_proto[HCI_PROTO_SCO];
-       if (hp && hp->auth_cfm)
-               hp->auth_cfm(conn, status);
+       if (hp && hp->security_cfm)
+               hp->security_cfm(conn, status, encrypt);
 }
 
-static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status)
+static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt)
 {
        register struct hci_proto *hp;
 
        hp = hci_proto[HCI_PROTO_L2CAP];
-       if (hp && hp->encrypt_cfm)
-               hp->encrypt_cfm(conn, status);
+       if (hp && hp->security_cfm)
+               hp->security_cfm(conn, status, encrypt);
 
        hp = hci_proto[HCI_PROTO_SCO];
-       if (hp && hp->encrypt_cfm)
-               hp->encrypt_cfm(conn, status);
+       if (hp && hp->security_cfm)
+               hp->security_cfm(conn, status, encrypt);
 }
 
 int hci_register_proto(struct hci_proto *hproto);
@@ -553,8 +584,7 @@ struct hci_cb {
 
        char *name;
 
-       void (*auth_cfm)        (struct hci_conn *conn, __u8 status);
-       void (*encrypt_cfm)     (struct hci_conn *conn, __u8 status, __u8 encrypt);
+       void (*security_cfm)    (struct hci_conn *conn, __u8 status, __u8 encrypt);
        void (*key_change_cfm)  (struct hci_conn *conn, __u8 status);
        void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
 };
@@ -562,14 +592,20 @@ struct hci_cb {
 static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
 {
        struct list_head *p;
+       __u8 encrypt;
 
        hci_proto_auth_cfm(conn, status);
 
+       if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
+               return;
+
+       encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;
+
        read_lock_bh(&hci_cb_list_lock);
        list_for_each(p, &hci_cb_list) {
                struct hci_cb *cb = list_entry(p, struct hci_cb, list);
-               if (cb->auth_cfm)
-                       cb->auth_cfm(conn, status);
+               if (cb->security_cfm)
+                       cb->security_cfm(conn, status, encrypt);
        }
        read_unlock_bh(&hci_cb_list_lock);
 }
@@ -578,13 +614,16 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encr
 {
        struct list_head *p;
 
-       hci_proto_encrypt_cfm(conn, status);
+       if (conn->sec_level == BT_SECURITY_SDP)
+               conn->sec_level = BT_SECURITY_LOW;
+
+       hci_proto_encrypt_cfm(conn, status, encrypt);
 
        read_lock_bh(&hci_cb_list_lock);
        list_for_each(p, &hci_cb_list) {
                struct hci_cb *cb = list_entry(p, struct hci_cb, list);
-               if (cb->encrypt_cfm)
-                       cb->encrypt_cfm(conn, status, encrypt);
+               if (cb->security_cfm)
+                       cb->security_cfm(conn, status, encrypt);
        }
        read_unlock_bh(&hci_cb_list_lock);
 }