aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/bluetooth/mgmt.c80
1 files changed, 69 insertions, 11 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 796db5849795..bd91ee5f130c 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -599,12 +599,35 @@ static void update_scan_rsp_data(struct hci_request *req)
599 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp); 599 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
600} 600}
601 601
602static u8 get_adv_discov_flags(struct hci_dev *hdev)
603{
604 struct pending_cmd *cmd;
605
606 /* If there's a pending mgmt command the flags will not yet have
607 * their final values, so check for this first.
608 */
609 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
610 if (cmd) {
611 struct mgmt_mode *cp = cmd->param;
612 if (cp->val == 0x01)
613 return LE_AD_GENERAL;
614 else if (cp->val == 0x02)
615 return LE_AD_LIMITED;
616 } else {
617 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
618 return LE_AD_LIMITED;
619 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
620 return LE_AD_GENERAL;
621 }
622
623 return 0;
624}
625
602static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr) 626static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
603{ 627{
604 u8 ad_len = 0, flags = 0; 628 u8 ad_len = 0, flags = 0;
605 629
606 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) 630 flags |= get_adv_discov_flags(hdev);
607 flags |= LE_AD_GENERAL;
608 631
609 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { 632 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
610 if (lmp_le_br_capable(hdev)) 633 if (lmp_le_br_capable(hdev))
@@ -1120,15 +1143,15 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
1120 struct pending_cmd *cmd; 1143 struct pending_cmd *cmd;
1121 struct hci_request req; 1144 struct hci_request req;
1122 u16 timeout; 1145 u16 timeout;
1123 u8 scan, status; 1146 u8 scan;
1124 int err; 1147 int err;
1125 1148
1126 BT_DBG("request for %s", hdev->name); 1149 BT_DBG("request for %s", hdev->name);
1127 1150
1128 status = mgmt_bredr_support(hdev); 1151 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1129 if (status) 1152 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1130 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, 1153 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1131 status); 1154 MGMT_STATUS_REJECTED);
1132 1155
1133 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02) 1156 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
1134 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, 1157 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
@@ -1228,6 +1251,12 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
1228 1251
1229 hci_req_init(&req, hdev); 1252 hci_req_init(&req, hdev);
1230 1253
1254 /* The procedure for LE-only controllers is much simpler - just
1255 * update the advertising data.
1256 */
1257 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1258 goto update_ad;
1259
1231 scan = SCAN_PAGE; 1260 scan = SCAN_PAGE;
1232 1261
1233 if (cp->val) { 1262 if (cp->val) {
@@ -1260,6 +1289,9 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
1260 1289
1261 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan); 1290 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
1262 1291
1292update_ad:
1293 update_adv_data(&req);
1294
1263 err = hci_req_run(&req, set_discoverable_complete); 1295 err = hci_req_run(&req, set_discoverable_complete);
1264 if (err < 0) 1296 if (err < 0)
1265 mgmt_pending_remove(cmd); 1297 mgmt_pending_remove(cmd);
@@ -1451,8 +1483,17 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
1451 1483
1452 hci_req_init(&req, hdev); 1484 hci_req_init(&req, hdev);
1453 1485
1454 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) && 1486 /* If BR/EDR is not enabled and we disable advertising as a
1455 cp->val != test_bit(HCI_PSCAN, &hdev->flags)) { 1487 * by-product of disabling connectable, we need to update the
1488 * advertising flags.
1489 */
1490 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1491 if (!cp->val) {
1492 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1493 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1494 }
1495 update_adv_data(&req);
1496 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
1456 if (cp->val) { 1497 if (cp->val) {
1457 scan = SCAN_PAGE; 1498 scan = SCAN_PAGE;
1458 } else { 1499 } else {
@@ -4348,6 +4389,7 @@ void mgmt_discoverable_timeout(struct hci_dev *hdev)
4348 * safe to unconditionally clear the flag. 4389 * safe to unconditionally clear the flag.
4349 */ 4390 */
4350 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); 4391 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
4392 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4351 4393
4352 hci_req_init(&req, hdev); 4394 hci_req_init(&req, hdev);
4353 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { 4395 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
@@ -4356,10 +4398,13 @@ void mgmt_discoverable_timeout(struct hci_dev *hdev)
4356 sizeof(scan), &scan); 4398 sizeof(scan), &scan);
4357 } 4399 }
4358 update_class(&req); 4400 update_class(&req);
4401 update_adv_data(&req);
4359 hci_req_run(&req, NULL); 4402 hci_req_run(&req, NULL);
4360 4403
4361 hdev->discov_timeout = 0; 4404 hdev->discov_timeout = 0;
4362 4405
4406 new_settings(hdev, NULL);
4407
4363 hci_dev_unlock(hdev); 4408 hci_dev_unlock(hdev);
4364} 4409}
4365 4410
@@ -4374,13 +4419,26 @@ void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
4374 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev)) 4419 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
4375 return; 4420 return;
4376 4421
4377 if (discoverable) 4422 if (discoverable) {
4378 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags); 4423 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4379 else 4424 } else {
4425 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
4380 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); 4426 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4427 }
4428
4429 if (changed) {
4430 struct hci_request req;
4431
4432 /* In case this change in discoverable was triggered by
4433 * a disabling of connectable there could be a need to
4434 * update the advertising flags.
4435 */
4436 hci_req_init(&req, hdev);
4437 update_adv_data(&req);
4438 hci_req_run(&req, NULL);
4381 4439
4382 if (changed)
4383 new_settings(hdev, NULL); 4440 new_settings(hdev, NULL);
4441 }
4384} 4442}
4385 4443
4386void mgmt_connectable(struct hci_dev *hdev, u8 connectable) 4444void mgmt_connectable(struct hci_dev *hdev, u8 connectable)