aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorArman Uguray <armansito@chromium.org>2015-03-25 21:53:40 -0400
committerMarcel Holtmann <marcel@holtmann.org>2015-03-25 22:30:28 -0400
commite7a685d316e7d4b64cd3b2811687b0270d590386 (patch)
tree132a7990c834e6d13951b960848d31942e9109a8 /net/bluetooth
parent495099962138732c28449d07f3b1988836659851 (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.c87
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
1016static void update_adv_data(struct hci_request *req) 1016static 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
1030static 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
1047static 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
1069static 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
1162static 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
1178static void disable_advertising(struct hci_request *req) 1204static 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