diff options
Diffstat (limited to 'include/net/bluetooth')
-rw-r--r-- | include/net/bluetooth/hci_core.h | 146 | ||||
-rw-r--r-- | include/net/bluetooth/mgmt.h | 7 |
2 files changed, 56 insertions, 97 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 52863c3e0b13..acec9140c3f9 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -108,7 +108,7 @@ struct bt_uuid { | |||
108 | struct smp_csrk { | 108 | struct smp_csrk { |
109 | bdaddr_t bdaddr; | 109 | bdaddr_t bdaddr; |
110 | u8 bdaddr_type; | 110 | u8 bdaddr_type; |
111 | u8 master; | 111 | u8 type; |
112 | u8 val[16]; | 112 | u8 val[16]; |
113 | }; | 113 | }; |
114 | 114 | ||
@@ -373,6 +373,7 @@ struct hci_dev { | |||
373 | int (*close)(struct hci_dev *hdev); | 373 | int (*close)(struct hci_dev *hdev); |
374 | int (*flush)(struct hci_dev *hdev); | 374 | int (*flush)(struct hci_dev *hdev); |
375 | int (*setup)(struct hci_dev *hdev); | 375 | int (*setup)(struct hci_dev *hdev); |
376 | int (*shutdown)(struct hci_dev *hdev); | ||
376 | int (*send)(struct hci_dev *hdev, struct sk_buff *skb); | 377 | int (*send)(struct hci_dev *hdev, struct sk_buff *skb); |
377 | void (*notify)(struct hci_dev *hdev, unsigned int evt); | 378 | void (*notify)(struct hci_dev *hdev, unsigned int evt); |
378 | void (*hw_error)(struct hci_dev *hdev, u8 code); | 379 | void (*hw_error)(struct hci_dev *hdev, u8 code); |
@@ -498,19 +499,14 @@ struct hci_conn_params { | |||
498 | extern struct list_head hci_dev_list; | 499 | extern struct list_head hci_dev_list; |
499 | extern struct list_head hci_cb_list; | 500 | extern struct list_head hci_cb_list; |
500 | extern rwlock_t hci_dev_list_lock; | 501 | extern rwlock_t hci_dev_list_lock; |
501 | extern rwlock_t hci_cb_list_lock; | 502 | extern struct mutex hci_cb_list_lock; |
502 | 503 | ||
503 | /* ----- HCI interface to upper protocols ----- */ | 504 | /* ----- HCI interface to upper protocols ----- */ |
504 | int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr); | 505 | int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr); |
505 | void l2cap_connect_cfm(struct hci_conn *hcon, u8 status); | ||
506 | int l2cap_disconn_ind(struct hci_conn *hcon); | 506 | int l2cap_disconn_ind(struct hci_conn *hcon); |
507 | void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason); | ||
508 | int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt); | ||
509 | int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags); | 507 | int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags); |
510 | 508 | ||
511 | int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags); | 509 | int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags); |
512 | void sco_connect_cfm(struct hci_conn *hcon, __u8 status); | ||
513 | void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason); | ||
514 | int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb); | 510 | int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb); |
515 | 511 | ||
516 | /* ----- Inquiry cache ----- */ | 512 | /* ----- Inquiry cache ----- */ |
@@ -1050,28 +1046,6 @@ static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
1050 | } | 1046 | } |
1051 | } | 1047 | } |
1052 | 1048 | ||
1053 | static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status) | ||
1054 | { | ||
1055 | switch (conn->type) { | ||
1056 | case ACL_LINK: | ||
1057 | case LE_LINK: | ||
1058 | l2cap_connect_cfm(conn, status); | ||
1059 | break; | ||
1060 | |||
1061 | case SCO_LINK: | ||
1062 | case ESCO_LINK: | ||
1063 | sco_connect_cfm(conn, status); | ||
1064 | break; | ||
1065 | |||
1066 | default: | ||
1067 | BT_ERR("unknown link type %d", conn->type); | ||
1068 | break; | ||
1069 | } | ||
1070 | |||
1071 | if (conn->connect_cfm_cb) | ||
1072 | conn->connect_cfm_cb(conn, status); | ||
1073 | } | ||
1074 | |||
1075 | static inline int hci_proto_disconn_ind(struct hci_conn *conn) | 1049 | static inline int hci_proto_disconn_ind(struct hci_conn *conn) |
1076 | { | 1050 | { |
1077 | if (conn->type != ACL_LINK && conn->type != LE_LINK) | 1051 | if (conn->type != ACL_LINK && conn->type != LE_LINK) |
@@ -1080,91 +1054,69 @@ static inline int hci_proto_disconn_ind(struct hci_conn *conn) | |||
1080 | return l2cap_disconn_ind(conn); | 1054 | return l2cap_disconn_ind(conn); |
1081 | } | 1055 | } |
1082 | 1056 | ||
1083 | static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason) | 1057 | /* ----- HCI callbacks ----- */ |
1084 | { | 1058 | struct hci_cb { |
1085 | switch (conn->type) { | 1059 | struct list_head list; |
1086 | case ACL_LINK: | ||
1087 | case LE_LINK: | ||
1088 | l2cap_disconn_cfm(conn, reason); | ||
1089 | break; | ||
1090 | |||
1091 | case SCO_LINK: | ||
1092 | case ESCO_LINK: | ||
1093 | sco_disconn_cfm(conn, reason); | ||
1094 | break; | ||
1095 | |||
1096 | /* L2CAP would be handled for BREDR chan */ | ||
1097 | case AMP_LINK: | ||
1098 | break; | ||
1099 | 1060 | ||
1100 | default: | 1061 | char *name; |
1101 | BT_ERR("unknown link type %d", conn->type); | ||
1102 | break; | ||
1103 | } | ||
1104 | 1062 | ||
1105 | if (conn->disconn_cfm_cb) | 1063 | void (*connect_cfm) (struct hci_conn *conn, __u8 status); |
1106 | conn->disconn_cfm_cb(conn, reason); | 1064 | void (*disconn_cfm) (struct hci_conn *conn, __u8 status); |
1107 | } | 1065 | void (*security_cfm) (struct hci_conn *conn, __u8 status, |
1066 | __u8 encrypt); | ||
1067 | void (*key_change_cfm) (struct hci_conn *conn, __u8 status); | ||
1068 | void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role); | ||
1069 | }; | ||
1108 | 1070 | ||
1109 | static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status) | 1071 | static inline void hci_connect_cfm(struct hci_conn *conn, __u8 status) |
1110 | { | 1072 | { |
1111 | __u8 encrypt; | 1073 | struct hci_cb *cb; |
1112 | |||
1113 | if (conn->type != ACL_LINK && conn->type != LE_LINK) | ||
1114 | return; | ||
1115 | |||
1116 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) | ||
1117 | return; | ||
1118 | 1074 | ||
1119 | encrypt = test_bit(HCI_CONN_ENCRYPT, &conn->flags) ? 0x01 : 0x00; | 1075 | mutex_lock(&hci_cb_list_lock); |
1120 | l2cap_security_cfm(conn, status, encrypt); | 1076 | list_for_each_entry(cb, &hci_cb_list, list) { |
1077 | if (cb->connect_cfm) | ||
1078 | cb->connect_cfm(conn, status); | ||
1079 | } | ||
1080 | mutex_unlock(&hci_cb_list_lock); | ||
1121 | 1081 | ||
1122 | if (conn->security_cfm_cb) | 1082 | if (conn->connect_cfm_cb) |
1123 | conn->security_cfm_cb(conn, status); | 1083 | conn->connect_cfm_cb(conn, status); |
1124 | } | 1084 | } |
1125 | 1085 | ||
1126 | static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, | 1086 | static inline void hci_disconn_cfm(struct hci_conn *conn, __u8 reason) |
1127 | __u8 encrypt) | ||
1128 | { | 1087 | { |
1129 | if (conn->type != ACL_LINK && conn->type != LE_LINK) | 1088 | struct hci_cb *cb; |
1130 | return; | ||
1131 | 1089 | ||
1132 | l2cap_security_cfm(conn, status, encrypt); | 1090 | mutex_lock(&hci_cb_list_lock); |
1091 | list_for_each_entry(cb, &hci_cb_list, list) { | ||
1092 | if (cb->disconn_cfm) | ||
1093 | cb->disconn_cfm(conn, reason); | ||
1094 | } | ||
1095 | mutex_unlock(&hci_cb_list_lock); | ||
1133 | 1096 | ||
1134 | if (conn->security_cfm_cb) | 1097 | if (conn->disconn_cfm_cb) |
1135 | conn->security_cfm_cb(conn, status); | 1098 | conn->disconn_cfm_cb(conn, reason); |
1136 | } | 1099 | } |
1137 | 1100 | ||
1138 | /* ----- HCI callbacks ----- */ | ||
1139 | struct hci_cb { | ||
1140 | struct list_head list; | ||
1141 | |||
1142 | char *name; | ||
1143 | |||
1144 | void (*security_cfm) (struct hci_conn *conn, __u8 status, | ||
1145 | __u8 encrypt); | ||
1146 | void (*key_change_cfm) (struct hci_conn *conn, __u8 status); | ||
1147 | void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role); | ||
1148 | }; | ||
1149 | |||
1150 | static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status) | 1101 | static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status) |
1151 | { | 1102 | { |
1152 | struct hci_cb *cb; | 1103 | struct hci_cb *cb; |
1153 | __u8 encrypt; | 1104 | __u8 encrypt; |
1154 | 1105 | ||
1155 | hci_proto_auth_cfm(conn, status); | ||
1156 | |||
1157 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) | 1106 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) |
1158 | return; | 1107 | return; |
1159 | 1108 | ||
1160 | encrypt = test_bit(HCI_CONN_ENCRYPT, &conn->flags) ? 0x01 : 0x00; | 1109 | encrypt = test_bit(HCI_CONN_ENCRYPT, &conn->flags) ? 0x01 : 0x00; |
1161 | 1110 | ||
1162 | read_lock(&hci_cb_list_lock); | 1111 | mutex_lock(&hci_cb_list_lock); |
1163 | list_for_each_entry(cb, &hci_cb_list, list) { | 1112 | list_for_each_entry(cb, &hci_cb_list, list) { |
1164 | if (cb->security_cfm) | 1113 | if (cb->security_cfm) |
1165 | cb->security_cfm(conn, status, encrypt); | 1114 | cb->security_cfm(conn, status, encrypt); |
1166 | } | 1115 | } |
1167 | read_unlock(&hci_cb_list_lock); | 1116 | mutex_unlock(&hci_cb_list_lock); |
1117 | |||
1118 | if (conn->security_cfm_cb) | ||
1119 | conn->security_cfm_cb(conn, status); | ||
1168 | } | 1120 | } |
1169 | 1121 | ||
1170 | static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, | 1122 | static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, |
@@ -1178,26 +1130,27 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, | |||
1178 | if (conn->pending_sec_level > conn->sec_level) | 1130 | if (conn->pending_sec_level > conn->sec_level) |
1179 | conn->sec_level = conn->pending_sec_level; | 1131 | conn->sec_level = conn->pending_sec_level; |
1180 | 1132 | ||
1181 | hci_proto_encrypt_cfm(conn, status, encrypt); | 1133 | mutex_lock(&hci_cb_list_lock); |
1182 | |||
1183 | read_lock(&hci_cb_list_lock); | ||
1184 | list_for_each_entry(cb, &hci_cb_list, list) { | 1134 | list_for_each_entry(cb, &hci_cb_list, list) { |
1185 | if (cb->security_cfm) | 1135 | if (cb->security_cfm) |
1186 | cb->security_cfm(conn, status, encrypt); | 1136 | cb->security_cfm(conn, status, encrypt); |
1187 | } | 1137 | } |
1188 | read_unlock(&hci_cb_list_lock); | 1138 | mutex_unlock(&hci_cb_list_lock); |
1139 | |||
1140 | if (conn->security_cfm_cb) | ||
1141 | conn->security_cfm_cb(conn, status); | ||
1189 | } | 1142 | } |
1190 | 1143 | ||
1191 | static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status) | 1144 | static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status) |
1192 | { | 1145 | { |
1193 | struct hci_cb *cb; | 1146 | struct hci_cb *cb; |
1194 | 1147 | ||
1195 | read_lock(&hci_cb_list_lock); | 1148 | mutex_lock(&hci_cb_list_lock); |
1196 | list_for_each_entry(cb, &hci_cb_list, list) { | 1149 | list_for_each_entry(cb, &hci_cb_list, list) { |
1197 | if (cb->key_change_cfm) | 1150 | if (cb->key_change_cfm) |
1198 | cb->key_change_cfm(conn, status); | 1151 | cb->key_change_cfm(conn, status); |
1199 | } | 1152 | } |
1200 | read_unlock(&hci_cb_list_lock); | 1153 | mutex_unlock(&hci_cb_list_lock); |
1201 | } | 1154 | } |
1202 | 1155 | ||
1203 | static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, | 1156 | static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, |
@@ -1205,12 +1158,12 @@ static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, | |||
1205 | { | 1158 | { |
1206 | struct hci_cb *cb; | 1159 | struct hci_cb *cb; |
1207 | 1160 | ||
1208 | read_lock(&hci_cb_list_lock); | 1161 | mutex_lock(&hci_cb_list_lock); |
1209 | list_for_each_entry(cb, &hci_cb_list, list) { | 1162 | list_for_each_entry(cb, &hci_cb_list, list) { |
1210 | if (cb->role_switch_cfm) | 1163 | if (cb->role_switch_cfm) |
1211 | cb->role_switch_cfm(conn, status, role); | 1164 | cb->role_switch_cfm(conn, status, role); |
1212 | } | 1165 | } |
1213 | read_unlock(&hci_cb_list_lock); | 1166 | mutex_unlock(&hci_cb_list_lock); |
1214 | } | 1167 | } |
1215 | 1168 | ||
1216 | static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type) | 1169 | static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type) |
@@ -1312,7 +1265,8 @@ void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode); | |||
1312 | 1265 | ||
1313 | /* ----- HCI Sockets ----- */ | 1266 | /* ----- HCI Sockets ----- */ |
1314 | void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb); | 1267 | void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb); |
1315 | void hci_send_to_control(struct sk_buff *skb, struct sock *skip_sk); | 1268 | void hci_send_to_channel(unsigned short channel, struct sk_buff *skb, |
1269 | struct sock *skip_sk); | ||
1316 | void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb); | 1270 | void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb); |
1317 | 1271 | ||
1318 | void hci_sock_dev_event(struct hci_dev *hdev, int event); | 1272 | void hci_sock_dev_event(struct hci_dev *hdev, int event); |
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index e218a30f2061..fe8eef00e9ca 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h | |||
@@ -647,9 +647,14 @@ struct mgmt_ev_new_irk { | |||
647 | struct mgmt_irk_info irk; | 647 | struct mgmt_irk_info irk; |
648 | } __packed; | 648 | } __packed; |
649 | 649 | ||
650 | #define MGMT_CSRK_LOCAL_UNAUTHENTICATED 0x00 | ||
651 | #define MGMT_CSRK_REMOTE_UNAUTHENTICATED 0x01 | ||
652 | #define MGMT_CSRK_LOCAL_AUTHENTICATED 0x02 | ||
653 | #define MGMT_CSRK_REMOTE_AUTHENTICATED 0x03 | ||
654 | |||
650 | struct mgmt_csrk_info { | 655 | struct mgmt_csrk_info { |
651 | struct mgmt_addr_info addr; | 656 | struct mgmt_addr_info addr; |
652 | __u8 master; | 657 | __u8 type; |
653 | __u8 val[16]; | 658 | __u8 val[16]; |
654 | } __packed; | 659 | } __packed; |
655 | 660 | ||