aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichał Narajowski <michal.narajowski@codecoup.pl>2016-09-18 06:50:02 -0400
committerMarcel Holtmann <marcel@holtmann.org>2016-09-19 14:19:34 -0400
commit7c295c4801b2de24fc25687eb0cb73cf0c99d114 (patch)
tree16897e509d1fb647184b89d3f310290c860d4993
parent1110a2dbe69831abdcf119c3a9a4c4ef2d0905f8 (diff)
Bluetooth: Add support for local name in scan rsp
This patch enables appending local name to scan response data. If currently advertised instance has name flag set it is expired immediately. Signed-off-by: Michał Narajowski <michal.narajowski@codecoup.pl> Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--net/bluetooth/hci_request.c28
-rw-r--r--net/bluetooth/mgmt.c46
2 files changed, 64 insertions, 10 deletions
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index 9566ff8e3223..0ce6cdd278b2 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -971,14 +971,14 @@ void __hci_req_enable_advertising(struct hci_request *req)
971 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); 971 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
972} 972}
973 973
974static u8 create_default_scan_rsp_data(struct hci_dev *hdev, u8 *ptr) 974static u8 append_local_name(struct hci_dev *hdev, u8 *ptr, u8 ad_len)
975{ 975{
976 u8 ad_len = 0;
977 size_t name_len; 976 size_t name_len;
977 int max_len;
978 978
979 max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
979 name_len = strlen(hdev->dev_name); 980 name_len = strlen(hdev->dev_name);
980 if (name_len > 0) { 981 if (name_len > 0 && max_len > 0) {
981 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
982 982
983 if (name_len > max_len) { 983 if (name_len > max_len) {
984 name_len = max_len; 984 name_len = max_len;
@@ -997,22 +997,34 @@ static u8 create_default_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
997 return ad_len; 997 return ad_len;
998} 998}
999 999
1000static u8 create_default_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
1001{
1002 return append_local_name(hdev, ptr, 0);
1003}
1004
1000static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 instance, 1005static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 instance,
1001 u8 *ptr) 1006 u8 *ptr)
1002{ 1007{
1003 struct adv_info *adv_instance; 1008 struct adv_info *adv_instance;
1009 u32 instance_flags;
1010 u8 scan_rsp_len = 0;
1004 1011
1005 adv_instance = hci_find_adv_instance(hdev, instance); 1012 adv_instance = hci_find_adv_instance(hdev, instance);
1006 if (!adv_instance) 1013 if (!adv_instance)
1007 return 0; 1014 return 0;
1008 1015
1009 /* TODO: Set the appropriate entries based on advertising instance flags 1016 instance_flags = adv_instance->flags;
1010 * here once flags other than 0 are supported. 1017
1011 */
1012 memcpy(ptr, adv_instance->scan_rsp_data, 1018 memcpy(ptr, adv_instance->scan_rsp_data,
1013 adv_instance->scan_rsp_len); 1019 adv_instance->scan_rsp_len);
1014 1020
1015 return adv_instance->scan_rsp_len; 1021 scan_rsp_len += adv_instance->scan_rsp_len;
1022 ptr += adv_instance->scan_rsp_len;
1023
1024 if (instance_flags & MGMT_ADV_FLAG_LOCAL_NAME)
1025 scan_rsp_len = append_local_name(hdev, ptr, scan_rsp_len);
1026
1027 return scan_rsp_len;
1016} 1028}
1017 1029
1018void __hci_req_update_scan_rsp_data(struct hci_request *req, u8 instance) 1030void __hci_req_update_scan_rsp_data(struct hci_request *req, u8 instance)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 0ac881cfc646..89954bb19222 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3012,6 +3012,35 @@ static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
3012 HCI_OP_USER_PASSKEY_NEG_REPLY, 0); 3012 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
3013} 3013}
3014 3014
3015static void adv_expire(struct hci_dev *hdev, u32 flags)
3016{
3017 struct adv_info *adv_instance;
3018 struct hci_request req;
3019 int err;
3020
3021 adv_instance = hci_find_adv_instance(hdev, hdev->cur_adv_instance);
3022 if (!adv_instance)
3023 return;
3024
3025 /* stop if current instance doesn't need to be changed */
3026 if (!(adv_instance->flags & flags))
3027 return;
3028
3029 cancel_adv_timeout(hdev);
3030
3031 adv_instance = hci_get_next_instance(hdev, adv_instance->instance);
3032 if (!adv_instance)
3033 return;
3034
3035 hci_req_init(&req, hdev);
3036 err = __hci_req_schedule_adv_instance(&req, adv_instance->instance,
3037 true);
3038 if (err)
3039 return;
3040
3041 hci_req_run(&req, NULL);
3042}
3043
3015static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode) 3044static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
3016{ 3045{
3017 struct mgmt_cp_set_local_name *cp; 3046 struct mgmt_cp_set_local_name *cp;
@@ -3027,13 +3056,17 @@ static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
3027 3056
3028 cp = cmd->param; 3057 cp = cmd->param;
3029 3058
3030 if (status) 3059 if (status) {
3031 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 3060 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3032 mgmt_status(status)); 3061 mgmt_status(status));
3033 else 3062 } else {
3034 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0, 3063 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3035 cp, sizeof(*cp)); 3064 cp, sizeof(*cp));
3036 3065
3066 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
3067 adv_expire(hdev, MGMT_ADV_FLAG_LOCAL_NAME);
3068 }
3069
3037 mgmt_pending_remove(cmd); 3070 mgmt_pending_remove(cmd);
3038 3071
3039unlock: 3072unlock:
@@ -5885,6 +5918,7 @@ static u32 get_supported_adv_flags(struct hci_dev *hdev)
5885 flags |= MGMT_ADV_FLAG_DISCOV; 5918 flags |= MGMT_ADV_FLAG_DISCOV;
5886 flags |= MGMT_ADV_FLAG_LIMITED_DISCOV; 5919 flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
5887 flags |= MGMT_ADV_FLAG_MANAGED_FLAGS; 5920 flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
5921 flags |= MGMT_ADV_FLAG_LOCAL_NAME;
5888 5922
5889 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) 5923 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID)
5890 flags |= MGMT_ADV_FLAG_TX_POWER; 5924 flags |= MGMT_ADV_FLAG_TX_POWER;
@@ -5961,6 +5995,10 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
5961 tx_power_managed = true; 5995 tx_power_managed = true;
5962 max_len -= 3; 5996 max_len -= 3;
5963 } 5997 }
5998 } else {
5999 /* at least 1 byte of name should fit in */
6000 if (adv_flags & MGMT_ADV_FLAG_LOCAL_NAME)
6001 max_len -= 3;
5964 } 6002 }
5965 6003
5966 if (len > max_len) 6004 if (len > max_len)
@@ -6293,6 +6331,10 @@ static u8 tlv_data_max_len(u32 adv_flags, bool is_adv_data)
6293 6331
6294 if (adv_flags & MGMT_ADV_FLAG_TX_POWER) 6332 if (adv_flags & MGMT_ADV_FLAG_TX_POWER)
6295 max_len -= 3; 6333 max_len -= 3;
6334 } else {
6335 /* at least 1 byte of name should fit in */
6336 if (adv_flags & MGMT_ADV_FLAG_LOCAL_NAME)
6337 max_len -= 3;
6296 } 6338 }
6297 6339
6298 return max_len; 6340 return max_len;