From 1f6c6378c59f3ddac9ed89a68ccefe2611300c09 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 16 Mar 2011 14:29:35 +0200 Subject: Bluetooth: Add define for the maximum name length on HCI level This patch adds a clear define for the maximum device name length in HCI messages and thereby avoids magic numbers in the code. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 8 +++++--- include/net/bluetooth/hci_core.h | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index ec6acf2f1c0b..1cd031cd1c4d 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -535,15 +535,17 @@ struct hci_cp_delete_stored_link_key { __u8 delete_all; } __packed; +#define HCI_MAX_NAME_LENGTH 248 + #define HCI_OP_WRITE_LOCAL_NAME 0x0c13 struct hci_cp_write_local_name { - __u8 name[248]; + __u8 name[HCI_MAX_NAME_LENGTH]; } __packed; #define HCI_OP_READ_LOCAL_NAME 0x0c14 struct hci_rp_read_local_name { __u8 status; - __u8 name[248]; + __u8 name[HCI_MAX_NAME_LENGTH]; } __packed; #define HCI_OP_WRITE_CA_TIMEOUT 0x0c16 @@ -745,7 +747,7 @@ struct hci_ev_auth_complete { struct hci_ev_remote_name { __u8 status; bdaddr_t bdaddr; - __u8 name[248]; + __u8 name[HCI_MAX_NAME_LENGTH]; } __packed; #define HCI_EV_ENCRYPT_CHANGE 0x08 diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 441dadbf6a89..9aabb14982dd 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -94,7 +94,7 @@ struct hci_dev { __u8 bus; __u8 dev_type; bdaddr_t bdaddr; - __u8 dev_name[248]; + __u8 dev_name[HCI_MAX_NAME_LENGTH]; __u8 dev_class[3]; __u8 major_class; __u8 minor_class; -- cgit v1.2.3 From dc4fe30b8675033e538e2dea50be8af9c75f1b6a Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 16 Mar 2011 14:29:36 +0200 Subject: Bluetooth: mgmt: Add local name information to read_info reply This patch adds the name of the adapter to the reply of the read_info management command. The management messages reserve 249 bytes for the name instead of 248 (like in the HCI spec) so that there is always a guarantee that it is nul-terminated. That way it can safely be passed onto string manipulation functions. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/mgmt.h | 5 +++++ net/bluetooth/mgmt.c | 4 ++++ 2 files changed, 9 insertions(+) (limited to 'include') diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 5fabfa886b3e..7d0749bed090 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -41,6 +41,10 @@ struct mgmt_rp_read_index_list { __le16 index[0]; } __packed; +/* Reserve one extra byte for names in management messages so that they + * are always guaranteed to be nul-terminated */ +#define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1) + #define MGMT_OP_READ_INFO 0x0004 struct mgmt_rp_read_info { __u8 type; @@ -55,6 +59,7 @@ struct mgmt_rp_read_info { __u16 manufacturer; __u8 hci_ver; __u16 hci_rev; + __u8 name[MGMT_MAX_NAME_LENGTH]; } __packed; struct mgmt_mode { diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 0054c74e27b7..ffdb2f4e8635 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -183,6 +183,8 @@ static int read_controller_info(struct sock *sk, u16 index) set_bit(HCI_MGMT, &hdev->flags); + memset(&rp, 0, sizeof(rp)); + rp.type = hdev->dev_type; rp.powered = test_bit(HCI_UP, &hdev->flags); @@ -204,6 +206,8 @@ static int read_controller_info(struct sock *sk, u16 index) rp.hci_ver = hdev->hci_ver; put_unaligned_le16(hdev->hci_rev, &rp.hci_rev); + memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name)); + hci_dev_unlock_bh(hdev); hci_dev_put(hdev); -- cgit v1.2.3 From b312b161ecb833b1bce5c4a97853f4a4f40c7901 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 16 Mar 2011 14:29:37 +0200 Subject: Bluetooth: mgmt: Add support for setting the local name This patch adds a new set_local_name management command as well as a local_name_changed management event. With these user space can both change the local name as well as monitor changes to it by others. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 1 + include/net/bluetooth/mgmt.h | 10 ++++++ net/bluetooth/hci_event.c | 9 +++-- net/bluetooth/mgmt.c | 75 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 9aabb14982dd..3912c7ab717c 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -767,6 +767,7 @@ int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status); +int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status); /* HCI info for socket */ #define hci_pi(sk) ((struct hci_pinfo *) sk) diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 7d0749bed090..89e7c82c4784 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -172,6 +172,11 @@ struct mgmt_rp_user_confirm_reply { #define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x0016 +#define MGMT_OP_SET_LOCAL_NAME 0x0017 +struct mgmt_cp_set_local_name { + __u8 name[MGMT_MAX_NAME_LENGTH]; +} __packed; + #define MGMT_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { __le16 opcode; @@ -239,3 +244,8 @@ struct mgmt_ev_auth_failed { bdaddr_t bdaddr; __u8 status; } __packed; + +#define MGMT_EV_LOCAL_NAME_CHANGED 0x0011 +struct mgmt_ev_local_name_changed { + __u8 name[MGMT_MAX_NAME_LENGTH]; +} __packed; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 91ef52673ed3..0def3e1fe5ef 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -193,13 +193,16 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) BT_DBG("%s status 0x%x", hdev->name, status); - if (status) - return; - sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); if (!sent) return; + if (test_bit(HCI_MGMT, &hdev->flags)) + mgmt_set_local_name_complete(hdev->id, sent, status); + + if (status) + return; + memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); } diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index ffdb2f4e8635..f7ce78235590 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1256,6 +1256,45 @@ failed: return err; } +static int set_local_name(struct sock *sk, u16 index, unsigned char *data, + u16 len) +{ + struct mgmt_cp_set_local_name *mgmt_cp = (void *) data; + struct hci_cp_write_local_name hci_cp; + struct hci_dev *hdev; + struct pending_cmd *cmd; + int err; + + BT_DBG(""); + + if (len != sizeof(*mgmt_cp)) + return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, EINVAL); + + hdev = hci_dev_get(index); + if (!hdev) + return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, ENODEV); + + hci_dev_lock_bh(hdev); + + cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, index, data, len); + if (!cmd) { + err = -ENOMEM; + goto failed; + } + + memcpy(hci_cp.name, mgmt_cp->name, sizeof(hci_cp.name)); + err = hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(hci_cp), + &hci_cp); + if (err < 0) + mgmt_pending_remove(cmd); + +failed: + hci_dev_unlock_bh(hdev); + hci_dev_put(hdev); + + return err; +} + int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) { unsigned char *buf; @@ -1351,6 +1390,9 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) case MGMT_OP_USER_CONFIRM_NEG_REPLY: err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 0); break; + case MGMT_OP_SET_LOCAL_NAME: + err = set_local_name(sk, index, buf + sizeof(*hdr), len); + break; default: BT_DBG("Unknown op %u", opcode); err = cmd_status(sk, index, opcode, 0x01); @@ -1647,3 +1689,36 @@ int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status) return mgmt_event(MGMT_EV_AUTH_FAILED, index, &ev, sizeof(ev), NULL); } + +int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status) +{ + struct pending_cmd *cmd; + struct mgmt_cp_set_local_name ev; + int err; + + memset(&ev, 0, sizeof(ev)); + memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); + + cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, index); + if (!cmd) + goto send_event; + + if (status) { + err = cmd_status(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, EIO); + goto failed; + } + + err = cmd_complete(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, &ev, + sizeof(ev)); + if (err < 0) + goto failed; + +send_event: + err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, index, &ev, sizeof(ev), + cmd ? cmd->sk : NULL); + +failed: + if (cmd) + mgmt_pending_remove(cmd); + return err; +} -- cgit v1.2.3 From b0d2199d6ff9f788b324fe54b1f783aff83502c4 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 22 Mar 2011 18:06:49 -0300 Subject: Bluetooth: Remove unused struct item num in struct l2cap_chan_list isn't used anywhere. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 4f4bff1eaed6..7a0262524a50 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -280,7 +280,6 @@ struct l2cap_conn_param_update_rsp { struct l2cap_chan_list { struct sock *head; rwlock_t lock; - long num; }; struct l2cap_conn { -- cgit v1.2.3 From c35938b2f56547ee77b5a038fe0db394aeac59bb Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 22 Mar 2011 13:12:21 +0100 Subject: Bluetooth: Add read_local_oob_data management command This patch adds a command to read local OOB data to the managment interface. The command maps directly to the Read Local OOB Data HCI command. Signed-off-by: Szymon Janc Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 7 ++++ include/net/bluetooth/hci_core.h | 2 + include/net/bluetooth/mgmt.h | 6 +++ net/bluetooth/hci_event.c | 15 ++++++++ net/bluetooth/mgmt.c | 83 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 113 insertions(+) (limited to 'include') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 1cd031cd1c4d..ac4de1afe046 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -613,6 +613,13 @@ struct hci_cp_write_ssp_mode { __u8 mode; } __packed; +#define HCI_OP_READ_LOCAL_OOB_DATA 0x0c57 +struct hci_rp_read_local_oob_data { + __u8 status; + __u8 hash[16]; + __u8 randomizer[16]; +} __packed; + #define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58 #define HCI_OP_READ_LOCAL_VERSION 0x1001 diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 3912c7ab717c..fd9b8a31e5b0 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -768,6 +768,8 @@ int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); 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_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, + u8 status); /* HCI info for socket */ #define hci_pi(sk) ((struct hci_pinfo *) sk) diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 89e7c82c4784..6ebb1265c36e 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -177,6 +177,12 @@ struct mgmt_cp_set_local_name { __u8 name[MGMT_MAX_NAME_LENGTH]; } __packed; +#define MGMT_OP_READ_LOCAL_OOB_DATA 0x0018 +struct mgmt_rp_read_local_oob_data { + __u8 hash[16]; + __u8 randomizer[16]; +} __packed; + #define MGMT_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { __le16 opcode; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 0def3e1fe5ef..582ef60a8bc0 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -822,6 +822,17 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, rp->status); } +static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, + struct sk_buff *skb) +{ + struct hci_rp_read_local_oob_data *rp = (void *) skb->data; + + BT_DBG("%s status 0x%x", hdev->name, rp->status); + + mgmt_read_local_oob_data_reply_complete(hdev->id, rp->hash, + rp->randomizer, rp->status); +} + static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) { BT_DBG("%s status 0x%x", hdev->name, status); @@ -1752,6 +1763,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk hci_cc_pin_code_neg_reply(hdev, skb); break; + case HCI_OP_READ_LOCAL_OOB_DATA: + hci_cc_read_local_oob_data_reply(hdev, skb); + break; + case HCI_OP_LE_READ_BUFFER_SIZE: hci_cc_le_read_buffer_size(hdev, skb); break; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 93f0f04c8bcd..33b1f7400dab 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1296,6 +1296,55 @@ failed: return err; } +static int read_local_oob_data(struct sock *sk, u16 index) +{ + struct hci_dev *hdev; + struct pending_cmd *cmd; + int err; + + BT_DBG("hci%u", index); + + hdev = hci_dev_get(index); + if (!hdev) + return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, + ENODEV); + + hci_dev_lock_bh(hdev); + + if (!test_bit(HCI_UP, &hdev->flags)) { + err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, + ENETDOWN); + goto unlock; + } + + if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) { + err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, + EOPNOTSUPP); + goto unlock; + } + + if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index)) { + err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, EBUSY); + goto unlock; + } + + cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, index, NULL, 0); + if (!cmd) { + err = -ENOMEM; + goto unlock; + } + + err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL); + if (err < 0) + mgmt_pending_remove(cmd); + +unlock: + hci_dev_unlock_bh(hdev); + hci_dev_put(hdev); + + return err; +} + int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) { unsigned char *buf; @@ -1394,6 +1443,10 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) case MGMT_OP_SET_LOCAL_NAME: err = set_local_name(sk, index, buf + sizeof(*hdr), len); break; + case MGMT_OP_READ_LOCAL_OOB_DATA: + err = read_local_oob_data(sk, index); + break; + default: BT_DBG("Unknown op %u", opcode); err = cmd_status(sk, index, opcode, 0x01); @@ -1723,3 +1776,33 @@ failed: mgmt_pending_remove(cmd); return err; } + +int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, + u8 status) +{ + struct pending_cmd *cmd; + int err; + + BT_DBG("hci%u status %u", index, status); + + cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index); + if (!cmd) + return -ENOENT; + + if (status) { + err = cmd_status(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, + EIO); + } else { + struct mgmt_rp_read_local_oob_data rp; + + memcpy(rp.hash, hash, sizeof(rp.hash)); + memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer)); + + err = cmd_complete(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, + &rp, sizeof(rp)); + } + + mgmt_pending_remove(cmd); + + return err; +} -- cgit v1.2.3 From 2763eda6ccaf126633bb3180f440c8f3589f0679 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 22 Mar 2011 13:12:22 +0100 Subject: Bluetooth: Add add/remove_remote_oob_data management commands This patch adds commands to add and remove remote OOB data to the managment interface. Remote data is stored in kernel and can be used by corresponding HCI commands and events when needed. Signed-off-by: Szymon Janc Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 17 +++++++++ include/net/bluetooth/hci_core.h | 16 +++++++++ include/net/bluetooth/mgmt.h | 12 +++++++ net/bluetooth/hci_core.c | 67 +++++++++++++++++++++++++++++++++++ net/bluetooth/hci_event.c | 35 +++++++++++++++++++ net/bluetooth/mgmt.c | 75 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 222 insertions(+) (limited to 'include') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index ac4de1afe046..b989a8c3e01a 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -426,6 +426,18 @@ struct hci_rp_user_confirm_reply { #define HCI_OP_USER_CONFIRM_NEG_REPLY 0x042d +#define HCI_OP_REMOTE_OOB_DATA_REPLY 0x0430 +struct hci_cp_remote_oob_data_reply { + bdaddr_t bdaddr; + __u8 hash[16]; + __u8 randomizer[16]; +} __packed; + +#define HCI_OP_REMOTE_OOB_DATA_NEG_REPLY 0x0433 +struct hci_cp_remote_oob_data_neg_reply { + bdaddr_t bdaddr; +} __packed; + #define HCI_OP_IO_CAPABILITY_NEG_REPLY 0x0434 struct hci_cp_io_capability_neg_reply { bdaddr_t bdaddr; @@ -962,6 +974,11 @@ struct hci_ev_user_confirm_req { __le32 passkey; } __packed; +#define HCI_EV_REMOTE_OOB_DATA_REQUEST 0x35 +struct hci_ev_remote_oob_data_request { + bdaddr_t bdaddr; +} __packed; + #define HCI_EV_SIMPLE_PAIR_COMPLETE 0x36 struct hci_ev_simple_pair_complete { __u8 status; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index fd9b8a31e5b0..87bff518b54b 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -82,6 +82,13 @@ struct link_key { u8 pin_len; }; +struct oob_data { + struct list_head list; + bdaddr_t bdaddr; + u8 hash[16]; + u8 randomizer[16]; +}; + #define NUM_REASSEMBLY 4 struct hci_dev { struct list_head list; @@ -169,6 +176,8 @@ struct hci_dev { struct list_head link_keys; + struct list_head remote_oob_data; + struct hci_dev_stats stat; struct sk_buff_head driver_init; @@ -505,6 +514,13 @@ int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, u8 *key, u8 type, u8 pin_len); int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); +int hci_remote_oob_data_clear(struct hci_dev *hdev); +struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev, + bdaddr_t *bdaddr); +int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, + u8 *randomizer); +int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr); + void hci_del_off_timer(struct hci_dev *hdev); void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 6ebb1265c36e..1a6283f9fee8 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -183,6 +183,18 @@ struct mgmt_rp_read_local_oob_data { __u8 randomizer[16]; } __packed; +#define MGMT_OP_ADD_REMOTE_OOB_DATA 0x0019 +struct mgmt_cp_add_remote_oob_data { + bdaddr_t bdaddr; + __u8 hash[16]; + __u8 randomizer[16]; +} __packed; + +#define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x001A +struct mgmt_cp_remove_remote_oob_data { + bdaddr_t bdaddr; +} __packed; + #define MGMT_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { __le16 opcode; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index c20cbe5ff6db..675f0a1832ee 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1076,6 +1076,70 @@ static void hci_cmd_timer(unsigned long arg) tasklet_schedule(&hdev->cmd_task); } +struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev, + bdaddr_t *bdaddr) +{ + struct oob_data *data; + + list_for_each_entry(data, &hdev->remote_oob_data, list) + if (bacmp(bdaddr, &data->bdaddr) == 0) + return data; + + return NULL; +} + +int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr) +{ + struct oob_data *data; + + data = hci_find_remote_oob_data(hdev, bdaddr); + if (!data) + return -ENOENT; + + BT_DBG("%s removing %s", hdev->name, batostr(bdaddr)); + + list_del(&data->list); + kfree(data); + + return 0; +} + +int hci_remote_oob_data_clear(struct hci_dev *hdev) +{ + struct oob_data *data, *n; + + list_for_each_entry_safe(data, n, &hdev->remote_oob_data, list) { + list_del(&data->list); + kfree(data); + } + + return 0; +} + +int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, + u8 *randomizer) +{ + struct oob_data *data; + + data = hci_find_remote_oob_data(hdev, bdaddr); + + if (!data) { + data = kmalloc(sizeof(*data), GFP_ATOMIC); + if (!data) + return -ENOMEM; + + bacpy(&data->bdaddr, bdaddr); + list_add(&data->list, &hdev->remote_oob_data); + } + + memcpy(data->hash, hash, sizeof(data->hash)); + memcpy(data->randomizer, randomizer, sizeof(data->randomizer)); + + BT_DBG("%s for %s", hdev->name, batostr(bdaddr)); + + return 0; +} + /* Register HCI device */ int hci_register_dev(struct hci_dev *hdev) { @@ -1140,6 +1204,8 @@ int hci_register_dev(struct hci_dev *hdev) INIT_LIST_HEAD(&hdev->link_keys); + INIT_LIST_HEAD(&hdev->remote_oob_data); + INIT_WORK(&hdev->power_on, hci_power_on); INIT_WORK(&hdev->power_off, hci_power_off); setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev); @@ -1219,6 +1285,7 @@ int hci_unregister_dev(struct hci_dev *hdev) hci_blacklist_clear(hdev); hci_uuids_clear(hdev); hci_link_keys_clear(hdev); + hci_remote_oob_data_clear(hdev); hci_dev_unlock_bh(hdev); __hci_dev_put(hdev); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 582ef60a8bc0..e0aaf3053667 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2471,6 +2471,37 @@ static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_ hci_dev_unlock(hdev); } +static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, + struct sk_buff *skb) +{ + struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; + struct oob_data *data; + + BT_DBG("%s", hdev->name); + + hci_dev_lock(hdev); + + data = hci_find_remote_oob_data(hdev, &ev->bdaddr); + if (data) { + struct hci_cp_remote_oob_data_reply cp; + + bacpy(&cp.bdaddr, &ev->bdaddr); + memcpy(cp.hash, data->hash, sizeof(cp.hash)); + memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); + + hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), + &cp); + } else { + struct hci_cp_remote_oob_data_neg_reply cp; + + bacpy(&cp.bdaddr, &ev->bdaddr); + hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), + &cp); + } + + hci_dev_unlock(hdev); +} + static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_le_conn_complete *ev = (void *) skb->data; @@ -2673,6 +2704,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) hci_le_meta_evt(hdev, skb); break; + case HCI_EV_REMOTE_OOB_DATA_REQUEST: + hci_remote_oob_data_request_evt(hdev, skb); + break; + default: BT_DBG("%s event 0x%x", hdev->name, event); break; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 33b1f7400dab..a42dc8ca0a6f 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1345,6 +1345,74 @@ unlock: return err; } +static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data, + u16 len) +{ + struct hci_dev *hdev; + struct mgmt_cp_add_remote_oob_data *cp = (void *) data; + int err; + + BT_DBG("hci%u ", index); + + if (len != sizeof(*cp)) + return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, + EINVAL); + + hdev = hci_dev_get(index); + if (!hdev) + return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, + ENODEV); + + hci_dev_lock_bh(hdev); + + err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash, + cp->randomizer); + if (err < 0) + err = cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, -err); + else + err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL, + 0); + + hci_dev_unlock_bh(hdev); + hci_dev_put(hdev); + + return err; +} + +static int remove_remote_oob_data(struct sock *sk, u16 index, + unsigned char *data, u16 len) +{ + struct hci_dev *hdev; + struct mgmt_cp_remove_remote_oob_data *cp = (void *) data; + int err; + + BT_DBG("hci%u ", index); + + if (len != sizeof(*cp)) + return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, + EINVAL); + + hdev = hci_dev_get(index); + if (!hdev) + return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, + ENODEV); + + hci_dev_lock_bh(hdev); + + err = hci_remove_remote_oob_data(hdev, &cp->bdaddr); + if (err < 0) + err = cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, + -err); + else + err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, + NULL, 0); + + hci_dev_unlock_bh(hdev); + hci_dev_put(hdev); + + return err; +} + int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) { unsigned char *buf; @@ -1446,6 +1514,13 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) case MGMT_OP_READ_LOCAL_OOB_DATA: err = read_local_oob_data(sk, index); break; + case MGMT_OP_ADD_REMOTE_OOB_DATA: + err = add_remote_oob_data(sk, index, buf + sizeof(*hdr), len); + break; + case MGMT_OP_REMOVE_REMOTE_OOB_DATA: + err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr), + len); + break; default: BT_DBG("Unknown op %u", opcode); -- cgit v1.2.3 From f3dd4f0f586b3a70734820b68c69985363e2d798 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Thu, 24 Mar 2011 20:14:16 -0300 Subject: Bluetooth: Remove unused struct l2cap_conn item Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 7a0262524a50..2b9ca0d5c4a0 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -301,7 +301,6 @@ struct l2cap_conn { struct sk_buff *rx_skb; __u32 rx_len; - __u8 rx_ident; __u8 tx_ident; __u8 disc_reason; -- cgit v1.2.3 From 80a1e1dbf62a08984d4c1bfb5a4bca38c3e1664f Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 28 Mar 2011 14:07:23 +0300 Subject: Bluetooth: Add local Extended Inquiry Response (EIR) support This patch adds automated creation of the local EIR data based on what 16-bit UUIDs are registered and what the device name is. This should cover the majority use cases, however things like 32/128-bit UUIDs, TX power and Device ID will need to be added later to be on par with what bluetoothd is capable of doing (without the Management interface). Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 8 ++ include/net/bluetooth/hci_core.h | 1 + net/bluetooth/mgmt.c | 163 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+) (limited to 'include') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index b989a8c3e01a..6846ec02dcb0 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -614,6 +614,14 @@ struct hci_cp_host_buffer_size { #define HCI_OP_WRITE_INQUIRY_MODE 0x0c45 +#define HCI_MAX_EIR_LENGTH 240 + +#define HCI_OP_WRITE_EIR 0x0c52 +struct hci_cp_write_eir { + uint8_t fec; + uint8_t data[HCI_MAX_EIR_LENGTH]; +} __packed; + #define HCI_OP_READ_SSP_MODE 0x0c55 struct hci_rp_read_ssp_mode { __u8 status; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 87bff518b54b..3b2f09df279a 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -102,6 +102,7 @@ struct hci_dev { __u8 dev_type; bdaddr_t bdaddr; __u8 dev_name[HCI_MAX_NAME_LENGTH]; + __u8 eir[HCI_MAX_EIR_LENGTH]; __u8 dev_class[3]; __u8 major_class; __u8 minor_class; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index a42dc8ca0a6f..62055c9a8084 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -544,6 +544,150 @@ failed: return err; } +#define EIR_FLAGS 0x01 /* flags */ +#define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */ +#define EIR_UUID16_ALL 0x03 /* 16-bit UUID, all listed */ +#define EIR_UUID32_SOME 0x04 /* 32-bit UUID, more available */ +#define EIR_UUID32_ALL 0x05 /* 32-bit UUID, all listed */ +#define EIR_UUID128_SOME 0x06 /* 128-bit UUID, more available */ +#define EIR_UUID128_ALL 0x07 /* 128-bit UUID, all listed */ +#define EIR_NAME_SHORT 0x08 /* shortened local name */ +#define EIR_NAME_COMPLETE 0x09 /* complete local name */ +#define EIR_TX_POWER 0x0A /* transmit power level */ +#define EIR_DEVICE_ID 0x10 /* device ID */ + +#define PNP_INFO_SVCLASS_ID 0x1200 + +static u8 bluetooth_base_uuid[] = { + 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static u16 get_uuid16(u8 *uuid128) +{ + u32 val; + int i; + + for (i = 0; i < 12; i++) { + if (bluetooth_base_uuid[i] != uuid128[i]) + return 0; + } + + memcpy(&val, &uuid128[12], 4); + + val = le32_to_cpu(val); + if (val > 0xffff) + return 0; + + return (u16) val; +} + +static void create_eir(struct hci_dev *hdev, u8 *data) +{ + u8 *ptr = data; + u16 eir_len = 0; + u16 uuid16_list[HCI_MAX_EIR_LENGTH / sizeof(u16)]; + int i, truncated = 0; + struct list_head *p; + size_t name_len; + + name_len = strlen(hdev->dev_name); + + if (name_len > 0) { + /* EIR Data type */ + if (name_len > 48) { + name_len = 48; + ptr[1] = EIR_NAME_SHORT; + } else + ptr[1] = EIR_NAME_COMPLETE; + + /* EIR Data length */ + ptr[0] = name_len + 1; + + memcpy(ptr + 2, hdev->dev_name, name_len); + + eir_len += (name_len + 2); + ptr += (name_len + 2); + } + + memset(uuid16_list, 0, sizeof(uuid16_list)); + + /* Group all UUID16 types */ + list_for_each(p, &hdev->uuids) { + struct bt_uuid *uuid = list_entry(p, struct bt_uuid, list); + u16 uuid16; + + uuid16 = get_uuid16(uuid->uuid); + if (uuid16 == 0) + return; + + if (uuid16 < 0x1100) + continue; + + if (uuid16 == PNP_INFO_SVCLASS_ID) + continue; + + /* Stop if not enough space to put next UUID */ + if (eir_len + 2 + sizeof(u16) > HCI_MAX_EIR_LENGTH) { + truncated = 1; + break; + } + + /* Check for duplicates */ + for (i = 0; uuid16_list[i] != 0; i++) + if (uuid16_list[i] == uuid16) + break; + + if (uuid16_list[i] == 0) { + uuid16_list[i] = uuid16; + eir_len += sizeof(u16); + } + } + + if (uuid16_list[0] != 0) { + u8 *length = ptr; + + /* EIR Data type */ + ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL; + + ptr += 2; + eir_len += 2; + + for (i = 0; uuid16_list[i] != 0; i++) { + *ptr++ = (uuid16_list[i] & 0x00ff); + *ptr++ = (uuid16_list[i] & 0xff00) >> 8; + } + + /* EIR Data length */ + *length = (i * sizeof(u16)) + 1; + } +} + +static int update_eir(struct hci_dev *hdev) +{ + struct hci_cp_write_eir cp; + + if (!(hdev->features[6] & LMP_EXT_INQ)) + return 0; + + if (hdev->ssp_mode == 0) + return 0; + + if (test_bit(HCI_SERVICE_CACHE, &hdev->flags)) + return 0; + + memset(&cp, 0, sizeof(cp)); + + create_eir(hdev, cp.data); + + if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0) + return 0; + + memcpy(hdev->eir, cp.data, sizeof(cp.data)); + + return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); +} + static u8 get_service_classes(struct hci_dev *hdev) { struct list_head *p; @@ -612,6 +756,10 @@ static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) if (err < 0) goto failed; + err = update_eir(hdev); + if (err < 0) + goto failed; + err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0); failed: @@ -668,6 +816,10 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) if (err < 0) goto unlock; + err = update_eir(hdev); + if (err < 0) + goto unlock; + err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0); unlock: @@ -737,6 +889,8 @@ static int set_service_cache(struct sock *sk, u16 index, unsigned char *data, } else { clear_bit(HCI_SERVICE_CACHE, &hdev->flags); err = update_class(hdev); + if (err == 0) + err = update_eir(hdev); } if (err == 0) @@ -1822,6 +1976,7 @@ int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status) int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status) { struct pending_cmd *cmd; + struct hci_dev *hdev; struct mgmt_cp_set_local_name ev; int err; @@ -1837,6 +1992,14 @@ int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status) goto failed; } + hdev = hci_dev_get(index); + if (hdev) { + hci_dev_lock_bh(hdev); + update_eir(hdev); + hci_dev_unlock_bh(hdev); + hci_dev_put(hdev); + } + err = cmd_complete(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, &ev, sizeof(ev)); if (err < 0) -- cgit v1.2.3 From 105721328f0fa53e772592eaca17ee0023f0cc87 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 16 Mar 2011 15:36:29 -0300 Subject: Bluetooth: Fix HCI_RESET command synchronization We can't send new commands before a cmd_complete for the HCI_RESET command shows up. Reported-by: Mikko Vinni Reported-by: Justin P. Mattock Reported-by: Ed Tomlinson Signed-off-by: Gustavo F. Padovan Tested-by: Justin P. Mattock Tested-by: Mikko Vinni Tested-by: Ed Tomlinson --- include/net/bluetooth/hci.h | 2 ++ net/bluetooth/hci_core.c | 6 +++++- net/bluetooth/hci_event.c | 4 +++- 3 files changed, 10 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index ec6acf2f1c0b..2c0d309c7381 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -84,6 +84,8 @@ enum { HCI_SERVICE_CACHE, HCI_LINK_KEYS, HCI_DEBUG_KEYS, + + HCI_RESET, }; /* HCI ioctl defines */ diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index b372fb8bcdcf..92b48e257b89 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -186,6 +186,7 @@ static void hci_reset_req(struct hci_dev *hdev, unsigned long opt) BT_DBG("%s %ld", hdev->name, opt); /* Reset device */ + set_bit(HCI_RESET, &hdev->flags); hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL); } @@ -213,8 +214,10 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt) /* Mandatory initialization */ /* Reset */ - if (!test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks)) + if (!test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks)) { + set_bit(HCI_RESET, &hdev->flags); hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL); + } /* Read Local Supported Features */ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL); @@ -1074,6 +1077,7 @@ static void hci_cmd_timer(unsigned long arg) BT_ERR("%s command tx timeout", hdev->name); atomic_set(&hdev->cmd_cnt, 1); + clear_bit(HCI_RESET, &hdev->flags); tasklet_schedule(&hdev->cmd_task); } diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 3fbfa50c2bff..cebe7588469f 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -183,6 +183,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) BT_DBG("%s status 0x%x", hdev->name, status); + clear_bit(HCI_RESET, &hdev->flags); + hci_req_complete(hdev, HCI_OP_RESET, status); } @@ -1847,7 +1849,7 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) if (ev->opcode != HCI_OP_NOP) del_timer(&hdev->cmd_timer); - if (ev->ncmd) { + if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { atomic_set(&hdev->cmd_cnt, 1); if (!skb_queue_empty(&hdev->cmd_q)) tasklet_schedule(&hdev->cmd_task); -- cgit v1.2.3 From e17acd40f6006d0a0e0b1b3f7359ba4d543011c6 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 30 Mar 2011 23:57:16 +0300 Subject: Bluetooth: Add mgmt_device_found event This patch adds a device_found event to the Management interface. For now the event only maps to BR/EDR inquiry result HCI events, but in the future the plan is to also use it for the LE device discovery process. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 2 ++ include/net/bluetooth/mgmt.h | 8 ++++++++ net/bluetooth/hci_event.c | 22 ++++++++++++++-------- net/bluetooth/mgmt.c | 17 +++++++++++++++++ 4 files changed, 41 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 3b2f09df279a..2a88fc82429b 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -787,6 +787,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_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, u8 status); +int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, + u8 *eir); /* HCI info for socket */ #define hci_pi(sk) ((struct hci_pinfo *) sk) diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 1a6283f9fee8..864d0cbd2d57 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -267,3 +267,11 @@ struct mgmt_ev_auth_failed { struct mgmt_ev_local_name_changed { __u8 name[MGMT_MAX_NAME_LENGTH]; } __packed; + +#define MGMT_EV_DEVICE_FOUND 0x0012 +struct mgmt_ev_device_found { + bdaddr_t bdaddr; + __u8 dev_class[3]; + __s8 rssi; + __u8 eir[HCI_MAX_EIR_LENGTH]; +} __packed; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 833797e9654b..d04011c06be0 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1228,7 +1228,7 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff * hci_dev_lock(hdev); - for (; num_rsp; num_rsp--) { + for (; num_rsp; num_rsp--, info++) { bacpy(&data.bdaddr, &info->bdaddr); data.pscan_rep_mode = info->pscan_rep_mode; data.pscan_period_mode = info->pscan_period_mode; @@ -1237,8 +1237,9 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff * data.clock_offset = info->clock_offset; data.rssi = 0x00; data.ssp_mode = 0x00; - info++; hci_inquiry_cache_update(hdev, &data); + mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 0, + NULL); } hci_dev_unlock(hdev); @@ -2158,7 +2159,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct struct inquiry_info_with_rssi_and_pscan_mode *info; info = (void *) (skb->data + 1); - for (; num_rsp; num_rsp--) { + for (; num_rsp; num_rsp--, info++) { bacpy(&data.bdaddr, &info->bdaddr); data.pscan_rep_mode = info->pscan_rep_mode; data.pscan_period_mode = info->pscan_period_mode; @@ -2167,13 +2168,15 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct data.clock_offset = info->clock_offset; data.rssi = info->rssi; data.ssp_mode = 0x00; - info++; hci_inquiry_cache_update(hdev, &data); + mgmt_device_found(hdev->id, &info->bdaddr, + info->dev_class, info->rssi, + NULL); } } else { struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); - for (; num_rsp; num_rsp--) { + for (; num_rsp; num_rsp--, info++) { bacpy(&data.bdaddr, &info->bdaddr); data.pscan_rep_mode = info->pscan_rep_mode; data.pscan_period_mode = info->pscan_period_mode; @@ -2182,8 +2185,10 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct data.clock_offset = info->clock_offset; data.rssi = info->rssi; data.ssp_mode = 0x00; - info++; hci_inquiry_cache_update(hdev, &data); + mgmt_device_found(hdev->id, &info->bdaddr, + info->dev_class, info->rssi, + NULL); } } @@ -2314,7 +2319,7 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct hci_dev_lock(hdev); - for (; num_rsp; num_rsp--) { + for (; num_rsp; num_rsp--, info++) { bacpy(&data.bdaddr, &info->bdaddr); data.pscan_rep_mode = info->pscan_rep_mode; data.pscan_period_mode = info->pscan_period_mode; @@ -2323,8 +2328,9 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct data.clock_offset = info->clock_offset; data.rssi = info->rssi; data.ssp_mode = 0x01; - info++; hci_inquiry_cache_update(hdev, &data); + mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, + info->rssi, info->data); } hci_dev_unlock(hdev); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index f87691e04dca..86fb50215485 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2046,3 +2046,20 @@ int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, return err; } + +int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, + u8 *eir) +{ + struct mgmt_ev_device_found ev; + + memset(&ev, 0, sizeof(ev)); + + bacpy(&ev.bdaddr, bdaddr); + memcpy(ev.dev_class, dev_class, sizeof(ev.dev_class)); + ev.rssi = rssi; + + if (eir) + memcpy(ev.eir, eir, sizeof(ev.eir)); + + return mgmt_event(MGMT_EV_DEVICE_FOUND, index, &ev, sizeof(ev), NULL); +} -- cgit v1.2.3 From a88a9652d25a63ce10b6a5fe680d0ad8f33b9c9b Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 30 Mar 2011 13:18:12 +0300 Subject: Bluetooth: Add mgmt_remote_name event This patch adds a new remote_name event to the Management interface which is sent every time the name of a remote device is resolved (over BR/EDR). Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 1 + include/net/bluetooth/mgmt.h | 6 ++++++ net/bluetooth/hci_event.c | 3 +++ net/bluetooth/mgmt.c | 12 ++++++++++++ 4 files changed, 22 insertions(+) (limited to 'include') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 2a88fc82429b..4093133c1283 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -789,6 +789,7 @@ int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, u8 status); int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, u8 *eir); +int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name); /* HCI info for socket */ #define hci_pi(sk) ((struct hci_pinfo *) sk) diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 864d0cbd2d57..6b6ff92ab499 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -275,3 +275,9 @@ struct mgmt_ev_device_found { __s8 rssi; __u8 eir[HCI_MAX_EIR_LENGTH]; } __packed; + +#define MGMT_EV_REMOTE_NAME 0x0013 +struct mgmt_ev_remote_name { + bdaddr_t bdaddr; + __u8 name[MGMT_MAX_NAME_LENGTH]; +} __packed; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index d04011c06be0..7a3398d9cd65 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1497,6 +1497,9 @@ static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb hci_dev_lock(hdev); + if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags)) + mgmt_remote_name(hdev->id, &ev->bdaddr, ev->name); + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); if (conn && hci_outgoing_auth_needed(hdev, conn)) { struct hci_cp_auth_requested cp; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 86fb50215485..9a61320c5f2e 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2063,3 +2063,15 @@ int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, return mgmt_event(MGMT_EV_DEVICE_FOUND, index, &ev, sizeof(ev), NULL); } + +int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name) +{ + struct mgmt_ev_remote_name ev; + + memset(&ev, 0, sizeof(ev)); + + bacpy(&ev.bdaddr, bdaddr); + memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); + + return mgmt_event(MGMT_EV_REMOTE_NAME, index, &ev, sizeof(ev), NULL); +} -- cgit v1.2.3