diff options
author | Arman Uguray <armansito@chromium.org> | 2015-03-25 21:53:40 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2015-03-25 22:30:28 -0400 |
commit | e7a685d316e7d4b64cd3b2811687b0270d590386 (patch) | |
tree | 132a7990c834e6d13951b960848d31942e9109a8 /net/bluetooth | |
parent | 495099962138732c28449d07f3b1988836659851 (diff) |
Bluetooth: Support the "connectable mode" adv flag
This patch adds support for the "connectable mode" flag of the
Add Advertising command.
Signed-off-by: Arman Uguray <armansito@chromium.org>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/mgmt.c | 87 |
1 files changed, 56 insertions, 31 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index f95937c47b9e..672ff5b66c21 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -1013,11 +1013,8 @@ static void update_adv_data_for_instance(struct hci_request *req, u8 instance) | |||
1013 | hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); | 1013 | hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); |
1014 | } | 1014 | } |
1015 | 1015 | ||
1016 | static void update_adv_data(struct hci_request *req) | 1016 | static u8 get_current_adv_instance(struct hci_dev *hdev) |
1017 | { | 1017 | { |
1018 | struct hci_dev *hdev = req->hdev; | ||
1019 | u8 instance; | ||
1020 | |||
1021 | /* The "Set Advertising" setting supersedes the "Add Advertising" | 1018 | /* The "Set Advertising" setting supersedes the "Add Advertising" |
1022 | * setting. Here we set the advertising data based on which | 1019 | * setting. Here we set the advertising data based on which |
1023 | * setting was set. When neither apply, default to the global settings, | 1020 | * setting was set. When neither apply, default to the global settings, |
@@ -1025,9 +1022,54 @@ static void update_adv_data(struct hci_request *req) | |||
1025 | */ | 1022 | */ |
1026 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) && | 1023 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) && |
1027 | !hci_dev_test_flag(hdev, HCI_ADVERTISING)) | 1024 | !hci_dev_test_flag(hdev, HCI_ADVERTISING)) |
1028 | instance = 0x01; | 1025 | return 0x01; |
1029 | else | 1026 | |
1030 | instance = 0x00; | 1027 | return 0x00; |
1028 | } | ||
1029 | |||
1030 | static bool get_connectable(struct hci_dev *hdev) | ||
1031 | { | ||
1032 | struct mgmt_pending_cmd *cmd; | ||
1033 | |||
1034 | /* If there's a pending mgmt command the flag will not yet have | ||
1035 | * it's final value, so check for this first. | ||
1036 | */ | ||
1037 | cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev); | ||
1038 | if (cmd) { | ||
1039 | struct mgmt_mode *cp = cmd->param; | ||
1040 | |||
1041 | return cp->val; | ||
1042 | } | ||
1043 | |||
1044 | return hci_dev_test_flag(hdev, HCI_CONNECTABLE); | ||
1045 | } | ||
1046 | |||
1047 | static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance) | ||
1048 | { | ||
1049 | u32 flags; | ||
1050 | |||
1051 | if (instance > 0x01) | ||
1052 | return 0; | ||
1053 | |||
1054 | if (instance == 1) | ||
1055 | return hdev->adv_instance.flags; | ||
1056 | |||
1057 | flags = 0; | ||
1058 | |||
1059 | /* For instance 0, assemble the flags from global settings */ | ||
1060 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE) || | ||
1061 | get_connectable(hdev)) | ||
1062 | flags |= MGMT_ADV_FLAG_CONNECTABLE; | ||
1063 | |||
1064 | /* TODO: Add the rest of the flags */ | ||
1065 | |||
1066 | return flags; | ||
1067 | } | ||
1068 | |||
1069 | static void update_adv_data(struct hci_request *req) | ||
1070 | { | ||
1071 | struct hci_dev *hdev = req->hdev; | ||
1072 | u8 instance = get_current_adv_instance(hdev); | ||
1031 | 1073 | ||
1032 | update_adv_data_for_instance(req, instance); | 1074 | update_adv_data_for_instance(req, instance); |
1033 | } | 1075 | } |
@@ -1159,22 +1201,6 @@ static void update_class(struct hci_request *req) | |||
1159 | hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); | 1201 | hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); |
1160 | } | 1202 | } |
1161 | 1203 | ||
1162 | static bool get_connectable(struct hci_dev *hdev) | ||
1163 | { | ||
1164 | struct mgmt_pending_cmd *cmd; | ||
1165 | |||
1166 | /* If there's a pending mgmt command the flag will not yet have | ||
1167 | * it's final value, so check for this first. | ||
1168 | */ | ||
1169 | cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev); | ||
1170 | if (cmd) { | ||
1171 | struct mgmt_mode *cp = cmd->param; | ||
1172 | return cp->val; | ||
1173 | } | ||
1174 | |||
1175 | return hci_dev_test_flag(hdev, HCI_CONNECTABLE); | ||
1176 | } | ||
1177 | |||
1178 | static void disable_advertising(struct hci_request *req) | 1204 | static void disable_advertising(struct hci_request *req) |
1179 | { | 1205 | { |
1180 | u8 enable = 0x00; | 1206 | u8 enable = 0x00; |
@@ -1188,6 +1214,8 @@ static void enable_advertising(struct hci_request *req) | |||
1188 | struct hci_cp_le_set_adv_param cp; | 1214 | struct hci_cp_le_set_adv_param cp; |
1189 | u8 own_addr_type, enable = 0x01; | 1215 | u8 own_addr_type, enable = 0x01; |
1190 | bool connectable; | 1216 | bool connectable; |
1217 | u8 instance; | ||
1218 | u32 flags; | ||
1191 | 1219 | ||
1192 | if (hci_conn_num(hdev, LE_LINK) > 0) | 1220 | if (hci_conn_num(hdev, LE_LINK) > 0) |
1193 | return; | 1221 | return; |
@@ -1202,10 +1230,9 @@ static void enable_advertising(struct hci_request *req) | |||
1202 | */ | 1230 | */ |
1203 | hci_dev_clear_flag(hdev, HCI_LE_ADV); | 1231 | hci_dev_clear_flag(hdev, HCI_LE_ADV); |
1204 | 1232 | ||
1205 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) | 1233 | instance = get_current_adv_instance(hdev); |
1206 | connectable = true; | 1234 | flags = get_adv_instance_flags(hdev, instance); |
1207 | else | 1235 | connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE); |
1208 | connectable = get_connectable(hdev); | ||
1209 | 1236 | ||
1210 | /* Set require_privacy to true only when non-connectable | 1237 | /* Set require_privacy to true only when non-connectable |
1211 | * advertising is used. In that case it is fine to use a | 1238 | * advertising is used. In that case it is fine to use a |
@@ -6623,10 +6650,8 @@ static int add_advertising(struct sock *sk, struct hci_dev *hdev, | |||
6623 | flags = __le32_to_cpu(cp->flags); | 6650 | flags = __le32_to_cpu(cp->flags); |
6624 | timeout = __le16_to_cpu(cp->timeout); | 6651 | timeout = __le16_to_cpu(cp->timeout); |
6625 | 6652 | ||
6626 | /* The current implementation only supports adding one instance and | 6653 | /* The current implementation only supports adding one instance */ |
6627 | * doesn't support flags. | 6654 | if (cp->instance != 0x01) |
6628 | */ | ||
6629 | if (cp->instance != 0x01 || flags) | ||
6630 | return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING, | 6655 | return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING, |
6631 | MGMT_STATUS_INVALID_PARAMS); | 6656 | MGMT_STATUS_INVALID_PARAMS); |
6632 | 6657 | ||