|
@@ -169,6 +169,7 @@ struct hci_conn {
|
|
__u16 link_policy;
|
|
__u16 link_policy;
|
|
__u32 link_mode;
|
|
__u32 link_mode;
|
|
__u8 auth_type;
|
|
__u8 auth_type;
|
|
|
|
+ __u8 sec_level;
|
|
__u8 power_save;
|
|
__u8 power_save;
|
|
unsigned long pend;
|
|
unsigned long pend;
|
|
|
|
|
|
@@ -325,12 +326,11 @@ int hci_conn_del(struct hci_conn *conn);
|
|
void hci_conn_hash_flush(struct hci_dev *hdev);
|
|
void hci_conn_hash_flush(struct hci_dev *hdev);
|
|
void hci_conn_check_pending(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 *dst, __u8 auth_type);
|
|
|
|
|
|
+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_check_link_mode(struct hci_conn *conn);
|
|
-int hci_conn_auth(struct hci_conn *conn);
|
|
|
|
-int hci_conn_encrypt(struct hci_conn *conn);
|
|
|
|
|
|
+int hci_conn_security(struct hci_conn *conn, __u8 sec_level);
|
|
int hci_conn_change_link_key(struct hci_conn *conn);
|
|
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_active_mode(struct hci_conn *conn);
|
|
void hci_conn_enter_sniff_mode(struct hci_conn *conn);
|
|
void hci_conn_enter_sniff_mode(struct hci_conn *conn);
|
|
@@ -470,26 +470,25 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
|
|
|
|
|
|
/* ----- HCI protocols ----- */
|
|
/* ----- HCI protocols ----- */
|
|
struct hci_proto {
|
|
struct hci_proto {
|
|
- char *name;
|
|
|
|
|
|
+ char *name;
|
|
unsigned int id;
|
|
unsigned int id;
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
|
|
|
|
void *priv;
|
|
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 (*connect_cfm) (struct hci_conn *conn, __u8 status);
|
|
int (*disconn_ind) (struct hci_conn *conn, __u8 reason);
|
|
int (*disconn_ind) (struct hci_conn *conn, __u8 reason);
|
|
int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
|
|
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 (*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, __u8 encrypt);
|
|
|
|
|
|
+ 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)
|
|
static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
|
|
{
|
|
{
|
|
register struct hci_proto *hp;
|
|
register struct hci_proto *hp;
|
|
int mask = 0;
|
|
int mask = 0;
|
|
-
|
|
|
|
|
|
+
|
|
hp = hci_proto[HCI_PROTO_L2CAP];
|
|
hp = hci_proto[HCI_PROTO_L2CAP];
|
|
if (hp && hp->connect_ind)
|
|
if (hp && hp->connect_ind)
|
|
mask |= hp->connect_ind(hdev, bdaddr, type);
|
|
mask |= hp->connect_ind(hdev, bdaddr, type);
|
|
@@ -530,14 +529,20 @@ static inline void hci_proto_disconn_ind(struct hci_conn *conn, __u8 reason)
|
|
static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
|
|
static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
|
|
{
|
|
{
|
|
register struct hci_proto *hp;
|
|
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];
|
|
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];
|
|
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, __u8 encrypt)
|
|
static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt)
|
|
@@ -545,12 +550,12 @@ static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u
|
|
register struct hci_proto *hp;
|
|
register struct hci_proto *hp;
|
|
|
|
|
|
hp = hci_proto[HCI_PROTO_L2CAP];
|
|
hp = hci_proto[HCI_PROTO_L2CAP];
|
|
- if (hp && hp->encrypt_cfm)
|
|
|
|
- hp->encrypt_cfm(conn, status, encrypt);
|
|
|
|
|
|
+ if (hp && hp->security_cfm)
|
|
|
|
+ hp->security_cfm(conn, status, encrypt);
|
|
|
|
|
|
hp = hci_proto[HCI_PROTO_SCO];
|
|
hp = hci_proto[HCI_PROTO_SCO];
|
|
- if (hp && hp->encrypt_cfm)
|
|
|
|
- hp->encrypt_cfm(conn, status, encrypt);
|
|
|
|
|
|
+ if (hp && hp->security_cfm)
|
|
|
|
+ hp->security_cfm(conn, status, encrypt);
|
|
}
|
|
}
|
|
|
|
|
|
int hci_register_proto(struct hci_proto *hproto);
|
|
int hci_register_proto(struct hci_proto *hproto);
|
|
@@ -562,8 +567,7 @@ struct hci_cb {
|
|
|
|
|
|
char *name;
|
|
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 (*key_change_cfm) (struct hci_conn *conn, __u8 status);
|
|
void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
|
|
void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
|
|
};
|
|
};
|
|
@@ -571,14 +575,20 @@ struct hci_cb {
|
|
static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
|
|
static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
|
|
{
|
|
{
|
|
struct list_head *p;
|
|
struct list_head *p;
|
|
|
|
+ __u8 encrypt;
|
|
|
|
|
|
hci_proto_auth_cfm(conn, status);
|
|
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);
|
|
read_lock_bh(&hci_cb_list_lock);
|
|
list_for_each(p, &hci_cb_list) {
|
|
list_for_each(p, &hci_cb_list) {
|
|
struct hci_cb *cb = list_entry(p, struct 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);
|
|
read_unlock_bh(&hci_cb_list_lock);
|
|
}
|
|
}
|
|
@@ -592,8 +602,8 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encr
|
|
read_lock_bh(&hci_cb_list_lock);
|
|
read_lock_bh(&hci_cb_list_lock);
|
|
list_for_each(p, &hci_cb_list) {
|
|
list_for_each(p, &hci_cb_list) {
|
|
struct hci_cb *cb = list_entry(p, struct 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);
|
|
read_unlock_bh(&hci_cb_list_lock);
|
|
}
|
|
}
|