Commit 4c659c39 authored by Johan Hedberg's avatar Johan Hedberg Committed by Gustavo F. Padovan

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: default avatarJohan Hedberg <johan.hedberg@intel.com>
Signed-off-by: default avatarGustavo F. Padovan <padovan@profusion.mobi>
parent 86742e1e
...@@ -912,10 +912,10 @@ int mgmt_discoverable(u16 index, u8 discoverable); ...@@ -912,10 +912,10 @@ int mgmt_discoverable(u16 index, u8 discoverable);
int mgmt_connectable(u16 index, u8 connectable); int mgmt_connectable(u16 index, u8 connectable);
int mgmt_write_scan_failed(u16 index, u8 scan, u8 status); int mgmt_write_scan_failed(u16 index, u8 scan, u8 status);
int mgmt_new_link_key(u16 index, struct link_key *key, u8 persistent); int mgmt_new_link_key(u16 index, struct link_key *key, u8 persistent);
int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 link_type); int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 type);
int mgmt_disconnected(u16 index, bdaddr_t *bdaddr); int mgmt_disconnected(u16 index, bdaddr_t *bdaddr, u8 type);
int mgmt_disconnect_failed(u16 index); int mgmt_disconnect_failed(u16 index);
int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status); int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 type, u8 status);
int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr, u8 secure); int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr, u8 secure);
int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); 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,8 +928,8 @@ int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status);
int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status); int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status);
int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
u8 status); u8 status);
int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 type, u8 *dev_class,
u8 *eir); s8 rssi, u8 *eir);
int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name); int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name);
int mgmt_inquiry_failed(u16 index, u8 status); int mgmt_inquiry_failed(u16 index, u8 status);
int mgmt_discovering(u16 index, u8 discovering); int mgmt_discovering(u16 index, u8 discovering);
......
...@@ -128,10 +128,20 @@ struct mgmt_rp_disconnect { ...@@ -128,10 +128,20 @@ struct mgmt_rp_disconnect {
bdaddr_t bdaddr; bdaddr_t bdaddr;
} __packed; } __packed;
#define MGMT_ADDR_BREDR 0x00
#define MGMT_ADDR_LE 0x01
#define MGMT_ADDR_BREDR_LE 0x02
#define MGMT_ADDR_INVALID 0xff
struct mgmt_addr_info {
bdaddr_t bdaddr;
__u8 type;
} __packed;
#define MGMT_OP_GET_CONNECTIONS 0x0010 #define MGMT_OP_GET_CONNECTIONS 0x0010
struct mgmt_rp_get_connections { struct mgmt_rp_get_connections {
__le16 conn_count; __le16 conn_count;
bdaddr_t conn[0]; struct mgmt_addr_info addr[0];
} __packed; } __packed;
#define MGMT_OP_PIN_CODE_REPLY 0x0011 #define MGMT_OP_PIN_CODE_REPLY 0x0011
...@@ -254,19 +264,12 @@ struct mgmt_ev_new_link_key { ...@@ -254,19 +264,12 @@ struct mgmt_ev_new_link_key {
} __packed; } __packed;
#define MGMT_EV_CONNECTED 0x000B #define MGMT_EV_CONNECTED 0x000B
struct mgmt_ev_connected {
bdaddr_t bdaddr;
__u8 link_type;
} __packed;
#define MGMT_EV_DISCONNECTED 0x000C #define MGMT_EV_DISCONNECTED 0x000C
struct mgmt_ev_disconnected {
bdaddr_t bdaddr;
} __packed;
#define MGMT_EV_CONNECT_FAILED 0x000D #define MGMT_EV_CONNECT_FAILED 0x000D
struct mgmt_ev_connect_failed { struct mgmt_ev_connect_failed {
bdaddr_t bdaddr; struct mgmt_addr_info addr;
__u8 status; __u8 status;
} __packed; } __packed;
...@@ -296,7 +299,7 @@ struct mgmt_ev_local_name_changed { ...@@ -296,7 +299,7 @@ struct mgmt_ev_local_name_changed {
#define MGMT_EV_DEVICE_FOUND 0x0012 #define MGMT_EV_DEVICE_FOUND 0x0012
struct mgmt_ev_device_found { struct mgmt_ev_device_found {
bdaddr_t bdaddr; struct mgmt_addr_info addr;
__u8 dev_class[3]; __u8 dev_class[3];
__s8 rssi; __s8 rssi;
__u8 eir[HCI_MAX_EIR_LENGTH]; __u8 eir[HCI_MAX_EIR_LENGTH];
......
...@@ -1404,8 +1404,8 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff * ...@@ -1404,8 +1404,8 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
data.rssi = 0x00; data.rssi = 0x00;
data.ssp_mode = 0x00; data.ssp_mode = 0x00;
hci_inquiry_cache_update(hdev, &data); hci_inquiry_cache_update(hdev, &data);
mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 0, mgmt_device_found(hdev->id, &info->bdaddr, ACL_LINK,
NULL); info->dev_class, 0, NULL);
} }
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -1471,7 +1471,8 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s ...@@ -1471,7 +1471,8 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
} else { } else {
conn->state = BT_CLOSED; conn->state = BT_CLOSED;
if (conn->type == ACL_LINK) if (conn->type == ACL_LINK)
mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status); mgmt_connect_failed(hdev->id, &ev->bdaddr, conn->type,
ev->status);
} }
if (conn->type == ACL_LINK) if (conn->type == ACL_LINK)
...@@ -1584,7 +1585,7 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff ...@@ -1584,7 +1585,7 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff
conn->state = BT_CLOSED; conn->state = BT_CLOSED;
if (conn->type == ACL_LINK || conn->type == LE_LINK) if (conn->type == ACL_LINK || conn->type == LE_LINK)
mgmt_disconnected(hdev->id, &conn->dst); mgmt_disconnected(hdev->id, &conn->dst, conn->type);
hci_proto_disconn_cfm(conn, ev->reason); hci_proto_disconn_cfm(conn, ev->reason);
hci_conn_del(conn); hci_conn_del(conn);
...@@ -2408,7 +2409,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct ...@@ -2408,7 +2409,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
data.rssi = info->rssi; data.rssi = info->rssi;
data.ssp_mode = 0x00; data.ssp_mode = 0x00;
hci_inquiry_cache_update(hdev, &data); hci_inquiry_cache_update(hdev, &data);
mgmt_device_found(hdev->id, &info->bdaddr, mgmt_device_found(hdev->id, &info->bdaddr, ACL_LINK,
info->dev_class, info->rssi, info->dev_class, info->rssi,
NULL); NULL);
} }
...@@ -2425,7 +2426,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct ...@@ -2425,7 +2426,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
data.rssi = info->rssi; data.rssi = info->rssi;
data.ssp_mode = 0x00; data.ssp_mode = 0x00;
hci_inquiry_cache_update(hdev, &data); hci_inquiry_cache_update(hdev, &data);
mgmt_device_found(hdev->id, &info->bdaddr, mgmt_device_found(hdev->id, &info->bdaddr, ACL_LINK,
info->dev_class, info->rssi, info->dev_class, info->rssi,
NULL); NULL);
} }
...@@ -2568,8 +2569,8 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct ...@@ -2568,8 +2569,8 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
data.rssi = info->rssi; data.rssi = info->rssi;
data.ssp_mode = 0x01; data.ssp_mode = 0x01;
hci_inquiry_cache_update(hdev, &data); hci_inquiry_cache_update(hdev, &data);
mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, mgmt_device_found(hdev->id, &info->bdaddr, ACL_LINK,
info->rssi, info->data); info->dev_class, info->rssi, info->data);
} }
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -2832,7 +2833,8 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff ...@@ -2832,7 +2833,8 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff
} }
if (ev->status) { if (ev->status) {
mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status); mgmt_connect_failed(hdev->id, &ev->bdaddr, conn->type,
ev->status);
hci_proto_connect_cfm(conn, ev->status); hci_proto_connect_cfm(conn, ev->status);
conn->state = BT_CLOSED; conn->state = BT_CLOSED;
hci_conn_del(conn); hci_conn_del(conn);
......
...@@ -1069,6 +1069,18 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len) ...@@ -1069,6 +1069,18 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
return err; return err;
} }
static u8 link_to_mgmt(u8 link_type)
{
switch (link_type) {
case LE_LINK:
return MGMT_ADDR_LE;
case ACL_LINK:
return MGMT_ADDR_BREDR;
default:
return MGMT_ADDR_INVALID;
}
}
static int get_connections(struct sock *sk, u16 index) static int get_connections(struct sock *sk, u16 index)
{ {
struct mgmt_rp_get_connections *rp; struct mgmt_rp_get_connections *rp;
...@@ -1092,7 +1104,7 @@ static int get_connections(struct sock *sk, u16 index) ...@@ -1092,7 +1104,7 @@ static int get_connections(struct sock *sk, u16 index)
count++; count++;
} }
rp_len = sizeof(*rp) + (count * sizeof(bdaddr_t)); rp_len = sizeof(*rp) + (count * sizeof(struct mgmt_addr_info));
rp = kmalloc(rp_len, GFP_ATOMIC); rp = kmalloc(rp_len, GFP_ATOMIC);
if (!rp) { if (!rp) {
err = -ENOMEM; err = -ENOMEM;
...@@ -1102,8 +1114,16 @@ static int get_connections(struct sock *sk, u16 index) ...@@ -1102,8 +1114,16 @@ static int get_connections(struct sock *sk, u16 index)
put_unaligned_le16(count, &rp->conn_count); put_unaligned_le16(count, &rp->conn_count);
i = 0; i = 0;
list_for_each_entry(c, &hdev->conn_hash.list, list) list_for_each_entry(c, &hdev->conn_hash.list, list) {
bacpy(&rp->conn[i++], &c->dst); bacpy(&rp->addr[i].bdaddr, &c->dst);
rp->addr[i].type = link_to_mgmt(c->type);
if (rp->addr[i].type == MGMT_ADDR_INVALID)
continue;
i++;
}
/* Recalculate length in case of filtered SCO connections, etc */
rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
err = cmd_complete(sk, index, MGMT_OP_GET_CONNECTIONS, rp, rp_len); err = cmd_complete(sk, index, MGMT_OP_GET_CONNECTIONS, rp, rp_len);
...@@ -2075,10 +2095,10 @@ int mgmt_new_link_key(u16 index, struct link_key *key, u8 persistent) ...@@ -2075,10 +2095,10 @@ int mgmt_new_link_key(u16 index, struct link_key *key, u8 persistent)
int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 link_type) int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 link_type)
{ {
struct mgmt_ev_connected ev; struct mgmt_addr_info ev;
bacpy(&ev.bdaddr, bdaddr); bacpy(&ev.bdaddr, bdaddr);
ev.link_type = link_type; ev.type = link_to_mgmt(link_type);
return mgmt_event(MGMT_EV_CONNECTED, index, &ev, sizeof(ev), NULL); return mgmt_event(MGMT_EV_CONNECTED, index, &ev, sizeof(ev), NULL);
} }
...@@ -2099,15 +2119,16 @@ static void disconnect_rsp(struct pending_cmd *cmd, void *data) ...@@ -2099,15 +2119,16 @@ static void disconnect_rsp(struct pending_cmd *cmd, void *data)
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
} }
int mgmt_disconnected(u16 index, bdaddr_t *bdaddr) int mgmt_disconnected(u16 index, bdaddr_t *bdaddr, u8 type)
{ {
struct mgmt_ev_disconnected ev; struct mgmt_addr_info ev;
struct sock *sk = NULL; struct sock *sk = NULL;
int err; int err;
mgmt_pending_foreach(MGMT_OP_DISCONNECT, index, disconnect_rsp, &sk); mgmt_pending_foreach(MGMT_OP_DISCONNECT, index, disconnect_rsp, &sk);
bacpy(&ev.bdaddr, bdaddr); bacpy(&ev.bdaddr, bdaddr);
ev.type = link_to_mgmt(type);
err = mgmt_event(MGMT_EV_DISCONNECTED, index, &ev, sizeof(ev), sk); err = mgmt_event(MGMT_EV_DISCONNECTED, index, &ev, sizeof(ev), sk);
...@@ -2133,11 +2154,12 @@ int mgmt_disconnect_failed(u16 index) ...@@ -2133,11 +2154,12 @@ int mgmt_disconnect_failed(u16 index)
return err; return err;
} }
int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status) int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 type, u8 status)
{ {
struct mgmt_ev_connect_failed ev; struct mgmt_ev_connect_failed ev;
bacpy(&ev.bdaddr, bdaddr); bacpy(&ev.addr.bdaddr, bdaddr);
ev.addr.type = link_to_mgmt(type);
ev.status = status; ev.status = status;
return mgmt_event(MGMT_EV_CONNECT_FAILED, index, &ev, sizeof(ev), NULL); 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,14 +2347,15 @@ int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
return err; return err;
} }
int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 type, u8 *dev_class,
u8 *eir) s8 rssi, u8 *eir)
{ {
struct mgmt_ev_device_found ev; struct mgmt_ev_device_found ev;
memset(&ev, 0, sizeof(ev)); memset(&ev, 0, sizeof(ev));
bacpy(&ev.bdaddr, bdaddr); bacpy(&ev.addr.bdaddr, bdaddr);
ev.addr.type = link_to_mgmt(type);
ev.rssi = rssi; ev.rssi = rssi;
if (eir) if (eir)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment