aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorArman Uguray <armansito@chromium.org>2015-03-25 21:53:46 -0400
committerMarcel Holtmann <marcel@holtmann.org>2015-03-25 22:30:29 -0400
commitfdf51784cd728e55daa0ca7b0ba16966afbfeae0 (patch)
tree03079295611a83b333d5e3cf68be069bb644ea61 /net
parent089fa8c09e7fd36b9db01c23c826fb7956f25a1e (diff)
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>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/mgmt.c155
1 files changed, 64 insertions, 91 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index eab09b5a71df..fb2e764c6211 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -941,52 +941,73 @@ static u8 get_adv_discov_flags(struct hci_dev *hdev)
941 return 0; 941 return 0;
942} 942}
943 943
944static u8 create_default_adv_data(struct hci_dev *hdev, u8 *ptr) 944static u8 get_current_adv_instance(struct hci_dev *hdev)
945{ 945{
946 u8 ad_len = 0, flags = 0; 946 /* The "Set Advertising" setting supersedes the "Add Advertising"
947 947 * setting. Here we set the advertising data based on which
948 flags |= get_adv_discov_flags(hdev); 948 * setting was set. When neither apply, default to the global settings,
949 * represented by instance "0".
950 */
951 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
952 !hci_dev_test_flag(hdev, HCI_ADVERTISING))
953 return 0x01;
949 954
950 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) 955 return 0x00;
951 flags |= LE_AD_NO_BREDR; 956}
952 957
953 if (flags) { 958static bool get_connectable(struct hci_dev *hdev)
954 BT_DBG("adv flags 0x%02x", flags); 959{
960 struct mgmt_pending_cmd *cmd;
955 961
956 ptr[0] = 2; 962 /* If there's a pending mgmt command the flag will not yet have
957 ptr[1] = EIR_FLAGS; 963 * it's final value, so check for this first.
958 ptr[2] = flags; 964 */
965 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
966 if (cmd) {
967 struct mgmt_mode *cp = cmd->param;
959 968
960 ad_len += 3; 969 return cp->val;
961 ptr += 3;
962 } 970 }
963 971
964 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) { 972 return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
965 ptr[0] = 2; 973}
966 ptr[1] = EIR_TX_POWER;
967 ptr[2] = (u8) hdev->adv_tx_power;
968 974
969 ad_len += 3; 975static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
970 ptr += 3; 976{
971 } 977 u32 flags;
972 978
973 return ad_len; 979 if (instance > 0x01)
980 return 0;
981
982 if (instance == 0x01)
983 return hdev->adv_instance.flags;
984
985 /* Instance 0 always manages the "Tx Power" and "Flags" fields */
986 flags = MGMT_ADV_FLAG_TX_POWER | MGMT_ADV_FLAG_MANAGED_FLAGS;
987
988 /* For instance 0, assemble the flags from global settings */
989 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE) ||
990 get_connectable(hdev))
991 flags |= MGMT_ADV_FLAG_CONNECTABLE;
992
993 return flags;
974} 994}
975 995
976static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr) 996static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
977{ 997{
978 u8 ad_len = 0, flags = 0; 998 u8 ad_len = 0, flags = 0;
999 u32 instance_flags = get_adv_instance_flags(hdev, instance);
979 1000
980 /* The Add Advertising command allows userspace to set both the general 1001 /* The Add Advertising command allows userspace to set both the general
981 * and limited discoverable flags. 1002 * and limited discoverable flags.
982 */ 1003 */
983 if (hdev->adv_instance.flags & MGMT_ADV_FLAG_DISCOV) 1004 if (instance_flags & MGMT_ADV_FLAG_DISCOV)
984 flags |= LE_AD_GENERAL; 1005 flags |= LE_AD_GENERAL;
985 1006
986 if (hdev->adv_instance.flags & MGMT_ADV_FLAG_LIMITED_DISCOV) 1007 if (instance_flags & MGMT_ADV_FLAG_LIMITED_DISCOV)
987 flags |= LE_AD_LIMITED; 1008 flags |= LE_AD_LIMITED;
988 1009
989 if (flags || (hdev->adv_instance.flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) { 1010 if (flags || (instance_flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) {
990 /* If a discovery flag wasn't provided, simply use the global 1011 /* If a discovery flag wasn't provided, simply use the global
991 * settings. 1012 * settings.
992 */ 1013 */
@@ -996,16 +1017,22 @@ static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr)
996 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) 1017 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
997 flags |= LE_AD_NO_BREDR; 1018 flags |= LE_AD_NO_BREDR;
998 1019
999 ptr[0] = 0x02; 1020 /* If flags would still be empty, then there is no need to
1000 ptr[1] = EIR_FLAGS; 1021 * include the "Flags" AD field".
1001 ptr[2] = flags; 1022 */
1023 if (flags) {
1024 ptr[0] = 0x02;
1025 ptr[1] = EIR_FLAGS;
1026 ptr[2] = flags;
1002 1027
1003 ad_len += 3; 1028 ad_len += 3;
1004 ptr += 3; 1029 ptr += 3;
1030 }
1005 } 1031 }
1006 1032
1033 /* Provide Tx Power only if we can provide a valid value for it */
1007 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID && 1034 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID &&
1008 (hdev->adv_instance.flags & MGMT_ADV_FLAG_TX_POWER)) { 1035 (instance_flags & MGMT_ADV_FLAG_TX_POWER)) {
1009 ptr[0] = 0x02; 1036 ptr[0] = 0x02;
1010 ptr[1] = EIR_TX_POWER; 1037 ptr[1] = EIR_TX_POWER;
1011 ptr[2] = (u8)hdev->adv_tx_power; 1038 ptr[2] = (u8)hdev->adv_tx_power;
@@ -1014,9 +1041,11 @@ static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr)
1014 ptr += 3; 1041 ptr += 3;
1015 } 1042 }
1016 1043
1017 memcpy(ptr, hdev->adv_instance.adv_data, 1044 if (instance) {
1018 hdev->adv_instance.adv_data_len); 1045 memcpy(ptr, hdev->adv_instance.adv_data,
1019 ad_len += hdev->adv_instance.adv_data_len; 1046 hdev->adv_instance.adv_data_len);
1047 ad_len += hdev->adv_instance.adv_data_len;
1048 }
1020 1049
1021 return ad_len; 1050 return ad_len;
1022} 1051}
@@ -1032,10 +1061,7 @@ static void update_adv_data_for_instance(struct hci_request *req, u8 instance)
1032 1061
1033 memset(&cp, 0, sizeof(cp)); 1062 memset(&cp, 0, sizeof(cp));
1034 1063
1035 if (instance) 1064 len = create_instance_adv_data(hdev, instance, cp.data);
1036 len = create_instance_adv_data(hdev, cp.data);
1037 else
1038 len = create_default_adv_data(hdev, cp.data);
1039 1065
1040 /* There's nothing to do if the data hasn't changed */ 1066 /* There's nothing to do if the data hasn't changed */
1041 if (hdev->adv_data_len == len && 1067 if (hdev->adv_data_len == len &&
@@ -1050,59 +1076,6 @@ static void update_adv_data_for_instance(struct hci_request *req, u8 instance)
1050 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); 1076 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
1051} 1077}
1052 1078
1053static u8 get_current_adv_instance(struct hci_dev *hdev)
1054{
1055 /* The "Set Advertising" setting supersedes the "Add Advertising"
1056 * setting. Here we set the advertising data based on which
1057 * setting was set. When neither apply, default to the global settings,
1058 * represented by instance "0".
1059 */
1060 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
1061 !hci_dev_test_flag(hdev, HCI_ADVERTISING))
1062 return 0x01;
1063
1064 return 0x00;
1065}
1066
1067static bool get_connectable(struct hci_dev *hdev)
1068{
1069 struct mgmt_pending_cmd *cmd;
1070
1071 /* If there's a pending mgmt command the flag will not yet have
1072 * it's final value, so check for this first.
1073 */
1074 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1075 if (cmd) {
1076 struct mgmt_mode *cp = cmd->param;
1077
1078 return cp->val;
1079 }
1080
1081 return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
1082}
1083
1084static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
1085{
1086 u32 flags;
1087
1088 if (instance > 0x01)
1089 return 0;
1090
1091 if (instance == 1)
1092 return hdev->adv_instance.flags;
1093
1094 flags = 0;
1095
1096 /* For instance 0, assemble the flags from global settings */
1097 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE) ||
1098 get_connectable(hdev))
1099 flags |= MGMT_ADV_FLAG_CONNECTABLE;
1100
1101 /* TODO: Add the rest of the flags */
1102
1103 return flags;
1104}
1105
1106static void update_adv_data(struct hci_request *req) 1079static void update_adv_data(struct hci_request *req)
1107{ 1080{
1108 struct hci_dev *hdev = req->hdev; 1081 struct hci_dev *hdev = req->hdev;