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

Bluetooth: Unify advertising data code paths

This patch simplifies the code paths for assembling the advertising data
used by advertising instances 0 and 1.

Signed-off-by: Arman Uguray <armansito@chromium.org>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>

authored by

Arman Uguray and committed by
Marcel Holtmann
fdf51784 089fa8c0

+86 -113
+86 -113
net/bluetooth/mgmt.c
··· 941 941 return 0; 942 942 } 943 943 944 - static u8 create_default_adv_data(struct hci_dev *hdev, u8 *ptr) 945 - { 946 - u8 ad_len = 0, flags = 0; 947 - 948 - flags |= get_adv_discov_flags(hdev); 949 - 950 - if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) 951 - flags |= LE_AD_NO_BREDR; 952 - 953 - if (flags) { 954 - BT_DBG("adv flags 0x%02x", flags); 955 - 956 - ptr[0] = 2; 957 - ptr[1] = EIR_FLAGS; 958 - ptr[2] = flags; 959 - 960 - ad_len += 3; 961 - ptr += 3; 962 - } 963 - 964 - if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) { 965 - ptr[0] = 2; 966 - ptr[1] = EIR_TX_POWER; 967 - ptr[2] = (u8) hdev->adv_tx_power; 968 - 969 - ad_len += 3; 970 - ptr += 3; 971 - } 972 - 973 - return ad_len; 974 - } 975 - 976 - static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr) 977 - { 978 - u8 ad_len = 0, flags = 0; 979 - 980 - /* The Add Advertising command allows userspace to set both the general 981 - * and limited discoverable flags. 982 - */ 983 - if (hdev->adv_instance.flags & MGMT_ADV_FLAG_DISCOV) 984 - flags |= LE_AD_GENERAL; 985 - 986 - if (hdev->adv_instance.flags & MGMT_ADV_FLAG_LIMITED_DISCOV) 987 - flags |= LE_AD_LIMITED; 988 - 989 - if (flags || (hdev->adv_instance.flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) { 990 - /* If a discovery flag wasn't provided, simply use the global 991 - * settings. 992 - */ 993 - if (!flags) 994 - flags |= get_adv_discov_flags(hdev); 995 - 996 - if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) 997 - flags |= LE_AD_NO_BREDR; 998 - 999 - ptr[0] = 0x02; 1000 - ptr[1] = EIR_FLAGS; 1001 - ptr[2] = flags; 1002 - 1003 - ad_len += 3; 1004 - ptr += 3; 1005 - } 1006 - 1007 - if (hdev->adv_tx_power != HCI_TX_POWER_INVALID && 1008 - (hdev->adv_instance.flags & MGMT_ADV_FLAG_TX_POWER)) { 1009 - ptr[0] = 0x02; 1010 - ptr[1] = EIR_TX_POWER; 1011 - ptr[2] = (u8)hdev->adv_tx_power; 1012 - 1013 - ad_len += 3; 1014 - ptr += 3; 1015 - } 1016 - 1017 - memcpy(ptr, hdev->adv_instance.adv_data, 1018 - hdev->adv_instance.adv_data_len); 1019 - ad_len += hdev->adv_instance.adv_data_len; 1020 - 1021 - return ad_len; 1022 - } 1023 - 1024 - static void update_adv_data_for_instance(struct hci_request *req, u8 instance) 1025 - { 1026 - struct hci_dev *hdev = req->hdev; 1027 - struct hci_cp_le_set_adv_data cp; 1028 - u8 len; 1029 - 1030 - if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) 1031 - return; 1032 - 1033 - memset(&cp, 0, sizeof(cp)); 1034 - 1035 - if (instance) 1036 - len = create_instance_adv_data(hdev, cp.data); 1037 - else 1038 - len = create_default_adv_data(hdev, cp.data); 1039 - 1040 - /* There's nothing to do if the data hasn't changed */ 1041 - if (hdev->adv_data_len == len && 1042 - memcmp(cp.data, hdev->adv_data, len) == 0) 1043 - return; 1044 - 1045 - memcpy(hdev->adv_data, cp.data, sizeof(cp.data)); 1046 - hdev->adv_data_len = len; 1047 - 1048 - cp.length = len; 1049 - 1050 - hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); 1051 - } 1052 - 1053 944 static u8 get_current_adv_instance(struct hci_dev *hdev) 1054 945 { 1055 946 /* The "Set Advertising" setting supersedes the "Add Advertising" ··· 979 1088 if (instance > 0x01) 980 1089 return 0; 981 1090 982 - if (instance == 1) 1091 + if (instance == 0x01) 983 1092 return hdev->adv_instance.flags; 984 1093 985 - flags = 0; 1094 + /* Instance 0 always manages the "Tx Power" and "Flags" fields */ 1095 + flags = MGMT_ADV_FLAG_TX_POWER | MGMT_ADV_FLAG_MANAGED_FLAGS; 986 1096 987 1097 /* For instance 0, assemble the flags from global settings */ 988 1098 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE) || 989 1099 get_connectable(hdev)) 990 1100 flags |= MGMT_ADV_FLAG_CONNECTABLE; 991 1101 992 - /* TODO: Add the rest of the flags */ 993 - 994 1102 return flags; 1103 + } 1104 + 1105 + static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr) 1106 + { 1107 + u8 ad_len = 0, flags = 0; 1108 + u32 instance_flags = get_adv_instance_flags(hdev, instance); 1109 + 1110 + /* The Add Advertising command allows userspace to set both the general 1111 + * and limited discoverable flags. 1112 + */ 1113 + if (instance_flags & MGMT_ADV_FLAG_DISCOV) 1114 + flags |= LE_AD_GENERAL; 1115 + 1116 + if (instance_flags & MGMT_ADV_FLAG_LIMITED_DISCOV) 1117 + flags |= LE_AD_LIMITED; 1118 + 1119 + if (flags || (instance_flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) { 1120 + /* If a discovery flag wasn't provided, simply use the global 1121 + * settings. 1122 + */ 1123 + if (!flags) 1124 + flags |= get_adv_discov_flags(hdev); 1125 + 1126 + if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) 1127 + flags |= LE_AD_NO_BREDR; 1128 + 1129 + /* If flags would still be empty, then there is no need to 1130 + * include the "Flags" AD field". 1131 + */ 1132 + if (flags) { 1133 + ptr[0] = 0x02; 1134 + ptr[1] = EIR_FLAGS; 1135 + ptr[2] = flags; 1136 + 1137 + ad_len += 3; 1138 + ptr += 3; 1139 + } 1140 + } 1141 + 1142 + /* Provide Tx Power only if we can provide a valid value for it */ 1143 + if (hdev->adv_tx_power != HCI_TX_POWER_INVALID && 1144 + (instance_flags & MGMT_ADV_FLAG_TX_POWER)) { 1145 + ptr[0] = 0x02; 1146 + ptr[1] = EIR_TX_POWER; 1147 + ptr[2] = (u8)hdev->adv_tx_power; 1148 + 1149 + ad_len += 3; 1150 + ptr += 3; 1151 + } 1152 + 1153 + if (instance) { 1154 + memcpy(ptr, hdev->adv_instance.adv_data, 1155 + hdev->adv_instance.adv_data_len); 1156 + ad_len += hdev->adv_instance.adv_data_len; 1157 + } 1158 + 1159 + return ad_len; 1160 + } 1161 + 1162 + static void update_adv_data_for_instance(struct hci_request *req, u8 instance) 1163 + { 1164 + struct hci_dev *hdev = req->hdev; 1165 + struct hci_cp_le_set_adv_data cp; 1166 + u8 len; 1167 + 1168 + if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) 1169 + return; 1170 + 1171 + memset(&cp, 0, sizeof(cp)); 1172 + 1173 + len = create_instance_adv_data(hdev, instance, cp.data); 1174 + 1175 + /* There's nothing to do if the data hasn't changed */ 1176 + if (hdev->adv_data_len == len && 1177 + memcmp(cp.data, hdev->adv_data, len) == 0) 1178 + return; 1179 + 1180 + memcpy(hdev->adv_data, cp.data, sizeof(cp.data)); 1181 + hdev->adv_data_len = len; 1182 + 1183 + cp.length = len; 1184 + 1185 + hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); 995 1186 } 996 1187 997 1188 static void update_adv_data(struct hci_request *req)