Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Michał Narajowski and committed by
Marcel Holtmann
7c295c48 1110a2db

+64 -10
+20 -8
net/bluetooth/hci_request.c
··· 971 971 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); 972 972 } 973 973 974 - static u8 create_default_scan_rsp_data(struct hci_dev *hdev, u8 *ptr) 974 + static u8 append_local_name(struct hci_dev *hdev, u8 *ptr, u8 ad_len) 975 975 { 976 - u8 ad_len = 0; 977 976 size_t name_len; 977 + int max_len; 978 978 979 + max_len = HCI_MAX_AD_LENGTH - ad_len - 2; 979 980 name_len = strlen(hdev->dev_name); 980 - if (name_len > 0) { 981 - size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2; 981 + if (name_len > 0 && max_len > 0) { 982 982 983 983 if (name_len > max_len) { 984 984 name_len = max_len; ··· 997 997 return ad_len; 998 998 } 999 999 1000 + static u8 create_default_scan_rsp_data(struct hci_dev *hdev, u8 *ptr) 1001 + { 1002 + return append_local_name(hdev, ptr, 0); 1003 + } 1004 + 1000 1005 static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 instance, 1001 1006 u8 *ptr) 1002 1007 { 1003 1008 struct adv_info *adv_instance; 1009 + u32 instance_flags; 1010 + u8 scan_rsp_len = 0; 1004 1011 1005 1012 adv_instance = hci_find_adv_instance(hdev, instance); 1006 1013 if (!adv_instance) 1007 1014 return 0; 1008 1015 1009 - /* TODO: Set the appropriate entries based on advertising instance flags 1010 - * here once flags other than 0 are supported. 1011 - */ 1016 + instance_flags = adv_instance->flags; 1017 + 1012 1018 memcpy(ptr, adv_instance->scan_rsp_data, 1013 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 1018 1030 void __hci_req_update_scan_rsp_data(struct hci_request *req, u8 instance)
+44 -2
net/bluetooth/mgmt.c
··· 3012 3012 HCI_OP_USER_PASSKEY_NEG_REPLY, 0); 3013 3013 } 3014 3014 3015 + static 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 + 3015 3044 static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode) 3016 3045 { 3017 3046 struct mgmt_cp_set_local_name *cp; ··· 3056 3027 3057 3028 cp = cmd->param; 3058 3029 3059 - if (status) 3030 + if (status) { 3060 3031 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 3061 3032 mgmt_status(status)); 3062 - else 3033 + } else { 3063 3034 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0, 3064 3035 cp, sizeof(*cp)); 3036 + 3037 + if (hci_dev_test_flag(hdev, HCI_LE_ADV)) 3038 + adv_expire(hdev, MGMT_ADV_FLAG_LOCAL_NAME); 3039 + } 3065 3040 3066 3041 mgmt_pending_remove(cmd); 3067 3042 ··· 5918 5885 flags |= MGMT_ADV_FLAG_DISCOV; 5919 5886 flags |= MGMT_ADV_FLAG_LIMITED_DISCOV; 5920 5887 flags |= MGMT_ADV_FLAG_MANAGED_FLAGS; 5888 + flags |= MGMT_ADV_FLAG_LOCAL_NAME; 5921 5889 5922 5890 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) 5923 5891 flags |= MGMT_ADV_FLAG_TX_POWER; ··· 5995 5961 tx_power_managed = true; 5996 5962 max_len -= 3; 5997 5963 } 5964 + } else { 5965 + /* at least 1 byte of name should fit in */ 5966 + if (adv_flags & MGMT_ADV_FLAG_LOCAL_NAME) 5967 + max_len -= 3; 5998 5968 } 5999 5969 6000 5970 if (len > max_len) ··· 6330 6292 max_len -= 3; 6331 6293 6332 6294 if (adv_flags & MGMT_ADV_FLAG_TX_POWER) 6295 + max_len -= 3; 6296 + } else { 6297 + /* at least 1 byte of name should fit in */ 6298 + if (adv_flags & MGMT_ADV_FLAG_LOCAL_NAME) 6333 6299 max_len -= 3; 6334 6300 } 6335 6301