diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2011-11-07 16:13:39 -0500 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-11-08 10:05:57 -0500 |
commit | 4c659c3976e81f9def48993cd00988d53d7379f2 (patch) | |
tree | 57cdd17455a2b71ab545bcb609baa4990afa8dda | |
parent | 86742e1eca319069490f6f20c2892baafc2a6922 (diff) |
Bluetooth: Add address type fields to mgmt messages that need them
This patch adds address type info (typically BR/EDR vs LE) to management
messages that need this. This also ensures conformance to the latest
management API specification.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
-rw-r--r-- | include/net/bluetooth/hci_core.h | 10 | ||||
-rw-r--r-- | include/net/bluetooth/mgmt.h | 23 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 20 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 47 |
4 files changed, 64 insertions, 36 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 4ebc882385f9..e6071d0ea20f 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -912,10 +912,10 @@ int mgmt_discoverable(u16 index, u8 discoverable); | |||
912 | int mgmt_connectable(u16 index, u8 connectable); | 912 | int mgmt_connectable(u16 index, u8 connectable); |
913 | int mgmt_write_scan_failed(u16 index, u8 scan, u8 status); | 913 | int mgmt_write_scan_failed(u16 index, u8 scan, u8 status); |
914 | int mgmt_new_link_key(u16 index, struct link_key *key, u8 persistent); | 914 | int mgmt_new_link_key(u16 index, struct link_key *key, u8 persistent); |
915 | int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 link_type); | 915 | int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 type); |
916 | int mgmt_disconnected(u16 index, bdaddr_t *bdaddr); | 916 | int mgmt_disconnected(u16 index, bdaddr_t *bdaddr, u8 type); |
917 | int mgmt_disconnect_failed(u16 index); | 917 | int mgmt_disconnect_failed(u16 index); |
918 | int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status); | 918 | int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 type, u8 status); |
919 | int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr, u8 secure); | 919 | int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr, u8 secure); |
920 | int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); | 920 | int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); |
921 | int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); | 921 | int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); |
@@ -928,8 +928,8 @@ int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status); | |||
928 | int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status); | 928 | int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status); |
929 | int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, | 929 | int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, |
930 | u8 status); | 930 | u8 status); |
931 | int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, | 931 | int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 type, u8 *dev_class, |
932 | u8 *eir); | 932 | s8 rssi, u8 *eir); |
933 | int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name); | 933 | int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name); |
934 | int mgmt_inquiry_failed(u16 index, u8 status); | 934 | int mgmt_inquiry_failed(u16 index, u8 status); |
935 | int mgmt_discovering(u16 index, u8 discovering); | 935 | int mgmt_discovering(u16 index, u8 discovering); |
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index fa33bc6c485f..3e320c9cae8f 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h | |||
@@ -128,10 +128,20 @@ struct mgmt_rp_disconnect { | |||
128 | bdaddr_t bdaddr; | 128 | bdaddr_t bdaddr; |
129 | } __packed; | 129 | } __packed; |
130 | 130 | ||
131 | #define MGMT_ADDR_BREDR 0x00 | ||
132 | #define MGMT_ADDR_LE 0x01 | ||
133 | #define MGMT_ADDR_BREDR_LE 0x02 | ||
134 | #define MGMT_ADDR_INVALID 0xff | ||
135 | |||
136 | struct mgmt_addr_info { | ||
137 | bdaddr_t bdaddr; | ||
138 | __u8 type; | ||
139 | } __packed; | ||
140 | |||
131 | #define MGMT_OP_GET_CONNECTIONS 0x0010 | 141 | #define MGMT_OP_GET_CONNECTIONS 0x0010 |
132 | struct mgmt_rp_get_connections { | 142 | struct mgmt_rp_get_connections { |
133 | __le16 conn_count; | 143 | __le16 conn_count; |
134 | bdaddr_t conn[0]; | 144 | struct mgmt_addr_info addr[0]; |
135 | } __packed; | 145 | } __packed; |
136 | 146 | ||
137 | #define MGMT_OP_PIN_CODE_REPLY 0x0011 | 147 | #define MGMT_OP_PIN_CODE_REPLY 0x0011 |
@@ -254,19 +264,12 @@ struct mgmt_ev_new_link_key { | |||
254 | } __packed; | 264 | } __packed; |
255 | 265 | ||
256 | #define MGMT_EV_CONNECTED 0x000B | 266 | #define MGMT_EV_CONNECTED 0x000B |
257 | struct mgmt_ev_connected { | ||
258 | bdaddr_t bdaddr; | ||
259 | __u8 link_type; | ||
260 | } __packed; | ||
261 | 267 | ||
262 | #define MGMT_EV_DISCONNECTED 0x000C | 268 | #define MGMT_EV_DISCONNECTED 0x000C |
263 | struct mgmt_ev_disconnected { | ||
264 | bdaddr_t bdaddr; | ||
265 | } __packed; | ||
266 | 269 | ||
267 | #define MGMT_EV_CONNECT_FAILED 0x000D | 270 | #define MGMT_EV_CONNECT_FAILED 0x000D |
268 | struct mgmt_ev_connect_failed { | 271 | struct mgmt_ev_connect_failed { |
269 | bdaddr_t bdaddr; | 272 | struct mgmt_addr_info addr; |
270 | __u8 status; | 273 | __u8 status; |
271 | } __packed; | 274 | } __packed; |
272 | 275 | ||
@@ -296,7 +299,7 @@ struct mgmt_ev_local_name_changed { | |||
296 | 299 | ||
297 | #define MGMT_EV_DEVICE_FOUND 0x0012 | 300 | #define MGMT_EV_DEVICE_FOUND 0x0012 |
298 | struct mgmt_ev_device_found { | 301 | struct mgmt_ev_device_found { |
299 | bdaddr_t bdaddr; | 302 | struct mgmt_addr_info addr; |
300 | __u8 dev_class[3]; | 303 | __u8 dev_class[3]; |
301 | __s8 rssi; | 304 | __s8 rssi; |
302 | __u8 eir[HCI_MAX_EIR_LENGTH]; | 305 | __u8 eir[HCI_MAX_EIR_LENGTH]; |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 176cecae4b42..2fced8c43258 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -1404,8 +1404,8 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff * | |||
1404 | data.rssi = 0x00; | 1404 | data.rssi = 0x00; |
1405 | data.ssp_mode = 0x00; | 1405 | data.ssp_mode = 0x00; |
1406 | hci_inquiry_cache_update(hdev, &data); | 1406 | hci_inquiry_cache_update(hdev, &data); |
1407 | mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 0, | 1407 | mgmt_device_found(hdev->id, &info->bdaddr, ACL_LINK, |
1408 | NULL); | 1408 | info->dev_class, 0, NULL); |
1409 | } | 1409 | } |
1410 | 1410 | ||
1411 | hci_dev_unlock(hdev); | 1411 | hci_dev_unlock(hdev); |
@@ -1471,7 +1471,8 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
1471 | } else { | 1471 | } else { |
1472 | conn->state = BT_CLOSED; | 1472 | conn->state = BT_CLOSED; |
1473 | if (conn->type == ACL_LINK) | 1473 | if (conn->type == ACL_LINK) |
1474 | mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status); | 1474 | mgmt_connect_failed(hdev->id, &ev->bdaddr, conn->type, |
1475 | ev->status); | ||
1475 | } | 1476 | } |
1476 | 1477 | ||
1477 | if (conn->type == ACL_LINK) | 1478 | if (conn->type == ACL_LINK) |
@@ -1584,7 +1585,7 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff | |||
1584 | conn->state = BT_CLOSED; | 1585 | conn->state = BT_CLOSED; |
1585 | 1586 | ||
1586 | if (conn->type == ACL_LINK || conn->type == LE_LINK) | 1587 | if (conn->type == ACL_LINK || conn->type == LE_LINK) |
1587 | mgmt_disconnected(hdev->id, &conn->dst); | 1588 | mgmt_disconnected(hdev->id, &conn->dst, conn->type); |
1588 | 1589 | ||
1589 | hci_proto_disconn_cfm(conn, ev->reason); | 1590 | hci_proto_disconn_cfm(conn, ev->reason); |
1590 | hci_conn_del(conn); | 1591 | hci_conn_del(conn); |
@@ -2408,7 +2409,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct | |||
2408 | data.rssi = info->rssi; | 2409 | data.rssi = info->rssi; |
2409 | data.ssp_mode = 0x00; | 2410 | data.ssp_mode = 0x00; |
2410 | hci_inquiry_cache_update(hdev, &data); | 2411 | hci_inquiry_cache_update(hdev, &data); |
2411 | mgmt_device_found(hdev->id, &info->bdaddr, | 2412 | mgmt_device_found(hdev->id, &info->bdaddr, ACL_LINK, |
2412 | info->dev_class, info->rssi, | 2413 | info->dev_class, info->rssi, |
2413 | NULL); | 2414 | NULL); |
2414 | } | 2415 | } |
@@ -2425,7 +2426,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct | |||
2425 | data.rssi = info->rssi; | 2426 | data.rssi = info->rssi; |
2426 | data.ssp_mode = 0x00; | 2427 | data.ssp_mode = 0x00; |
2427 | hci_inquiry_cache_update(hdev, &data); | 2428 | hci_inquiry_cache_update(hdev, &data); |
2428 | mgmt_device_found(hdev->id, &info->bdaddr, | 2429 | mgmt_device_found(hdev->id, &info->bdaddr, ACL_LINK, |
2429 | info->dev_class, info->rssi, | 2430 | info->dev_class, info->rssi, |
2430 | NULL); | 2431 | NULL); |
2431 | } | 2432 | } |
@@ -2568,8 +2569,8 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct | |||
2568 | data.rssi = info->rssi; | 2569 | data.rssi = info->rssi; |
2569 | data.ssp_mode = 0x01; | 2570 | data.ssp_mode = 0x01; |
2570 | hci_inquiry_cache_update(hdev, &data); | 2571 | hci_inquiry_cache_update(hdev, &data); |
2571 | mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, | 2572 | mgmt_device_found(hdev->id, &info->bdaddr, ACL_LINK, |
2572 | info->rssi, info->data); | 2573 | info->dev_class, info->rssi, info->data); |
2573 | } | 2574 | } |
2574 | 2575 | ||
2575 | hci_dev_unlock(hdev); | 2576 | hci_dev_unlock(hdev); |
@@ -2832,7 +2833,8 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff | |||
2832 | } | 2833 | } |
2833 | 2834 | ||
2834 | if (ev->status) { | 2835 | if (ev->status) { |
2835 | mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status); | 2836 | mgmt_connect_failed(hdev->id, &ev->bdaddr, conn->type, |
2837 | ev->status); | ||
2836 | hci_proto_connect_cfm(conn, ev->status); | 2838 | hci_proto_connect_cfm(conn, ev->status); |
2837 | conn->state = BT_CLOSED; | 2839 | conn->state = BT_CLOSED; |
2838 | hci_conn_del(conn); | 2840 | hci_conn_del(conn); |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 1939053c3fcd..4cb2f958fb10 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -1069,6 +1069,18 @@ failed: | |||
1069 | return err; | 1069 | return err; |
1070 | } | 1070 | } |
1071 | 1071 | ||
1072 | static u8 link_to_mgmt(u8 link_type) | ||
1073 | { | ||
1074 | switch (link_type) { | ||
1075 | case LE_LINK: | ||
1076 | return MGMT_ADDR_LE; | ||
1077 | case ACL_LINK: | ||
1078 | return MGMT_ADDR_BREDR; | ||
1079 | default: | ||
1080 | return MGMT_ADDR_INVALID; | ||
1081 | } | ||
1082 | } | ||
1083 | |||
1072 | static int get_connections(struct sock *sk, u16 index) | 1084 | static int get_connections(struct sock *sk, u16 index) |
1073 | { | 1085 | { |
1074 | struct mgmt_rp_get_connections *rp; | 1086 | struct mgmt_rp_get_connections *rp; |
@@ -1092,7 +1104,7 @@ static int get_connections(struct sock *sk, u16 index) | |||
1092 | count++; | 1104 | count++; |
1093 | } | 1105 | } |
1094 | 1106 | ||
1095 | rp_len = sizeof(*rp) + (count * sizeof(bdaddr_t)); | 1107 | rp_len = sizeof(*rp) + (count * sizeof(struct mgmt_addr_info)); |
1096 | rp = kmalloc(rp_len, GFP_ATOMIC); | 1108 | rp = kmalloc(rp_len, GFP_ATOMIC); |
1097 | if (!rp) { | 1109 | if (!rp) { |
1098 | err = -ENOMEM; | 1110 | err = -ENOMEM; |
@@ -1102,8 +1114,16 @@ static int get_connections(struct sock *sk, u16 index) | |||
1102 | put_unaligned_le16(count, &rp->conn_count); | 1114 | put_unaligned_le16(count, &rp->conn_count); |
1103 | 1115 | ||
1104 | i = 0; | 1116 | i = 0; |
1105 | list_for_each_entry(c, &hdev->conn_hash.list, list) | 1117 | list_for_each_entry(c, &hdev->conn_hash.list, list) { |
1106 | bacpy(&rp->conn[i++], &c->dst); | 1118 | bacpy(&rp->addr[i].bdaddr, &c->dst); |
1119 | rp->addr[i].type = link_to_mgmt(c->type); | ||
1120 | if (rp->addr[i].type == MGMT_ADDR_INVALID) | ||
1121 | continue; | ||
1122 | i++; | ||
1123 | } | ||
1124 | |||
1125 | /* Recalculate length in case of filtered SCO connections, etc */ | ||
1126 | rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info)); | ||
1107 | 1127 | ||
1108 | err = cmd_complete(sk, index, MGMT_OP_GET_CONNECTIONS, rp, rp_len); | 1128 | err = cmd_complete(sk, index, MGMT_OP_GET_CONNECTIONS, rp, rp_len); |
1109 | 1129 | ||
@@ -2075,10 +2095,10 @@ int mgmt_new_link_key(u16 index, struct link_key *key, u8 persistent) | |||
2075 | 2095 | ||
2076 | int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 link_type) | 2096 | int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 link_type) |
2077 | { | 2097 | { |
2078 | struct mgmt_ev_connected ev; | 2098 | struct mgmt_addr_info ev; |
2079 | 2099 | ||
2080 | bacpy(&ev.bdaddr, bdaddr); | 2100 | bacpy(&ev.bdaddr, bdaddr); |
2081 | ev.link_type = link_type; | 2101 | ev.type = link_to_mgmt(link_type); |
2082 | 2102 | ||
2083 | return mgmt_event(MGMT_EV_CONNECTED, index, &ev, sizeof(ev), NULL); | 2103 | return mgmt_event(MGMT_EV_CONNECTED, index, &ev, sizeof(ev), NULL); |
2084 | } | 2104 | } |
@@ -2099,15 +2119,16 @@ static void disconnect_rsp(struct pending_cmd *cmd, void *data) | |||
2099 | mgmt_pending_remove(cmd); | 2119 | mgmt_pending_remove(cmd); |
2100 | } | 2120 | } |
2101 | 2121 | ||
2102 | int mgmt_disconnected(u16 index, bdaddr_t *bdaddr) | 2122 | int mgmt_disconnected(u16 index, bdaddr_t *bdaddr, u8 type) |
2103 | { | 2123 | { |
2104 | struct mgmt_ev_disconnected ev; | 2124 | struct mgmt_addr_info ev; |
2105 | struct sock *sk = NULL; | 2125 | struct sock *sk = NULL; |
2106 | int err; | 2126 | int err; |
2107 | 2127 | ||
2108 | mgmt_pending_foreach(MGMT_OP_DISCONNECT, index, disconnect_rsp, &sk); | 2128 | mgmt_pending_foreach(MGMT_OP_DISCONNECT, index, disconnect_rsp, &sk); |
2109 | 2129 | ||
2110 | bacpy(&ev.bdaddr, bdaddr); | 2130 | bacpy(&ev.bdaddr, bdaddr); |
2131 | ev.type = link_to_mgmt(type); | ||
2111 | 2132 | ||
2112 | err = mgmt_event(MGMT_EV_DISCONNECTED, index, &ev, sizeof(ev), sk); | 2133 | err = mgmt_event(MGMT_EV_DISCONNECTED, index, &ev, sizeof(ev), sk); |
2113 | 2134 | ||
@@ -2133,11 +2154,12 @@ int mgmt_disconnect_failed(u16 index) | |||
2133 | return err; | 2154 | return err; |
2134 | } | 2155 | } |
2135 | 2156 | ||
2136 | int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status) | 2157 | int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 type, u8 status) |
2137 | { | 2158 | { |
2138 | struct mgmt_ev_connect_failed ev; | 2159 | struct mgmt_ev_connect_failed ev; |
2139 | 2160 | ||
2140 | bacpy(&ev.bdaddr, bdaddr); | 2161 | bacpy(&ev.addr.bdaddr, bdaddr); |
2162 | ev.addr.type = link_to_mgmt(type); | ||
2141 | ev.status = status; | 2163 | ev.status = status; |
2142 | 2164 | ||
2143 | return mgmt_event(MGMT_EV_CONNECT_FAILED, index, &ev, sizeof(ev), NULL); | 2165 | return mgmt_event(MGMT_EV_CONNECT_FAILED, index, &ev, sizeof(ev), NULL); |
@@ -2325,14 +2347,15 @@ int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, | |||
2325 | return err; | 2347 | return err; |
2326 | } | 2348 | } |
2327 | 2349 | ||
2328 | int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, | 2350 | int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 type, u8 *dev_class, |
2329 | u8 *eir) | 2351 | s8 rssi, u8 *eir) |
2330 | { | 2352 | { |
2331 | struct mgmt_ev_device_found ev; | 2353 | struct mgmt_ev_device_found ev; |
2332 | 2354 | ||
2333 | memset(&ev, 0, sizeof(ev)); | 2355 | memset(&ev, 0, sizeof(ev)); |
2334 | 2356 | ||
2335 | bacpy(&ev.bdaddr, bdaddr); | 2357 | bacpy(&ev.addr.bdaddr, bdaddr); |
2358 | ev.addr.type = link_to_mgmt(type); | ||
2336 | ev.rssi = rssi; | 2359 | ev.rssi = rssi; |
2337 | 2360 | ||
2338 | if (eir) | 2361 | if (eir) |