diff options
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r-- | net/bluetooth/mgmt.c | 680 |
1 files changed, 468 insertions, 212 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 39395c7144aa..03e7e732215f 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -384,7 +384,8 @@ static u32 get_supported_settings(struct hci_dev *hdev) | |||
384 | 384 | ||
385 | if (lmp_bredr_capable(hdev)) { | 385 | if (lmp_bredr_capable(hdev)) { |
386 | settings |= MGMT_SETTING_CONNECTABLE; | 386 | settings |= MGMT_SETTING_CONNECTABLE; |
387 | settings |= MGMT_SETTING_FAST_CONNECTABLE; | 387 | if (hdev->hci_ver >= BLUETOOTH_VER_1_2) |
388 | settings |= MGMT_SETTING_FAST_CONNECTABLE; | ||
388 | settings |= MGMT_SETTING_DISCOVERABLE; | 389 | settings |= MGMT_SETTING_DISCOVERABLE; |
389 | settings |= MGMT_SETTING_BREDR; | 390 | settings |= MGMT_SETTING_BREDR; |
390 | settings |= MGMT_SETTING_LINK_SECURITY; | 391 | settings |= MGMT_SETTING_LINK_SECURITY; |
@@ -409,6 +410,9 @@ static u32 get_current_settings(struct hci_dev *hdev) | |||
409 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | 410 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) |
410 | settings |= MGMT_SETTING_CONNECTABLE; | 411 | settings |= MGMT_SETTING_CONNECTABLE; |
411 | 412 | ||
413 | if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) | ||
414 | settings |= MGMT_SETTING_FAST_CONNECTABLE; | ||
415 | |||
412 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) | 416 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) |
413 | settings |= MGMT_SETTING_DISCOVERABLE; | 417 | settings |= MGMT_SETTING_DISCOVERABLE; |
414 | 418 | ||
@@ -591,32 +595,33 @@ static void create_eir(struct hci_dev *hdev, u8 *data) | |||
591 | ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); | 595 | ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); |
592 | } | 596 | } |
593 | 597 | ||
594 | static int update_eir(struct hci_dev *hdev) | 598 | static void update_eir(struct hci_request *req) |
595 | { | 599 | { |
600 | struct hci_dev *hdev = req->hdev; | ||
596 | struct hci_cp_write_eir cp; | 601 | struct hci_cp_write_eir cp; |
597 | 602 | ||
598 | if (!hdev_is_powered(hdev)) | 603 | if (!hdev_is_powered(hdev)) |
599 | return 0; | 604 | return; |
600 | 605 | ||
601 | if (!lmp_ext_inq_capable(hdev)) | 606 | if (!lmp_ext_inq_capable(hdev)) |
602 | return 0; | 607 | return; |
603 | 608 | ||
604 | if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) | 609 | if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) |
605 | return 0; | 610 | return; |
606 | 611 | ||
607 | if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) | 612 | if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) |
608 | return 0; | 613 | return; |
609 | 614 | ||
610 | memset(&cp, 0, sizeof(cp)); | 615 | memset(&cp, 0, sizeof(cp)); |
611 | 616 | ||
612 | create_eir(hdev, cp.data); | 617 | create_eir(hdev, cp.data); |
613 | 618 | ||
614 | if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0) | 619 | if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0) |
615 | return 0; | 620 | return; |
616 | 621 | ||
617 | memcpy(hdev->eir, cp.data, sizeof(cp.data)); | 622 | memcpy(hdev->eir, cp.data, sizeof(cp.data)); |
618 | 623 | ||
619 | return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); | 624 | hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp); |
620 | } | 625 | } |
621 | 626 | ||
622 | static u8 get_service_classes(struct hci_dev *hdev) | 627 | static u8 get_service_classes(struct hci_dev *hdev) |
@@ -630,47 +635,48 @@ static u8 get_service_classes(struct hci_dev *hdev) | |||
630 | return val; | 635 | return val; |
631 | } | 636 | } |
632 | 637 | ||
633 | static int update_class(struct hci_dev *hdev) | 638 | static void update_class(struct hci_request *req) |
634 | { | 639 | { |
640 | struct hci_dev *hdev = req->hdev; | ||
635 | u8 cod[3]; | 641 | u8 cod[3]; |
636 | int err; | ||
637 | 642 | ||
638 | BT_DBG("%s", hdev->name); | 643 | BT_DBG("%s", hdev->name); |
639 | 644 | ||
640 | if (!hdev_is_powered(hdev)) | 645 | if (!hdev_is_powered(hdev)) |
641 | return 0; | 646 | return; |
642 | 647 | ||
643 | if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) | 648 | if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) |
644 | return 0; | 649 | return; |
645 | 650 | ||
646 | cod[0] = hdev->minor_class; | 651 | cod[0] = hdev->minor_class; |
647 | cod[1] = hdev->major_class; | 652 | cod[1] = hdev->major_class; |
648 | cod[2] = get_service_classes(hdev); | 653 | cod[2] = get_service_classes(hdev); |
649 | 654 | ||
650 | if (memcmp(cod, hdev->dev_class, 3) == 0) | 655 | if (memcmp(cod, hdev->dev_class, 3) == 0) |
651 | return 0; | 656 | return; |
652 | |||
653 | err = hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); | ||
654 | if (err == 0) | ||
655 | set_bit(HCI_PENDING_CLASS, &hdev->dev_flags); | ||
656 | 657 | ||
657 | return err; | 658 | hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); |
658 | } | 659 | } |
659 | 660 | ||
660 | static void service_cache_off(struct work_struct *work) | 661 | static void service_cache_off(struct work_struct *work) |
661 | { | 662 | { |
662 | struct hci_dev *hdev = container_of(work, struct hci_dev, | 663 | struct hci_dev *hdev = container_of(work, struct hci_dev, |
663 | service_cache.work); | 664 | service_cache.work); |
665 | struct hci_request req; | ||
664 | 666 | ||
665 | if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) | 667 | if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) |
666 | return; | 668 | return; |
667 | 669 | ||
670 | hci_req_init(&req, hdev); | ||
671 | |||
668 | hci_dev_lock(hdev); | 672 | hci_dev_lock(hdev); |
669 | 673 | ||
670 | update_eir(hdev); | 674 | update_eir(&req); |
671 | update_class(hdev); | 675 | update_class(&req); |
672 | 676 | ||
673 | hci_dev_unlock(hdev); | 677 | hci_dev_unlock(hdev); |
678 | |||
679 | hci_req_run(&req, NULL); | ||
674 | } | 680 | } |
675 | 681 | ||
676 | static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev) | 682 | static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev) |
@@ -994,11 +1000,64 @@ failed: | |||
994 | return err; | 1000 | return err; |
995 | } | 1001 | } |
996 | 1002 | ||
1003 | static void write_fast_connectable(struct hci_request *req, bool enable) | ||
1004 | { | ||
1005 | struct hci_dev *hdev = req->hdev; | ||
1006 | struct hci_cp_write_page_scan_activity acp; | ||
1007 | u8 type; | ||
1008 | |||
1009 | if (hdev->hci_ver < BLUETOOTH_VER_1_2) | ||
1010 | return; | ||
1011 | |||
1012 | if (enable) { | ||
1013 | type = PAGE_SCAN_TYPE_INTERLACED; | ||
1014 | |||
1015 | /* 160 msec page scan interval */ | ||
1016 | acp.interval = __constant_cpu_to_le16(0x0100); | ||
1017 | } else { | ||
1018 | type = PAGE_SCAN_TYPE_STANDARD; /* default */ | ||
1019 | |||
1020 | /* default 1.28 sec page scan */ | ||
1021 | acp.interval = __constant_cpu_to_le16(0x0800); | ||
1022 | } | ||
1023 | |||
1024 | acp.window = __constant_cpu_to_le16(0x0012); | ||
1025 | |||
1026 | if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval || | ||
1027 | __cpu_to_le16(hdev->page_scan_window) != acp.window) | ||
1028 | hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, | ||
1029 | sizeof(acp), &acp); | ||
1030 | |||
1031 | if (hdev->page_scan_type != type) | ||
1032 | hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type); | ||
1033 | } | ||
1034 | |||
1035 | static void set_connectable_complete(struct hci_dev *hdev, u8 status) | ||
1036 | { | ||
1037 | struct pending_cmd *cmd; | ||
1038 | |||
1039 | BT_DBG("status 0x%02x", status); | ||
1040 | |||
1041 | hci_dev_lock(hdev); | ||
1042 | |||
1043 | cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev); | ||
1044 | if (!cmd) | ||
1045 | goto unlock; | ||
1046 | |||
1047 | send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev); | ||
1048 | |||
1049 | mgmt_pending_remove(cmd); | ||
1050 | |||
1051 | unlock: | ||
1052 | hci_dev_unlock(hdev); | ||
1053 | } | ||
1054 | |||
997 | static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | 1055 | static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, |
998 | u16 len) | 1056 | u16 len) |
999 | { | 1057 | { |
1000 | struct mgmt_mode *cp = data; | 1058 | struct mgmt_mode *cp = data; |
1001 | struct pending_cmd *cmd; | 1059 | struct pending_cmd *cmd; |
1060 | struct hci_request req; | ||
1002 | u8 scan; | 1061 | u8 scan; |
1003 | int err; | 1062 | int err; |
1004 | 1063 | ||
@@ -1065,7 +1124,20 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1065 | cancel_delayed_work(&hdev->discov_off); | 1124 | cancel_delayed_work(&hdev->discov_off); |
1066 | } | 1125 | } |
1067 | 1126 | ||
1068 | err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | 1127 | hci_req_init(&req, hdev); |
1128 | |||
1129 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | ||
1130 | |||
1131 | /* If we're going from non-connectable to connectable or | ||
1132 | * vice-versa when fast connectable is enabled ensure that fast | ||
1133 | * connectable gets disabled. write_fast_connectable won't do | ||
1134 | * anything if the page scan parameters are already what they | ||
1135 | * should be. | ||
1136 | */ | ||
1137 | if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) | ||
1138 | write_fast_connectable(&req, false); | ||
1139 | |||
1140 | err = hci_req_run(&req, set_connectable_complete); | ||
1069 | if (err < 0) | 1141 | if (err < 0) |
1070 | mgmt_pending_remove(cmd); | 1142 | mgmt_pending_remove(cmd); |
1071 | 1143 | ||
@@ -1332,6 +1404,29 @@ unlock: | |||
1332 | return err; | 1404 | return err; |
1333 | } | 1405 | } |
1334 | 1406 | ||
1407 | /* This is a helper function to test for pending mgmt commands that can | ||
1408 | * cause CoD or EIR HCI commands. We can only allow one such pending | ||
1409 | * mgmt command at a time since otherwise we cannot easily track what | ||
1410 | * the current values are, will be, and based on that calculate if a new | ||
1411 | * HCI command needs to be sent and if yes with what value. | ||
1412 | */ | ||
1413 | static bool pending_eir_or_class(struct hci_dev *hdev) | ||
1414 | { | ||
1415 | struct pending_cmd *cmd; | ||
1416 | |||
1417 | list_for_each_entry(cmd, &hdev->mgmt_pending, list) { | ||
1418 | switch (cmd->opcode) { | ||
1419 | case MGMT_OP_ADD_UUID: | ||
1420 | case MGMT_OP_REMOVE_UUID: | ||
1421 | case MGMT_OP_SET_DEV_CLASS: | ||
1422 | case MGMT_OP_SET_POWERED: | ||
1423 | return true; | ||
1424 | } | ||
1425 | } | ||
1426 | |||
1427 | return false; | ||
1428 | } | ||
1429 | |||
1335 | static const u8 bluetooth_base_uuid[] = { | 1430 | static const u8 bluetooth_base_uuid[] = { |
1336 | 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, | 1431 | 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, |
1337 | 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 1432 | 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -1351,10 +1446,37 @@ static u8 get_uuid_size(const u8 *uuid) | |||
1351 | return 16; | 1446 | return 16; |
1352 | } | 1447 | } |
1353 | 1448 | ||
1449 | static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status) | ||
1450 | { | ||
1451 | struct pending_cmd *cmd; | ||
1452 | |||
1453 | hci_dev_lock(hdev); | ||
1454 | |||
1455 | cmd = mgmt_pending_find(mgmt_op, hdev); | ||
1456 | if (!cmd) | ||
1457 | goto unlock; | ||
1458 | |||
1459 | cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status), | ||
1460 | hdev->dev_class, 3); | ||
1461 | |||
1462 | mgmt_pending_remove(cmd); | ||
1463 | |||
1464 | unlock: | ||
1465 | hci_dev_unlock(hdev); | ||
1466 | } | ||
1467 | |||
1468 | static void add_uuid_complete(struct hci_dev *hdev, u8 status) | ||
1469 | { | ||
1470 | BT_DBG("status 0x%02x", status); | ||
1471 | |||
1472 | mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status); | ||
1473 | } | ||
1474 | |||
1354 | static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | 1475 | static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) |
1355 | { | 1476 | { |
1356 | struct mgmt_cp_add_uuid *cp = data; | 1477 | struct mgmt_cp_add_uuid *cp = data; |
1357 | struct pending_cmd *cmd; | 1478 | struct pending_cmd *cmd; |
1479 | struct hci_request req; | ||
1358 | struct bt_uuid *uuid; | 1480 | struct bt_uuid *uuid; |
1359 | int err; | 1481 | int err; |
1360 | 1482 | ||
@@ -1362,7 +1484,7 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1362 | 1484 | ||
1363 | hci_dev_lock(hdev); | 1485 | hci_dev_lock(hdev); |
1364 | 1486 | ||
1365 | if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) { | 1487 | if (pending_eir_or_class(hdev)) { |
1366 | err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID, | 1488 | err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID, |
1367 | MGMT_STATUS_BUSY); | 1489 | MGMT_STATUS_BUSY); |
1368 | goto failed; | 1490 | goto failed; |
@@ -1380,23 +1502,28 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1380 | 1502 | ||
1381 | list_add_tail(&uuid->list, &hdev->uuids); | 1503 | list_add_tail(&uuid->list, &hdev->uuids); |
1382 | 1504 | ||
1383 | err = update_class(hdev); | 1505 | hci_req_init(&req, hdev); |
1384 | if (err < 0) | ||
1385 | goto failed; | ||
1386 | 1506 | ||
1387 | err = update_eir(hdev); | 1507 | update_class(&req); |
1388 | if (err < 0) | 1508 | update_eir(&req); |
1389 | goto failed; | 1509 | |
1510 | err = hci_req_run(&req, add_uuid_complete); | ||
1511 | if (err < 0) { | ||
1512 | if (err != -ENODATA) | ||
1513 | goto failed; | ||
1390 | 1514 | ||
1391 | if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) { | ||
1392 | err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0, | 1515 | err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0, |
1393 | hdev->dev_class, 3); | 1516 | hdev->dev_class, 3); |
1394 | goto failed; | 1517 | goto failed; |
1395 | } | 1518 | } |
1396 | 1519 | ||
1397 | cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len); | 1520 | cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len); |
1398 | if (!cmd) | 1521 | if (!cmd) { |
1399 | err = -ENOMEM; | 1522 | err = -ENOMEM; |
1523 | goto failed; | ||
1524 | } | ||
1525 | |||
1526 | err = 0; | ||
1400 | 1527 | ||
1401 | failed: | 1528 | failed: |
1402 | hci_dev_unlock(hdev); | 1529 | hci_dev_unlock(hdev); |
@@ -1417,6 +1544,13 @@ static bool enable_service_cache(struct hci_dev *hdev) | |||
1417 | return false; | 1544 | return false; |
1418 | } | 1545 | } |
1419 | 1546 | ||
1547 | static void remove_uuid_complete(struct hci_dev *hdev, u8 status) | ||
1548 | { | ||
1549 | BT_DBG("status 0x%02x", status); | ||
1550 | |||
1551 | mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status); | ||
1552 | } | ||
1553 | |||
1420 | static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, | 1554 | static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, |
1421 | u16 len) | 1555 | u16 len) |
1422 | { | 1556 | { |
@@ -1424,13 +1558,14 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1424 | struct pending_cmd *cmd; | 1558 | struct pending_cmd *cmd; |
1425 | struct bt_uuid *match, *tmp; | 1559 | struct bt_uuid *match, *tmp; |
1426 | u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | 1560 | u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
1561 | struct hci_request req; | ||
1427 | int err, found; | 1562 | int err, found; |
1428 | 1563 | ||
1429 | BT_DBG("request for %s", hdev->name); | 1564 | BT_DBG("request for %s", hdev->name); |
1430 | 1565 | ||
1431 | hci_dev_lock(hdev); | 1566 | hci_dev_lock(hdev); |
1432 | 1567 | ||
1433 | if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) { | 1568 | if (pending_eir_or_class(hdev)) { |
1434 | err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID, | 1569 | err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID, |
1435 | MGMT_STATUS_BUSY); | 1570 | MGMT_STATUS_BUSY); |
1436 | goto unlock; | 1571 | goto unlock; |
@@ -1466,34 +1601,47 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1466 | } | 1601 | } |
1467 | 1602 | ||
1468 | update_class: | 1603 | update_class: |
1469 | err = update_class(hdev); | 1604 | hci_req_init(&req, hdev); |
1470 | if (err < 0) | ||
1471 | goto unlock; | ||
1472 | 1605 | ||
1473 | err = update_eir(hdev); | 1606 | update_class(&req); |
1474 | if (err < 0) | 1607 | update_eir(&req); |
1475 | goto unlock; | 1608 | |
1609 | err = hci_req_run(&req, remove_uuid_complete); | ||
1610 | if (err < 0) { | ||
1611 | if (err != -ENODATA) | ||
1612 | goto unlock; | ||
1476 | 1613 | ||
1477 | if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) { | ||
1478 | err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0, | 1614 | err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0, |
1479 | hdev->dev_class, 3); | 1615 | hdev->dev_class, 3); |
1480 | goto unlock; | 1616 | goto unlock; |
1481 | } | 1617 | } |
1482 | 1618 | ||
1483 | cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len); | 1619 | cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len); |
1484 | if (!cmd) | 1620 | if (!cmd) { |
1485 | err = -ENOMEM; | 1621 | err = -ENOMEM; |
1622 | goto unlock; | ||
1623 | } | ||
1624 | |||
1625 | err = 0; | ||
1486 | 1626 | ||
1487 | unlock: | 1627 | unlock: |
1488 | hci_dev_unlock(hdev); | 1628 | hci_dev_unlock(hdev); |
1489 | return err; | 1629 | return err; |
1490 | } | 1630 | } |
1491 | 1631 | ||
1632 | static void set_class_complete(struct hci_dev *hdev, u8 status) | ||
1633 | { | ||
1634 | BT_DBG("status 0x%02x", status); | ||
1635 | |||
1636 | mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status); | ||
1637 | } | ||
1638 | |||
1492 | static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, | 1639 | static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, |
1493 | u16 len) | 1640 | u16 len) |
1494 | { | 1641 | { |
1495 | struct mgmt_cp_set_dev_class *cp = data; | 1642 | struct mgmt_cp_set_dev_class *cp = data; |
1496 | struct pending_cmd *cmd; | 1643 | struct pending_cmd *cmd; |
1644 | struct hci_request req; | ||
1497 | int err; | 1645 | int err; |
1498 | 1646 | ||
1499 | BT_DBG("request for %s", hdev->name); | 1647 | BT_DBG("request for %s", hdev->name); |
@@ -1502,15 +1650,19 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1502 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, | 1650 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, |
1503 | MGMT_STATUS_NOT_SUPPORTED); | 1651 | MGMT_STATUS_NOT_SUPPORTED); |
1504 | 1652 | ||
1505 | if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) | 1653 | hci_dev_lock(hdev); |
1506 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, | ||
1507 | MGMT_STATUS_BUSY); | ||
1508 | 1654 | ||
1509 | if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) | 1655 | if (pending_eir_or_class(hdev)) { |
1510 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, | 1656 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, |
1511 | MGMT_STATUS_INVALID_PARAMS); | 1657 | MGMT_STATUS_BUSY); |
1658 | goto unlock; | ||
1659 | } | ||
1512 | 1660 | ||
1513 | hci_dev_lock(hdev); | 1661 | if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) { |
1662 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, | ||
1663 | MGMT_STATUS_INVALID_PARAMS); | ||
1664 | goto unlock; | ||
1665 | } | ||
1514 | 1666 | ||
1515 | hdev->major_class = cp->major; | 1667 | hdev->major_class = cp->major; |
1516 | hdev->minor_class = cp->minor; | 1668 | hdev->minor_class = cp->minor; |
@@ -1521,26 +1673,34 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1521 | goto unlock; | 1673 | goto unlock; |
1522 | } | 1674 | } |
1523 | 1675 | ||
1676 | hci_req_init(&req, hdev); | ||
1677 | |||
1524 | if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) { | 1678 | if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) { |
1525 | hci_dev_unlock(hdev); | 1679 | hci_dev_unlock(hdev); |
1526 | cancel_delayed_work_sync(&hdev->service_cache); | 1680 | cancel_delayed_work_sync(&hdev->service_cache); |
1527 | hci_dev_lock(hdev); | 1681 | hci_dev_lock(hdev); |
1528 | update_eir(hdev); | 1682 | update_eir(&req); |
1529 | } | 1683 | } |
1530 | 1684 | ||
1531 | err = update_class(hdev); | 1685 | update_class(&req); |
1532 | if (err < 0) | 1686 | |
1533 | goto unlock; | 1687 | err = hci_req_run(&req, set_class_complete); |
1688 | if (err < 0) { | ||
1689 | if (err != -ENODATA) | ||
1690 | goto unlock; | ||
1534 | 1691 | ||
1535 | if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) { | ||
1536 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0, | 1692 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0, |
1537 | hdev->dev_class, 3); | 1693 | hdev->dev_class, 3); |
1538 | goto unlock; | 1694 | goto unlock; |
1539 | } | 1695 | } |
1540 | 1696 | ||
1541 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len); | 1697 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len); |
1542 | if (!cmd) | 1698 | if (!cmd) { |
1543 | err = -ENOMEM; | 1699 | err = -ENOMEM; |
1700 | goto unlock; | ||
1701 | } | ||
1702 | |||
1703 | err = 0; | ||
1544 | 1704 | ||
1545 | unlock: | 1705 | unlock: |
1546 | hci_dev_unlock(hdev); | 1706 | hci_dev_unlock(hdev); |
@@ -2140,7 +2300,7 @@ unlock: | |||
2140 | } | 2300 | } |
2141 | 2301 | ||
2142 | static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev, | 2302 | static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev, |
2143 | bdaddr_t *bdaddr, u8 type, u16 mgmt_op, | 2303 | struct mgmt_addr_info *addr, u16 mgmt_op, |
2144 | u16 hci_op, __le32 passkey) | 2304 | u16 hci_op, __le32 passkey) |
2145 | { | 2305 | { |
2146 | struct pending_cmd *cmd; | 2306 | struct pending_cmd *cmd; |
@@ -2150,37 +2310,41 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev, | |||
2150 | hci_dev_lock(hdev); | 2310 | hci_dev_lock(hdev); |
2151 | 2311 | ||
2152 | if (!hdev_is_powered(hdev)) { | 2312 | if (!hdev_is_powered(hdev)) { |
2153 | err = cmd_status(sk, hdev->id, mgmt_op, | 2313 | err = cmd_complete(sk, hdev->id, mgmt_op, |
2154 | MGMT_STATUS_NOT_POWERED); | 2314 | MGMT_STATUS_NOT_POWERED, addr, |
2315 | sizeof(*addr)); | ||
2155 | goto done; | 2316 | goto done; |
2156 | } | 2317 | } |
2157 | 2318 | ||
2158 | if (type == BDADDR_BREDR) | 2319 | if (addr->type == BDADDR_BREDR) |
2159 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr); | 2320 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr); |
2160 | else | 2321 | else |
2161 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr); | 2322 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr); |
2162 | 2323 | ||
2163 | if (!conn) { | 2324 | if (!conn) { |
2164 | err = cmd_status(sk, hdev->id, mgmt_op, | 2325 | err = cmd_complete(sk, hdev->id, mgmt_op, |
2165 | MGMT_STATUS_NOT_CONNECTED); | 2326 | MGMT_STATUS_NOT_CONNECTED, addr, |
2327 | sizeof(*addr)); | ||
2166 | goto done; | 2328 | goto done; |
2167 | } | 2329 | } |
2168 | 2330 | ||
2169 | if (type == BDADDR_LE_PUBLIC || type == BDADDR_LE_RANDOM) { | 2331 | if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) { |
2170 | /* Continue with pairing via SMP */ | 2332 | /* Continue with pairing via SMP */ |
2171 | err = smp_user_confirm_reply(conn, mgmt_op, passkey); | 2333 | err = smp_user_confirm_reply(conn, mgmt_op, passkey); |
2172 | 2334 | ||
2173 | if (!err) | 2335 | if (!err) |
2174 | err = cmd_status(sk, hdev->id, mgmt_op, | 2336 | err = cmd_complete(sk, hdev->id, mgmt_op, |
2175 | MGMT_STATUS_SUCCESS); | 2337 | MGMT_STATUS_SUCCESS, addr, |
2338 | sizeof(*addr)); | ||
2176 | else | 2339 | else |
2177 | err = cmd_status(sk, hdev->id, mgmt_op, | 2340 | err = cmd_complete(sk, hdev->id, mgmt_op, |
2178 | MGMT_STATUS_FAILED); | 2341 | MGMT_STATUS_FAILED, addr, |
2342 | sizeof(*addr)); | ||
2179 | 2343 | ||
2180 | goto done; | 2344 | goto done; |
2181 | } | 2345 | } |
2182 | 2346 | ||
2183 | cmd = mgmt_pending_add(sk, mgmt_op, hdev, bdaddr, sizeof(*bdaddr)); | 2347 | cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr)); |
2184 | if (!cmd) { | 2348 | if (!cmd) { |
2185 | err = -ENOMEM; | 2349 | err = -ENOMEM; |
2186 | goto done; | 2350 | goto done; |
@@ -2190,11 +2354,12 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev, | |||
2190 | if (hci_op == HCI_OP_USER_PASSKEY_REPLY) { | 2354 | if (hci_op == HCI_OP_USER_PASSKEY_REPLY) { |
2191 | struct hci_cp_user_passkey_reply cp; | 2355 | struct hci_cp_user_passkey_reply cp; |
2192 | 2356 | ||
2193 | bacpy(&cp.bdaddr, bdaddr); | 2357 | bacpy(&cp.bdaddr, &addr->bdaddr); |
2194 | cp.passkey = passkey; | 2358 | cp.passkey = passkey; |
2195 | err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp); | 2359 | err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp); |
2196 | } else | 2360 | } else |
2197 | err = hci_send_cmd(hdev, hci_op, sizeof(*bdaddr), bdaddr); | 2361 | err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr), |
2362 | &addr->bdaddr); | ||
2198 | 2363 | ||
2199 | if (err < 0) | 2364 | if (err < 0) |
2200 | mgmt_pending_remove(cmd); | 2365 | mgmt_pending_remove(cmd); |
@@ -2211,7 +2376,7 @@ static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev, | |||
2211 | 2376 | ||
2212 | BT_DBG(""); | 2377 | BT_DBG(""); |
2213 | 2378 | ||
2214 | return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type, | 2379 | return user_pairing_resp(sk, hdev, &cp->addr, |
2215 | MGMT_OP_PIN_CODE_NEG_REPLY, | 2380 | MGMT_OP_PIN_CODE_NEG_REPLY, |
2216 | HCI_OP_PIN_CODE_NEG_REPLY, 0); | 2381 | HCI_OP_PIN_CODE_NEG_REPLY, 0); |
2217 | } | 2382 | } |
@@ -2227,7 +2392,7 @@ static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2227 | return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY, | 2392 | return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY, |
2228 | MGMT_STATUS_INVALID_PARAMS); | 2393 | MGMT_STATUS_INVALID_PARAMS); |
2229 | 2394 | ||
2230 | return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type, | 2395 | return user_pairing_resp(sk, hdev, &cp->addr, |
2231 | MGMT_OP_USER_CONFIRM_REPLY, | 2396 | MGMT_OP_USER_CONFIRM_REPLY, |
2232 | HCI_OP_USER_CONFIRM_REPLY, 0); | 2397 | HCI_OP_USER_CONFIRM_REPLY, 0); |
2233 | } | 2398 | } |
@@ -2239,7 +2404,7 @@ static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev, | |||
2239 | 2404 | ||
2240 | BT_DBG(""); | 2405 | BT_DBG(""); |
2241 | 2406 | ||
2242 | return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type, | 2407 | return user_pairing_resp(sk, hdev, &cp->addr, |
2243 | MGMT_OP_USER_CONFIRM_NEG_REPLY, | 2408 | MGMT_OP_USER_CONFIRM_NEG_REPLY, |
2244 | HCI_OP_USER_CONFIRM_NEG_REPLY, 0); | 2409 | HCI_OP_USER_CONFIRM_NEG_REPLY, 0); |
2245 | } | 2410 | } |
@@ -2251,7 +2416,7 @@ static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2251 | 2416 | ||
2252 | BT_DBG(""); | 2417 | BT_DBG(""); |
2253 | 2418 | ||
2254 | return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type, | 2419 | return user_pairing_resp(sk, hdev, &cp->addr, |
2255 | MGMT_OP_USER_PASSKEY_REPLY, | 2420 | MGMT_OP_USER_PASSKEY_REPLY, |
2256 | HCI_OP_USER_PASSKEY_REPLY, cp->passkey); | 2421 | HCI_OP_USER_PASSKEY_REPLY, cp->passkey); |
2257 | } | 2422 | } |
@@ -2263,18 +2428,47 @@ static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev, | |||
2263 | 2428 | ||
2264 | BT_DBG(""); | 2429 | BT_DBG(""); |
2265 | 2430 | ||
2266 | return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type, | 2431 | return user_pairing_resp(sk, hdev, &cp->addr, |
2267 | MGMT_OP_USER_PASSKEY_NEG_REPLY, | 2432 | MGMT_OP_USER_PASSKEY_NEG_REPLY, |
2268 | HCI_OP_USER_PASSKEY_NEG_REPLY, 0); | 2433 | HCI_OP_USER_PASSKEY_NEG_REPLY, 0); |
2269 | } | 2434 | } |
2270 | 2435 | ||
2271 | static int update_name(struct hci_dev *hdev, const char *name) | 2436 | static void update_name(struct hci_request *req) |
2272 | { | 2437 | { |
2438 | struct hci_dev *hdev = req->hdev; | ||
2273 | struct hci_cp_write_local_name cp; | 2439 | struct hci_cp_write_local_name cp; |
2274 | 2440 | ||
2275 | memcpy(cp.name, name, sizeof(cp.name)); | 2441 | memcpy(cp.name, hdev->dev_name, sizeof(cp.name)); |
2442 | |||
2443 | hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp); | ||
2444 | } | ||
2445 | |||
2446 | static void set_name_complete(struct hci_dev *hdev, u8 status) | ||
2447 | { | ||
2448 | struct mgmt_cp_set_local_name *cp; | ||
2449 | struct pending_cmd *cmd; | ||
2450 | |||
2451 | BT_DBG("status 0x%02x", status); | ||
2452 | |||
2453 | hci_dev_lock(hdev); | ||
2454 | |||
2455 | cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev); | ||
2456 | if (!cmd) | ||
2457 | goto unlock; | ||
2458 | |||
2459 | cp = cmd->param; | ||
2276 | 2460 | ||
2277 | return hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp); | 2461 | if (status) |
2462 | cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, | ||
2463 | mgmt_status(status)); | ||
2464 | else | ||
2465 | cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0, | ||
2466 | cp, sizeof(*cp)); | ||
2467 | |||
2468 | mgmt_pending_remove(cmd); | ||
2469 | |||
2470 | unlock: | ||
2471 | hci_dev_unlock(hdev); | ||
2278 | } | 2472 | } |
2279 | 2473 | ||
2280 | static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, | 2474 | static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, |
@@ -2282,12 +2476,24 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2282 | { | 2476 | { |
2283 | struct mgmt_cp_set_local_name *cp = data; | 2477 | struct mgmt_cp_set_local_name *cp = data; |
2284 | struct pending_cmd *cmd; | 2478 | struct pending_cmd *cmd; |
2479 | struct hci_request req; | ||
2285 | int err; | 2480 | int err; |
2286 | 2481 | ||
2287 | BT_DBG(""); | 2482 | BT_DBG(""); |
2288 | 2483 | ||
2289 | hci_dev_lock(hdev); | 2484 | hci_dev_lock(hdev); |
2290 | 2485 | ||
2486 | /* If the old values are the same as the new ones just return a | ||
2487 | * direct command complete event. | ||
2488 | */ | ||
2489 | if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) && | ||
2490 | !memcmp(hdev->short_name, cp->short_name, | ||
2491 | sizeof(hdev->short_name))) { | ||
2492 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0, | ||
2493 | data, len); | ||
2494 | goto failed; | ||
2495 | } | ||
2496 | |||
2291 | memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name)); | 2497 | memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name)); |
2292 | 2498 | ||
2293 | if (!hdev_is_powered(hdev)) { | 2499 | if (!hdev_is_powered(hdev)) { |
@@ -2310,7 +2516,19 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2310 | goto failed; | 2516 | goto failed; |
2311 | } | 2517 | } |
2312 | 2518 | ||
2313 | err = update_name(hdev, cp->name); | 2519 | memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name)); |
2520 | |||
2521 | hci_req_init(&req, hdev); | ||
2522 | |||
2523 | if (lmp_bredr_capable(hdev)) { | ||
2524 | update_name(&req); | ||
2525 | update_eir(&req); | ||
2526 | } | ||
2527 | |||
2528 | if (lmp_le_capable(hdev)) | ||
2529 | hci_update_ad(&req); | ||
2530 | |||
2531 | err = hci_req_run(&req, set_name_complete); | ||
2314 | if (err < 0) | 2532 | if (err < 0) |
2315 | mgmt_pending_remove(cmd); | 2533 | mgmt_pending_remove(cmd); |
2316 | 2534 | ||
@@ -2698,6 +2916,7 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2698 | u16 len) | 2916 | u16 len) |
2699 | { | 2917 | { |
2700 | struct mgmt_cp_set_device_id *cp = data; | 2918 | struct mgmt_cp_set_device_id *cp = data; |
2919 | struct hci_request req; | ||
2701 | int err; | 2920 | int err; |
2702 | __u16 source; | 2921 | __u16 source; |
2703 | 2922 | ||
@@ -2718,24 +2937,59 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2718 | 2937 | ||
2719 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0); | 2938 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0); |
2720 | 2939 | ||
2721 | update_eir(hdev); | 2940 | hci_req_init(&req, hdev); |
2941 | update_eir(&req); | ||
2942 | hci_req_run(&req, NULL); | ||
2722 | 2943 | ||
2723 | hci_dev_unlock(hdev); | 2944 | hci_dev_unlock(hdev); |
2724 | 2945 | ||
2725 | return err; | 2946 | return err; |
2726 | } | 2947 | } |
2727 | 2948 | ||
2949 | static void fast_connectable_complete(struct hci_dev *hdev, u8 status) | ||
2950 | { | ||
2951 | struct pending_cmd *cmd; | ||
2952 | |||
2953 | BT_DBG("status 0x%02x", status); | ||
2954 | |||
2955 | hci_dev_lock(hdev); | ||
2956 | |||
2957 | cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev); | ||
2958 | if (!cmd) | ||
2959 | goto unlock; | ||
2960 | |||
2961 | if (status) { | ||
2962 | cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | ||
2963 | mgmt_status(status)); | ||
2964 | } else { | ||
2965 | struct mgmt_mode *cp = cmd->param; | ||
2966 | |||
2967 | if (cp->val) | ||
2968 | set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags); | ||
2969 | else | ||
2970 | clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags); | ||
2971 | |||
2972 | send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev); | ||
2973 | new_settings(hdev, cmd->sk); | ||
2974 | } | ||
2975 | |||
2976 | mgmt_pending_remove(cmd); | ||
2977 | |||
2978 | unlock: | ||
2979 | hci_dev_unlock(hdev); | ||
2980 | } | ||
2981 | |||
2728 | static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev, | 2982 | static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev, |
2729 | void *data, u16 len) | 2983 | void *data, u16 len) |
2730 | { | 2984 | { |
2731 | struct mgmt_mode *cp = data; | 2985 | struct mgmt_mode *cp = data; |
2732 | struct hci_cp_write_page_scan_activity acp; | 2986 | struct pending_cmd *cmd; |
2733 | u8 type; | 2987 | struct hci_request req; |
2734 | int err; | 2988 | int err; |
2735 | 2989 | ||
2736 | BT_DBG("%s", hdev->name); | 2990 | BT_DBG("%s", hdev->name); |
2737 | 2991 | ||
2738 | if (!lmp_bredr_capable(hdev)) | 2992 | if (!lmp_bredr_capable(hdev) || hdev->hci_ver < BLUETOOTH_VER_1_2) |
2739 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | 2993 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, |
2740 | MGMT_STATUS_NOT_SUPPORTED); | 2994 | MGMT_STATUS_NOT_SUPPORTED); |
2741 | 2995 | ||
@@ -2753,40 +3007,39 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev, | |||
2753 | 3007 | ||
2754 | hci_dev_lock(hdev); | 3008 | hci_dev_lock(hdev); |
2755 | 3009 | ||
2756 | if (cp->val) { | 3010 | if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) { |
2757 | type = PAGE_SCAN_TYPE_INTERLACED; | 3011 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, |
3012 | MGMT_STATUS_BUSY); | ||
3013 | goto unlock; | ||
3014 | } | ||
2758 | 3015 | ||
2759 | /* 160 msec page scan interval */ | 3016 | if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) { |
2760 | acp.interval = __constant_cpu_to_le16(0x0100); | 3017 | err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE, |
2761 | } else { | 3018 | hdev); |
2762 | type = PAGE_SCAN_TYPE_STANDARD; /* default */ | 3019 | goto unlock; |
3020 | } | ||
2763 | 3021 | ||
2764 | /* default 1.28 sec page scan */ | 3022 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev, |
2765 | acp.interval = __constant_cpu_to_le16(0x0800); | 3023 | data, len); |
3024 | if (!cmd) { | ||
3025 | err = -ENOMEM; | ||
3026 | goto unlock; | ||
2766 | } | 3027 | } |
2767 | 3028 | ||
2768 | /* default 11.25 msec page scan window */ | 3029 | hci_req_init(&req, hdev); |
2769 | acp.window = __constant_cpu_to_le16(0x0012); | ||
2770 | 3030 | ||
2771 | err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, sizeof(acp), | 3031 | write_fast_connectable(&req, cp->val); |
2772 | &acp); | ||
2773 | if (err < 0) { | ||
2774 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | ||
2775 | MGMT_STATUS_FAILED); | ||
2776 | goto done; | ||
2777 | } | ||
2778 | 3032 | ||
2779 | err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type); | 3033 | err = hci_req_run(&req, fast_connectable_complete); |
2780 | if (err < 0) { | 3034 | if (err < 0) { |
2781 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | 3035 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, |
2782 | MGMT_STATUS_FAILED); | 3036 | MGMT_STATUS_FAILED); |
2783 | goto done; | 3037 | mgmt_pending_remove(cmd); |
2784 | } | 3038 | } |
2785 | 3039 | ||
2786 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, 0, | 3040 | unlock: |
2787 | NULL, 0); | ||
2788 | done: | ||
2789 | hci_dev_unlock(hdev); | 3041 | hci_dev_unlock(hdev); |
3042 | |||
2790 | return err; | 3043 | return err; |
2791 | } | 3044 | } |
2792 | 3045 | ||
@@ -3043,79 +3296,115 @@ static void settings_rsp(struct pending_cmd *cmd, void *data) | |||
3043 | mgmt_pending_free(cmd); | 3296 | mgmt_pending_free(cmd); |
3044 | } | 3297 | } |
3045 | 3298 | ||
3046 | static int set_bredr_scan(struct hci_dev *hdev) | 3299 | static void set_bredr_scan(struct hci_request *req) |
3047 | { | 3300 | { |
3301 | struct hci_dev *hdev = req->hdev; | ||
3048 | u8 scan = 0; | 3302 | u8 scan = 0; |
3049 | 3303 | ||
3304 | /* Ensure that fast connectable is disabled. This function will | ||
3305 | * not do anything if the page scan parameters are already what | ||
3306 | * they should be. | ||
3307 | */ | ||
3308 | write_fast_connectable(req, false); | ||
3309 | |||
3050 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | 3310 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) |
3051 | scan |= SCAN_PAGE; | 3311 | scan |= SCAN_PAGE; |
3052 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) | 3312 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) |
3053 | scan |= SCAN_INQUIRY; | 3313 | scan |= SCAN_INQUIRY; |
3054 | 3314 | ||
3055 | if (!scan) | 3315 | if (scan) |
3056 | return 0; | 3316 | hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); |
3057 | |||
3058 | return hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | ||
3059 | } | 3317 | } |
3060 | 3318 | ||
3061 | int mgmt_powered(struct hci_dev *hdev, u8 powered) | 3319 | static void powered_complete(struct hci_dev *hdev, u8 status) |
3062 | { | 3320 | { |
3063 | struct cmd_lookup match = { NULL, hdev }; | 3321 | struct cmd_lookup match = { NULL, hdev }; |
3064 | int err; | ||
3065 | 3322 | ||
3066 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) | 3323 | BT_DBG("status 0x%02x", status); |
3067 | return 0; | 3324 | |
3325 | hci_dev_lock(hdev); | ||
3068 | 3326 | ||
3069 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); | 3327 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); |
3070 | 3328 | ||
3071 | if (powered) { | 3329 | new_settings(hdev, match.sk); |
3072 | u8 link_sec; | ||
3073 | 3330 | ||
3074 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && | 3331 | hci_dev_unlock(hdev); |
3075 | !lmp_host_ssp_capable(hdev)) { | ||
3076 | u8 ssp = 1; | ||
3077 | 3332 | ||
3078 | hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &ssp); | 3333 | if (match.sk) |
3079 | } | 3334 | sock_put(match.sk); |
3335 | } | ||
3080 | 3336 | ||
3081 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { | 3337 | static int powered_update_hci(struct hci_dev *hdev) |
3082 | struct hci_cp_write_le_host_supported cp; | 3338 | { |
3339 | struct hci_request req; | ||
3340 | u8 link_sec; | ||
3083 | 3341 | ||
3084 | cp.le = 1; | 3342 | hci_req_init(&req, hdev); |
3085 | cp.simul = lmp_le_br_capable(hdev); | ||
3086 | 3343 | ||
3087 | /* Check first if we already have the right | 3344 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && |
3088 | * host state (host features set) | 3345 | !lmp_host_ssp_capable(hdev)) { |
3089 | */ | 3346 | u8 ssp = 1; |
3090 | if (cp.le != lmp_host_le_capable(hdev) || | ||
3091 | cp.simul != lmp_host_le_br_capable(hdev)) | ||
3092 | hci_send_cmd(hdev, | ||
3093 | HCI_OP_WRITE_LE_HOST_SUPPORTED, | ||
3094 | sizeof(cp), &cp); | ||
3095 | } | ||
3096 | 3347 | ||
3097 | link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags); | 3348 | hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp); |
3098 | if (link_sec != test_bit(HCI_AUTH, &hdev->flags)) | 3349 | } |
3099 | hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, | ||
3100 | sizeof(link_sec), &link_sec); | ||
3101 | 3350 | ||
3102 | if (lmp_bredr_capable(hdev)) { | 3351 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { |
3103 | set_bredr_scan(hdev); | 3352 | struct hci_cp_write_le_host_supported cp; |
3104 | update_class(hdev); | ||
3105 | update_name(hdev, hdev->dev_name); | ||
3106 | update_eir(hdev); | ||
3107 | } | ||
3108 | } else { | ||
3109 | u8 status = MGMT_STATUS_NOT_POWERED; | ||
3110 | u8 zero_cod[] = { 0, 0, 0 }; | ||
3111 | 3353 | ||
3112 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); | 3354 | cp.le = 1; |
3355 | cp.simul = lmp_le_br_capable(hdev); | ||
3113 | 3356 | ||
3114 | if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) | 3357 | /* Check first if we already have the right |
3115 | mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, | 3358 | * host state (host features set) |
3116 | zero_cod, sizeof(zero_cod), NULL); | 3359 | */ |
3360 | if (cp.le != lmp_host_le_capable(hdev) || | ||
3361 | cp.simul != lmp_host_le_br_capable(hdev)) | ||
3362 | hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, | ||
3363 | sizeof(cp), &cp); | ||
3117 | } | 3364 | } |
3118 | 3365 | ||
3366 | link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags); | ||
3367 | if (link_sec != test_bit(HCI_AUTH, &hdev->flags)) | ||
3368 | hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE, | ||
3369 | sizeof(link_sec), &link_sec); | ||
3370 | |||
3371 | if (lmp_bredr_capable(hdev)) { | ||
3372 | set_bredr_scan(&req); | ||
3373 | update_class(&req); | ||
3374 | update_name(&req); | ||
3375 | update_eir(&req); | ||
3376 | } | ||
3377 | |||
3378 | return hci_req_run(&req, powered_complete); | ||
3379 | } | ||
3380 | |||
3381 | int mgmt_powered(struct hci_dev *hdev, u8 powered) | ||
3382 | { | ||
3383 | struct cmd_lookup match = { NULL, hdev }; | ||
3384 | u8 status_not_powered = MGMT_STATUS_NOT_POWERED; | ||
3385 | u8 zero_cod[] = { 0, 0, 0 }; | ||
3386 | int err; | ||
3387 | |||
3388 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) | ||
3389 | return 0; | ||
3390 | |||
3391 | if (powered) { | ||
3392 | if (powered_update_hci(hdev) == 0) | ||
3393 | return 0; | ||
3394 | |||
3395 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, | ||
3396 | &match); | ||
3397 | goto new_settings; | ||
3398 | } | ||
3399 | |||
3400 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); | ||
3401 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered); | ||
3402 | |||
3403 | if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) | ||
3404 | mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, | ||
3405 | zero_cod, sizeof(zero_cod), NULL); | ||
3406 | |||
3407 | new_settings: | ||
3119 | err = new_settings(hdev, match.sk); | 3408 | err = new_settings(hdev, match.sk); |
3120 | 3409 | ||
3121 | if (match.sk) | 3410 | if (match.sk) |
@@ -3152,7 +3441,7 @@ int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) | |||
3152 | 3441 | ||
3153 | int mgmt_connectable(struct hci_dev *hdev, u8 connectable) | 3442 | int mgmt_connectable(struct hci_dev *hdev, u8 connectable) |
3154 | { | 3443 | { |
3155 | struct cmd_lookup match = { NULL, hdev }; | 3444 | struct pending_cmd *cmd; |
3156 | bool changed = false; | 3445 | bool changed = false; |
3157 | int err = 0; | 3446 | int err = 0; |
3158 | 3447 | ||
@@ -3164,14 +3453,10 @@ int mgmt_connectable(struct hci_dev *hdev, u8 connectable) | |||
3164 | changed = true; | 3453 | changed = true; |
3165 | } | 3454 | } |
3166 | 3455 | ||
3167 | mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, settings_rsp, | 3456 | cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev); |
3168 | &match); | ||
3169 | 3457 | ||
3170 | if (changed) | 3458 | if (changed) |
3171 | err = new_settings(hdev, match.sk); | 3459 | err = new_settings(hdev, cmd ? cmd->sk : NULL); |
3172 | |||
3173 | if (match.sk) | ||
3174 | sock_put(match.sk); | ||
3175 | 3460 | ||
3176 | return err; | 3461 | return err; |
3177 | } | 3462 | } |
@@ -3555,23 +3840,25 @@ int mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status) | |||
3555 | return err; | 3840 | return err; |
3556 | } | 3841 | } |
3557 | 3842 | ||
3558 | static int clear_eir(struct hci_dev *hdev) | 3843 | static void clear_eir(struct hci_request *req) |
3559 | { | 3844 | { |
3845 | struct hci_dev *hdev = req->hdev; | ||
3560 | struct hci_cp_write_eir cp; | 3846 | struct hci_cp_write_eir cp; |
3561 | 3847 | ||
3562 | if (!lmp_ext_inq_capable(hdev)) | 3848 | if (!lmp_ext_inq_capable(hdev)) |
3563 | return 0; | 3849 | return; |
3564 | 3850 | ||
3565 | memset(hdev->eir, 0, sizeof(hdev->eir)); | 3851 | memset(hdev->eir, 0, sizeof(hdev->eir)); |
3566 | 3852 | ||
3567 | memset(&cp, 0, sizeof(cp)); | 3853 | memset(&cp, 0, sizeof(cp)); |
3568 | 3854 | ||
3569 | return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); | 3855 | hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp); |
3570 | } | 3856 | } |
3571 | 3857 | ||
3572 | int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) | 3858 | int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) |
3573 | { | 3859 | { |
3574 | struct cmd_lookup match = { NULL, hdev }; | 3860 | struct cmd_lookup match = { NULL, hdev }; |
3861 | struct hci_request req; | ||
3575 | bool changed = false; | 3862 | bool changed = false; |
3576 | int err = 0; | 3863 | int err = 0; |
3577 | 3864 | ||
@@ -3604,29 +3891,26 @@ int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) | |||
3604 | if (match.sk) | 3891 | if (match.sk) |
3605 | sock_put(match.sk); | 3892 | sock_put(match.sk); |
3606 | 3893 | ||
3894 | hci_req_init(&req, hdev); | ||
3895 | |||
3607 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) | 3896 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) |
3608 | update_eir(hdev); | 3897 | update_eir(&req); |
3609 | else | 3898 | else |
3610 | clear_eir(hdev); | 3899 | clear_eir(&req); |
3900 | |||
3901 | hci_req_run(&req, NULL); | ||
3611 | 3902 | ||
3612 | return err; | 3903 | return err; |
3613 | } | 3904 | } |
3614 | 3905 | ||
3615 | static void class_rsp(struct pending_cmd *cmd, void *data) | 3906 | static void sk_lookup(struct pending_cmd *cmd, void *data) |
3616 | { | 3907 | { |
3617 | struct cmd_lookup *match = data; | 3908 | struct cmd_lookup *match = data; |
3618 | 3909 | ||
3619 | cmd_complete(cmd->sk, cmd->index, cmd->opcode, match->mgmt_status, | ||
3620 | match->hdev->dev_class, 3); | ||
3621 | |||
3622 | list_del(&cmd->list); | ||
3623 | |||
3624 | if (match->sk == NULL) { | 3910 | if (match->sk == NULL) { |
3625 | match->sk = cmd->sk; | 3911 | match->sk = cmd->sk; |
3626 | sock_hold(match->sk); | 3912 | sock_hold(match->sk); |
3627 | } | 3913 | } |
3628 | |||
3629 | mgmt_pending_free(cmd); | ||
3630 | } | 3914 | } |
3631 | 3915 | ||
3632 | int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, | 3916 | int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, |
@@ -3635,11 +3919,9 @@ int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, | |||
3635 | struct cmd_lookup match = { NULL, hdev, mgmt_status(status) }; | 3919 | struct cmd_lookup match = { NULL, hdev, mgmt_status(status) }; |
3636 | int err = 0; | 3920 | int err = 0; |
3637 | 3921 | ||
3638 | clear_bit(HCI_PENDING_CLASS, &hdev->dev_flags); | 3922 | mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match); |
3639 | 3923 | mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match); | |
3640 | mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, class_rsp, &match); | 3924 | mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match); |
3641 | mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, class_rsp, &match); | ||
3642 | mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, class_rsp, &match); | ||
3643 | 3925 | ||
3644 | if (!status) | 3926 | if (!status) |
3645 | err = mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, | 3927 | err = mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, |
@@ -3653,55 +3935,29 @@ int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, | |||
3653 | 3935 | ||
3654 | int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status) | 3936 | int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status) |
3655 | { | 3937 | { |
3656 | struct pending_cmd *cmd; | ||
3657 | struct mgmt_cp_set_local_name ev; | 3938 | struct mgmt_cp_set_local_name ev; |
3658 | bool changed = false; | 3939 | struct pending_cmd *cmd; |
3659 | int err = 0; | ||
3660 | 3940 | ||
3661 | if (memcmp(name, hdev->dev_name, sizeof(hdev->dev_name)) != 0) { | 3941 | if (status) |
3662 | memcpy(hdev->dev_name, name, sizeof(hdev->dev_name)); | 3942 | return 0; |
3663 | changed = true; | ||
3664 | } | ||
3665 | 3943 | ||
3666 | memset(&ev, 0, sizeof(ev)); | 3944 | memset(&ev, 0, sizeof(ev)); |
3667 | memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); | 3945 | memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); |
3668 | memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH); | 3946 | memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH); |
3669 | 3947 | ||
3670 | cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev); | 3948 | cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev); |
3671 | if (!cmd) | 3949 | if (!cmd) { |
3672 | goto send_event; | 3950 | memcpy(hdev->dev_name, name, sizeof(hdev->dev_name)); |
3673 | |||
3674 | /* Always assume that either the short or the complete name has | ||
3675 | * changed if there was a pending mgmt command */ | ||
3676 | changed = true; | ||
3677 | 3951 | ||
3678 | if (status) { | 3952 | /* If this is a HCI command related to powering on the |
3679 | err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, | 3953 | * HCI dev don't send any mgmt signals. |
3680 | mgmt_status(status)); | 3954 | */ |
3681 | goto failed; | 3955 | if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) |
3956 | return 0; | ||
3682 | } | 3957 | } |
3683 | 3958 | ||
3684 | err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0, &ev, | 3959 | return mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev), |
3685 | sizeof(ev)); | 3960 | cmd ? cmd->sk : NULL); |
3686 | if (err < 0) | ||
3687 | goto failed; | ||
3688 | |||
3689 | send_event: | ||
3690 | if (changed) | ||
3691 | err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, | ||
3692 | sizeof(ev), cmd ? cmd->sk : NULL); | ||
3693 | |||
3694 | /* EIR is taken care of separately when powering on the | ||
3695 | * adapter so only update them here if this is a name change | ||
3696 | * unrelated to power on. | ||
3697 | */ | ||
3698 | if (!test_bit(HCI_INIT, &hdev->flags)) | ||
3699 | update_eir(hdev); | ||
3700 | |||
3701 | failed: | ||
3702 | if (cmd) | ||
3703 | mgmt_pending_remove(cmd); | ||
3704 | return err; | ||
3705 | } | 3961 | } |
3706 | 3962 | ||
3707 | int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, | 3963 | int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, |