aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2013-10-15 12:13:39 -0400
committerJohan Hedberg <johan.hedberg@intel.com>2013-10-15 14:22:32 -0400
commit310a3d4854d71c0a565c9f7705749e78f6113c4c (patch)
treeb50981121ce0579309100e18cfa6394125b2f249 /net
parent3d5053127fc51b11f10a2cc3ad638736f2fa814c (diff)
Bluetooth: Add support for entering limited discoverable mode
The limited discoverable mode should be used when a device is only discoverable for a certain amount of time and after that it returns back into being non-discoverable. This adds another option to the set discoverable management command to clearly distinguish limited discoverable from general discoverable mode. While the general discoverable mode can be set with a specific timeout or as permanent setting, the limited discoverable mode requires a timeout. The timeout is flexible and the kernel will not enforce any specific limitations. That GAP part of this is required by userspace to enforce according to the Bluetooth core specification. Devices in limited discoverable mode can still be found by the general discovery procedure. It is mandatory that a device sets both GIAC and LIAC when entering limited discoverable mode. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/hci_core.c8
-rw-r--r--net/bluetooth/mgmt.c67
2 files changed, 65 insertions, 10 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index a49ca4869621..7a3d17990b43 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1282,6 +1282,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
1282 cancel_delayed_work(&hdev->discov_off); 1282 cancel_delayed_work(&hdev->discov_off);
1283 hdev->discov_timeout = 0; 1283 hdev->discov_timeout = 0;
1284 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); 1284 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1285 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1285 } 1286 }
1286 1287
1287 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) 1288 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
@@ -1717,6 +1718,13 @@ static void hci_discov_off(struct work_struct *work)
1717 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan); 1718 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
1718 hci_req_run(&req, NULL); 1719 hci_req_run(&req, NULL);
1719 1720
1721 /* When discoverable timeout triggers, then just make sure
1722 * the limited discoverable flag is cleared. Even in the case
1723 * of a timeout triggered from general discoverable, it is
1724 * safe to unconditionally clear the flag.
1725 */
1726 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1727
1720 hdev->discov_timeout = 0; 1728 hdev->discov_timeout = 0;
1721 1729
1722 hci_dev_unlock(hdev); 1730 hci_dev_unlock(hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 1d608ca0b0ee..c70094014d46 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1039,6 +1039,7 @@ static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1039 if (status) { 1039 if (status) {
1040 u8 mgmt_err = mgmt_status(status); 1040 u8 mgmt_err = mgmt_status(status);
1041 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); 1041 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1042 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1042 goto remove_cmd; 1043 goto remove_cmd;
1043 } 1044 }
1044 1045
@@ -1094,12 +1095,17 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
1094 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, 1095 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1095 status); 1096 status);
1096 1097
1097 if (cp->val != 0x00 && cp->val != 0x01) 1098 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
1098 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, 1099 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1099 MGMT_STATUS_INVALID_PARAMS); 1100 MGMT_STATUS_INVALID_PARAMS);
1100 1101
1101 timeout = __le16_to_cpu(cp->timeout); 1102 timeout = __le16_to_cpu(cp->timeout);
1102 if (!cp->val && timeout > 0) 1103
1104 /* Disabling discoverable requires that no timeout is set,
1105 * and enabling limited discoverable requires a timeout.
1106 */
1107 if ((cp->val == 0x00 && timeout > 0) ||
1108 (cp->val == 0x02 && timeout == 0))
1103 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, 1109 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1104 MGMT_STATUS_INVALID_PARAMS); 1110 MGMT_STATUS_INVALID_PARAMS);
1105 1111
@@ -1127,6 +1133,10 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
1127 if (!hdev_is_powered(hdev)) { 1133 if (!hdev_is_powered(hdev)) {
1128 bool changed = false; 1134 bool changed = false;
1129 1135
1136 /* Setting limited discoverable when powered off is
1137 * not a valid operation since it requires a timeout
1138 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1139 */
1130 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) { 1140 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1131 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags); 1141 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1132 changed = true; 1142 changed = true;
@@ -1142,7 +1152,13 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
1142 goto failed; 1152 goto failed;
1143 } 1153 }
1144 1154
1145 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) { 1155 /* If the current mode is the same, then just update the timeout
1156 * value with the new value. And if only the timeout gets updated,
1157 * then no need for any HCI transactions.
1158 */
1159 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1160 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1161 &hdev->dev_flags)) {
1146 cancel_delayed_work(&hdev->discov_off); 1162 cancel_delayed_work(&hdev->discov_off);
1147 hdev->discov_timeout = timeout; 1163 hdev->discov_timeout = timeout;
1148 1164
@@ -1162,24 +1178,55 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
1162 goto failed; 1178 goto failed;
1163 } 1179 }
1164 1180
1181 /* Cancel any potential discoverable timeout that might be
1182 * still active and store new timeout value. The arming of
1183 * the timeout happens in the complete handler.
1184 */
1185 cancel_delayed_work(&hdev->discov_off);
1186 hdev->discov_timeout = timeout;
1187
1165 hci_req_init(&req, hdev); 1188 hci_req_init(&req, hdev);
1166 1189
1167 scan = SCAN_PAGE; 1190 scan = SCAN_PAGE;
1168 1191
1169 if (cp->val) 1192 if (cp->val) {
1193 struct hci_cp_write_current_iac_lap hci_cp;
1194
1195 if (cp->val == 0x02) {
1196 /* Limited discoverable mode */
1197 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1198
1199 hci_cp.num_iac = 2;
1200 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1201 hci_cp.iac_lap[1] = 0x8b;
1202 hci_cp.iac_lap[2] = 0x9e;
1203 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1204 hci_cp.iac_lap[4] = 0x8b;
1205 hci_cp.iac_lap[5] = 0x9e;
1206 } else {
1207 /* General discoverable mode */
1208 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1209
1210 hci_cp.num_iac = 1;
1211 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1212 hci_cp.iac_lap[1] = 0x8b;
1213 hci_cp.iac_lap[2] = 0x9e;
1214 }
1215
1216 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1217 (hci_cp.num_iac * 3) + 1, &hci_cp);
1218
1170 scan |= SCAN_INQUIRY; 1219 scan |= SCAN_INQUIRY;
1171 else 1220 } else {
1172 cancel_delayed_work(&hdev->discov_off); 1221 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1222 }
1173 1223
1174 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); 1224 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
1175 1225
1176 err = hci_req_run(&req, set_discoverable_complete); 1226 err = hci_req_run(&req, set_discoverable_complete);
1177 if (err < 0) 1227 if (err < 0)
1178 mgmt_pending_remove(cmd); 1228 mgmt_pending_remove(cmd);
1179 1229
1180 if (cp->val)
1181 hdev->discov_timeout = timeout;
1182
1183failed: 1230failed:
1184 hci_dev_unlock(hdev); 1231 hci_dev_unlock(hdev);
1185 return err; 1232 return err;