diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2015-11-18 05:49:20 -0500 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2015-12-09 18:51:47 -0500 |
commit | f22525700b2ae34eb97a29a91e2eee902062b484 (patch) | |
tree | 1d45d8ed3e7a2224836d7dd9942ce01151690b9f /net/bluetooth | |
parent | 196a5e97d13092f783e41001c1112d7f31518ea2 (diff) |
Bluetooth: Move advertising instance management to hci_request.c
This paves the way for eventually performing advertising changes
through the hdev->req_workqueue. Some new APIs need to be exposed from
mgmt.c to hci_request.c and vice-versa, but many of them will go away
once hdev->req_workqueue gets used.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/hci_conn.c | 2 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 19 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 4 | ||||
-rw-r--r-- | net/bluetooth/hci_request.c | 533 | ||||
-rw-r--r-- | net/bluetooth/hci_request.h | 14 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 574 |
6 files changed, 583 insertions, 563 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 2d334e07fd77..e2600213cd50 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -683,7 +683,7 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status) | |||
683 | /* Re-enable advertising in case this was a failed connection | 683 | /* Re-enable advertising in case this was a failed connection |
684 | * attempt as a peripheral. | 684 | * attempt as a peripheral. |
685 | */ | 685 | */ |
686 | mgmt_reenable_advertising(hdev); | 686 | hci_req_reenable_advertising(hdev); |
687 | } | 687 | } |
688 | 688 | ||
689 | static void create_le_conn_complete(struct hci_dev *hdev, u8 status, u16 opcode) | 689 | static void create_le_conn_complete(struct hci_dev *hdev, u8 status, u16 opcode) |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 89af7e4fac02..bab8958bf46e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -1549,11 +1549,6 @@ int hci_dev_do_close(struct hci_dev *hdev) | |||
1549 | if (hci_dev_test_flag(hdev, HCI_MGMT)) | 1549 | if (hci_dev_test_flag(hdev, HCI_MGMT)) |
1550 | cancel_delayed_work_sync(&hdev->rpa_expired); | 1550 | cancel_delayed_work_sync(&hdev->rpa_expired); |
1551 | 1551 | ||
1552 | if (hdev->adv_instance_timeout) { | ||
1553 | cancel_delayed_work_sync(&hdev->adv_instance_expire); | ||
1554 | hdev->adv_instance_timeout = 0; | ||
1555 | } | ||
1556 | |||
1557 | /* Avoid potential lockdep warnings from the *_flush() calls by | 1552 | /* Avoid potential lockdep warnings from the *_flush() calls by |
1558 | * ensuring the workqueue is empty up front. | 1553 | * ensuring the workqueue is empty up front. |
1559 | */ | 1554 | */ |
@@ -1774,7 +1769,7 @@ static void hci_update_scan_state(struct hci_dev *hdev, u8 scan) | |||
1774 | hci_dev_set_flag(hdev, HCI_BREDR_ENABLED); | 1769 | hci_dev_set_flag(hdev, HCI_BREDR_ENABLED); |
1775 | 1770 | ||
1776 | if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) | 1771 | if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) |
1777 | mgmt_update_adv_data(hdev); | 1772 | hci_req_update_adv_data(hdev, HCI_ADV_CURRENT); |
1778 | 1773 | ||
1779 | mgmt_new_settings(hdev); | 1774 | mgmt_new_settings(hdev); |
1780 | } | 1775 | } |
@@ -2112,17 +2107,6 @@ static void hci_discov_off(struct work_struct *work) | |||
2112 | mgmt_discoverable_timeout(hdev); | 2107 | mgmt_discoverable_timeout(hdev); |
2113 | } | 2108 | } |
2114 | 2109 | ||
2115 | static void hci_adv_timeout_expire(struct work_struct *work) | ||
2116 | { | ||
2117 | struct hci_dev *hdev; | ||
2118 | |||
2119 | hdev = container_of(work, struct hci_dev, adv_instance_expire.work); | ||
2120 | |||
2121 | BT_DBG("%s", hdev->name); | ||
2122 | |||
2123 | mgmt_adv_timeout_expired(hdev); | ||
2124 | } | ||
2125 | |||
2126 | void hci_uuids_clear(struct hci_dev *hdev) | 2110 | void hci_uuids_clear(struct hci_dev *hdev) |
2127 | { | 2111 | { |
2128 | struct bt_uuid *uuid, *tmp; | 2112 | struct bt_uuid *uuid, *tmp; |
@@ -3003,7 +2987,6 @@ struct hci_dev *hci_alloc_dev(void) | |||
3003 | 2987 | ||
3004 | INIT_DELAYED_WORK(&hdev->power_off, hci_power_off); | 2988 | INIT_DELAYED_WORK(&hdev->power_off, hci_power_off); |
3005 | INIT_DELAYED_WORK(&hdev->discov_off, hci_discov_off); | 2989 | INIT_DELAYED_WORK(&hdev->discov_off, hci_discov_off); |
3006 | INIT_DELAYED_WORK(&hdev->adv_instance_expire, hci_adv_timeout_expire); | ||
3007 | 2990 | ||
3008 | skb_queue_head_init(&hdev->rx_q); | 2991 | skb_queue_head_init(&hdev->rx_q); |
3009 | skb_queue_head_init(&hdev->cmd_q); | 2992 | skb_queue_head_init(&hdev->cmd_q); |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 703e37f1a955..7554da5b7a8f 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -1183,7 +1183,7 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, | |||
1183 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | 1183 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); |
1184 | else if (!hci_dev_test_flag(hdev, HCI_LE_ADV) && | 1184 | else if (!hci_dev_test_flag(hdev, HCI_LE_ADV) && |
1185 | hdev->discovery.state == DISCOVERY_FINDING) | 1185 | hdev->discovery.state == DISCOVERY_FINDING) |
1186 | mgmt_reenable_advertising(hdev); | 1186 | hci_req_reenable_advertising(hdev); |
1187 | 1187 | ||
1188 | break; | 1188 | break; |
1189 | 1189 | ||
@@ -2401,7 +2401,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2401 | * is timed out due to Directed Advertising." | 2401 | * is timed out due to Directed Advertising." |
2402 | */ | 2402 | */ |
2403 | if (type == LE_LINK) | 2403 | if (type == LE_LINK) |
2404 | mgmt_reenable_advertising(hdev); | 2404 | hci_req_reenable_advertising(hdev); |
2405 | 2405 | ||
2406 | unlock: | 2406 | unlock: |
2407 | hci_dev_unlock(hdev); | 2407 | hci_dev_unlock(hdev); |
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index 7c85435b8982..e6622bd1926d 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | #include <net/bluetooth/bluetooth.h> | 24 | #include <net/bluetooth/bluetooth.h> |
25 | #include <net/bluetooth/hci_core.h> | 25 | #include <net/bluetooth/hci_core.h> |
26 | #include <net/bluetooth/mgmt.h> | ||
26 | 27 | ||
27 | #include "smp.h" | 28 | #include "smp.h" |
28 | #include "hci_request.h" | 29 | #include "hci_request.h" |
@@ -580,6 +581,524 @@ void hci_req_add_le_passive_scan(struct hci_request *req) | |||
580 | &enable_cp); | 581 | &enable_cp); |
581 | } | 582 | } |
582 | 583 | ||
584 | static u8 get_current_adv_instance(struct hci_dev *hdev) | ||
585 | { | ||
586 | /* The "Set Advertising" setting supersedes the "Add Advertising" | ||
587 | * setting. Here we set the advertising data based on which | ||
588 | * setting was set. When neither apply, default to the global settings, | ||
589 | * represented by instance "0". | ||
590 | */ | ||
591 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) && | ||
592 | !hci_dev_test_flag(hdev, HCI_ADVERTISING)) | ||
593 | return hdev->cur_adv_instance; | ||
594 | |||
595 | return 0x00; | ||
596 | } | ||
597 | |||
598 | static u8 get_cur_adv_instance_scan_rsp_len(struct hci_dev *hdev) | ||
599 | { | ||
600 | u8 instance = get_current_adv_instance(hdev); | ||
601 | struct adv_info *adv_instance; | ||
602 | |||
603 | /* Ignore instance 0 */ | ||
604 | if (instance == 0x00) | ||
605 | return 0; | ||
606 | |||
607 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
608 | if (!adv_instance) | ||
609 | return 0; | ||
610 | |||
611 | /* TODO: Take into account the "appearance" and "local-name" flags here. | ||
612 | * These are currently being ignored as they are not supported. | ||
613 | */ | ||
614 | return adv_instance->scan_rsp_len; | ||
615 | } | ||
616 | |||
617 | void __hci_req_disable_advertising(struct hci_request *req) | ||
618 | { | ||
619 | u8 enable = 0x00; | ||
620 | |||
621 | hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); | ||
622 | } | ||
623 | |||
624 | static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance) | ||
625 | { | ||
626 | u32 flags; | ||
627 | struct adv_info *adv_instance; | ||
628 | |||
629 | if (instance == 0x00) { | ||
630 | /* Instance 0 always manages the "Tx Power" and "Flags" | ||
631 | * fields | ||
632 | */ | ||
633 | flags = MGMT_ADV_FLAG_TX_POWER | MGMT_ADV_FLAG_MANAGED_FLAGS; | ||
634 | |||
635 | /* For instance 0, the HCI_ADVERTISING_CONNECTABLE setting | ||
636 | * corresponds to the "connectable" instance flag. | ||
637 | */ | ||
638 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) | ||
639 | flags |= MGMT_ADV_FLAG_CONNECTABLE; | ||
640 | |||
641 | return flags; | ||
642 | } | ||
643 | |||
644 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
645 | |||
646 | /* Return 0 when we got an invalid instance identifier. */ | ||
647 | if (!adv_instance) | ||
648 | return 0; | ||
649 | |||
650 | return adv_instance->flags; | ||
651 | } | ||
652 | |||
653 | void __hci_req_enable_advertising(struct hci_request *req) | ||
654 | { | ||
655 | struct hci_dev *hdev = req->hdev; | ||
656 | struct hci_cp_le_set_adv_param cp; | ||
657 | u8 own_addr_type, enable = 0x01; | ||
658 | bool connectable; | ||
659 | u8 instance; | ||
660 | u32 flags; | ||
661 | |||
662 | if (hci_conn_num(hdev, LE_LINK) > 0) | ||
663 | return; | ||
664 | |||
665 | if (hci_dev_test_flag(hdev, HCI_LE_ADV)) | ||
666 | __hci_req_disable_advertising(req); | ||
667 | |||
668 | /* Clear the HCI_LE_ADV bit temporarily so that the | ||
669 | * hci_update_random_address knows that it's safe to go ahead | ||
670 | * and write a new random address. The flag will be set back on | ||
671 | * as soon as the SET_ADV_ENABLE HCI command completes. | ||
672 | */ | ||
673 | hci_dev_clear_flag(hdev, HCI_LE_ADV); | ||
674 | |||
675 | instance = get_current_adv_instance(hdev); | ||
676 | flags = get_adv_instance_flags(hdev, instance); | ||
677 | |||
678 | /* If the "connectable" instance flag was not set, then choose between | ||
679 | * ADV_IND and ADV_NONCONN_IND based on the global connectable setting. | ||
680 | */ | ||
681 | connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) || | ||
682 | mgmt_get_connectable(hdev); | ||
683 | |||
684 | /* Set require_privacy to true only when non-connectable | ||
685 | * advertising is used. In that case it is fine to use a | ||
686 | * non-resolvable private address. | ||
687 | */ | ||
688 | if (hci_update_random_address(req, !connectable, &own_addr_type) < 0) | ||
689 | return; | ||
690 | |||
691 | memset(&cp, 0, sizeof(cp)); | ||
692 | cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval); | ||
693 | cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval); | ||
694 | |||
695 | if (connectable) | ||
696 | cp.type = LE_ADV_IND; | ||
697 | else if (get_cur_adv_instance_scan_rsp_len(hdev)) | ||
698 | cp.type = LE_ADV_SCAN_IND; | ||
699 | else | ||
700 | cp.type = LE_ADV_NONCONN_IND; | ||
701 | |||
702 | cp.own_address_type = own_addr_type; | ||
703 | cp.channel_map = hdev->le_adv_channel_map; | ||
704 | |||
705 | hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp); | ||
706 | |||
707 | hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); | ||
708 | } | ||
709 | |||
710 | static u8 create_default_scan_rsp_data(struct hci_dev *hdev, u8 *ptr) | ||
711 | { | ||
712 | u8 ad_len = 0; | ||
713 | size_t name_len; | ||
714 | |||
715 | name_len = strlen(hdev->dev_name); | ||
716 | if (name_len > 0) { | ||
717 | size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2; | ||
718 | |||
719 | if (name_len > max_len) { | ||
720 | name_len = max_len; | ||
721 | ptr[1] = EIR_NAME_SHORT; | ||
722 | } else | ||
723 | ptr[1] = EIR_NAME_COMPLETE; | ||
724 | |||
725 | ptr[0] = name_len + 1; | ||
726 | |||
727 | memcpy(ptr + 2, hdev->dev_name, name_len); | ||
728 | |||
729 | ad_len += (name_len + 2); | ||
730 | ptr += (name_len + 2); | ||
731 | } | ||
732 | |||
733 | return ad_len; | ||
734 | } | ||
735 | |||
736 | static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 instance, | ||
737 | u8 *ptr) | ||
738 | { | ||
739 | struct adv_info *adv_instance; | ||
740 | |||
741 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
742 | if (!adv_instance) | ||
743 | return 0; | ||
744 | |||
745 | /* TODO: Set the appropriate entries based on advertising instance flags | ||
746 | * here once flags other than 0 are supported. | ||
747 | */ | ||
748 | memcpy(ptr, adv_instance->scan_rsp_data, | ||
749 | adv_instance->scan_rsp_len); | ||
750 | |||
751 | return adv_instance->scan_rsp_len; | ||
752 | } | ||
753 | |||
754 | static void update_inst_scan_rsp_data(struct hci_request *req, u8 instance) | ||
755 | { | ||
756 | struct hci_dev *hdev = req->hdev; | ||
757 | struct hci_cp_le_set_scan_rsp_data cp; | ||
758 | u8 len; | ||
759 | |||
760 | if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) | ||
761 | return; | ||
762 | |||
763 | memset(&cp, 0, sizeof(cp)); | ||
764 | |||
765 | if (instance) | ||
766 | len = create_instance_scan_rsp_data(hdev, instance, cp.data); | ||
767 | else | ||
768 | len = create_default_scan_rsp_data(hdev, cp.data); | ||
769 | |||
770 | if (hdev->scan_rsp_data_len == len && | ||
771 | !memcmp(cp.data, hdev->scan_rsp_data, len)) | ||
772 | return; | ||
773 | |||
774 | memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data)); | ||
775 | hdev->scan_rsp_data_len = len; | ||
776 | |||
777 | cp.length = len; | ||
778 | |||
779 | hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp); | ||
780 | } | ||
781 | |||
782 | void __hci_req_update_scan_rsp_data(struct hci_request *req, int instance) | ||
783 | { | ||
784 | if (instance == HCI_ADV_CURRENT) | ||
785 | instance = get_current_adv_instance(req->hdev); | ||
786 | |||
787 | update_inst_scan_rsp_data(req, get_current_adv_instance(req->hdev)); | ||
788 | } | ||
789 | |||
790 | static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr) | ||
791 | { | ||
792 | struct adv_info *adv_instance = NULL; | ||
793 | u8 ad_len = 0, flags = 0; | ||
794 | u32 instance_flags; | ||
795 | |||
796 | /* Return 0 when the current instance identifier is invalid. */ | ||
797 | if (instance) { | ||
798 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
799 | if (!adv_instance) | ||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | instance_flags = get_adv_instance_flags(hdev, instance); | ||
804 | |||
805 | /* The Add Advertising command allows userspace to set both the general | ||
806 | * and limited discoverable flags. | ||
807 | */ | ||
808 | if (instance_flags & MGMT_ADV_FLAG_DISCOV) | ||
809 | flags |= LE_AD_GENERAL; | ||
810 | |||
811 | if (instance_flags & MGMT_ADV_FLAG_LIMITED_DISCOV) | ||
812 | flags |= LE_AD_LIMITED; | ||
813 | |||
814 | if (flags || (instance_flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) { | ||
815 | /* If a discovery flag wasn't provided, simply use the global | ||
816 | * settings. | ||
817 | */ | ||
818 | if (!flags) | ||
819 | flags |= mgmt_get_adv_discov_flags(hdev); | ||
820 | |||
821 | if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) | ||
822 | flags |= LE_AD_NO_BREDR; | ||
823 | |||
824 | /* If flags would still be empty, then there is no need to | ||
825 | * include the "Flags" AD field". | ||
826 | */ | ||
827 | if (flags) { | ||
828 | ptr[0] = 0x02; | ||
829 | ptr[1] = EIR_FLAGS; | ||
830 | ptr[2] = flags; | ||
831 | |||
832 | ad_len += 3; | ||
833 | ptr += 3; | ||
834 | } | ||
835 | } | ||
836 | |||
837 | if (adv_instance) { | ||
838 | memcpy(ptr, adv_instance->adv_data, | ||
839 | adv_instance->adv_data_len); | ||
840 | ad_len += adv_instance->adv_data_len; | ||
841 | ptr += adv_instance->adv_data_len; | ||
842 | } | ||
843 | |||
844 | /* Provide Tx Power only if we can provide a valid value for it */ | ||
845 | if (hdev->adv_tx_power != HCI_TX_POWER_INVALID && | ||
846 | (instance_flags & MGMT_ADV_FLAG_TX_POWER)) { | ||
847 | ptr[0] = 0x02; | ||
848 | ptr[1] = EIR_TX_POWER; | ||
849 | ptr[2] = (u8)hdev->adv_tx_power; | ||
850 | |||
851 | ad_len += 3; | ||
852 | ptr += 3; | ||
853 | } | ||
854 | |||
855 | return ad_len; | ||
856 | } | ||
857 | |||
858 | static void update_inst_adv_data(struct hci_request *req, u8 instance) | ||
859 | { | ||
860 | struct hci_dev *hdev = req->hdev; | ||
861 | struct hci_cp_le_set_adv_data cp; | ||
862 | u8 len; | ||
863 | |||
864 | if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) | ||
865 | return; | ||
866 | |||
867 | memset(&cp, 0, sizeof(cp)); | ||
868 | |||
869 | len = create_instance_adv_data(hdev, instance, cp.data); | ||
870 | |||
871 | /* There's nothing to do if the data hasn't changed */ | ||
872 | if (hdev->adv_data_len == len && | ||
873 | memcmp(cp.data, hdev->adv_data, len) == 0) | ||
874 | return; | ||
875 | |||
876 | memcpy(hdev->adv_data, cp.data, sizeof(cp.data)); | ||
877 | hdev->adv_data_len = len; | ||
878 | |||
879 | cp.length = len; | ||
880 | |||
881 | hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); | ||
882 | } | ||
883 | |||
884 | void __hci_req_update_adv_data(struct hci_request *req, int instance) | ||
885 | { | ||
886 | if (instance == HCI_ADV_CURRENT) | ||
887 | instance = get_current_adv_instance(req->hdev); | ||
888 | |||
889 | update_inst_adv_data(req, instance); | ||
890 | } | ||
891 | |||
892 | int hci_req_update_adv_data(struct hci_dev *hdev, int instance) | ||
893 | { | ||
894 | struct hci_request req; | ||
895 | |||
896 | hci_req_init(&req, hdev); | ||
897 | __hci_req_update_adv_data(&req, instance); | ||
898 | |||
899 | return hci_req_run(&req, NULL); | ||
900 | } | ||
901 | |||
902 | static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode) | ||
903 | { | ||
904 | BT_DBG("%s status %u", hdev->name, status); | ||
905 | } | ||
906 | |||
907 | void hci_req_reenable_advertising(struct hci_dev *hdev) | ||
908 | { | ||
909 | struct hci_request req; | ||
910 | u8 instance; | ||
911 | |||
912 | if (!hci_dev_test_flag(hdev, HCI_ADVERTISING) && | ||
913 | !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) | ||
914 | return; | ||
915 | |||
916 | instance = get_current_adv_instance(hdev); | ||
917 | |||
918 | hci_req_init(&req, hdev); | ||
919 | |||
920 | if (instance) { | ||
921 | __hci_req_schedule_adv_instance(&req, instance, true); | ||
922 | } else { | ||
923 | __hci_req_update_adv_data(&req, HCI_ADV_CURRENT); | ||
924 | __hci_req_update_scan_rsp_data(&req, HCI_ADV_CURRENT); | ||
925 | __hci_req_enable_advertising(&req); | ||
926 | } | ||
927 | |||
928 | hci_req_run(&req, adv_enable_complete); | ||
929 | } | ||
930 | |||
931 | static void adv_timeout_expire(struct work_struct *work) | ||
932 | { | ||
933 | struct hci_dev *hdev = container_of(work, struct hci_dev, | ||
934 | adv_instance_expire.work); | ||
935 | |||
936 | struct hci_request req; | ||
937 | u8 instance; | ||
938 | |||
939 | BT_DBG("%s", hdev->name); | ||
940 | |||
941 | hci_dev_lock(hdev); | ||
942 | |||
943 | hdev->adv_instance_timeout = 0; | ||
944 | |||
945 | instance = get_current_adv_instance(hdev); | ||
946 | if (instance == 0x00) | ||
947 | goto unlock; | ||
948 | |||
949 | hci_req_init(&req, hdev); | ||
950 | |||
951 | hci_req_clear_adv_instance(hdev, &req, instance, false); | ||
952 | |||
953 | if (list_empty(&hdev->adv_instances)) | ||
954 | __hci_req_disable_advertising(&req); | ||
955 | |||
956 | if (!skb_queue_empty(&req.cmd_q)) | ||
957 | hci_req_run(&req, NULL); | ||
958 | |||
959 | unlock: | ||
960 | hci_dev_unlock(hdev); | ||
961 | } | ||
962 | |||
963 | int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance, | ||
964 | bool force) | ||
965 | { | ||
966 | struct hci_dev *hdev = req->hdev; | ||
967 | struct adv_info *adv_instance = NULL; | ||
968 | u16 timeout; | ||
969 | |||
970 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING) || | ||
971 | !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) | ||
972 | return -EPERM; | ||
973 | |||
974 | if (hdev->adv_instance_timeout) | ||
975 | return -EBUSY; | ||
976 | |||
977 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
978 | if (!adv_instance) | ||
979 | return -ENOENT; | ||
980 | |||
981 | /* A zero timeout means unlimited advertising. As long as there is | ||
982 | * only one instance, duration should be ignored. We still set a timeout | ||
983 | * in case further instances are being added later on. | ||
984 | * | ||
985 | * If the remaining lifetime of the instance is more than the duration | ||
986 | * then the timeout corresponds to the duration, otherwise it will be | ||
987 | * reduced to the remaining instance lifetime. | ||
988 | */ | ||
989 | if (adv_instance->timeout == 0 || | ||
990 | adv_instance->duration <= adv_instance->remaining_time) | ||
991 | timeout = adv_instance->duration; | ||
992 | else | ||
993 | timeout = adv_instance->remaining_time; | ||
994 | |||
995 | /* The remaining time is being reduced unless the instance is being | ||
996 | * advertised without time limit. | ||
997 | */ | ||
998 | if (adv_instance->timeout) | ||
999 | adv_instance->remaining_time = | ||
1000 | adv_instance->remaining_time - timeout; | ||
1001 | |||
1002 | hdev->adv_instance_timeout = timeout; | ||
1003 | queue_delayed_work(hdev->req_workqueue, | ||
1004 | &hdev->adv_instance_expire, | ||
1005 | msecs_to_jiffies(timeout * 1000)); | ||
1006 | |||
1007 | /* If we're just re-scheduling the same instance again then do not | ||
1008 | * execute any HCI commands. This happens when a single instance is | ||
1009 | * being advertised. | ||
1010 | */ | ||
1011 | if (!force && hdev->cur_adv_instance == instance && | ||
1012 | hci_dev_test_flag(hdev, HCI_LE_ADV)) | ||
1013 | return 0; | ||
1014 | |||
1015 | hdev->cur_adv_instance = instance; | ||
1016 | __hci_req_update_adv_data(req, HCI_ADV_CURRENT); | ||
1017 | __hci_req_update_scan_rsp_data(req, HCI_ADV_CURRENT); | ||
1018 | __hci_req_enable_advertising(req); | ||
1019 | |||
1020 | return 0; | ||
1021 | } | ||
1022 | |||
1023 | static void cancel_adv_timeout(struct hci_dev *hdev) | ||
1024 | { | ||
1025 | if (hdev->adv_instance_timeout) { | ||
1026 | hdev->adv_instance_timeout = 0; | ||
1027 | cancel_delayed_work(&hdev->adv_instance_expire); | ||
1028 | } | ||
1029 | } | ||
1030 | |||
1031 | /* For a single instance: | ||
1032 | * - force == true: The instance will be removed even when its remaining | ||
1033 | * lifetime is not zero. | ||
1034 | * - force == false: the instance will be deactivated but kept stored unless | ||
1035 | * the remaining lifetime is zero. | ||
1036 | * | ||
1037 | * For instance == 0x00: | ||
1038 | * - force == true: All instances will be removed regardless of their timeout | ||
1039 | * setting. | ||
1040 | * - force == false: Only instances that have a timeout will be removed. | ||
1041 | */ | ||
1042 | void hci_req_clear_adv_instance(struct hci_dev *hdev, struct hci_request *req, | ||
1043 | u8 instance, bool force) | ||
1044 | { | ||
1045 | struct adv_info *adv_instance, *n, *next_instance = NULL; | ||
1046 | int err; | ||
1047 | u8 rem_inst; | ||
1048 | |||
1049 | /* Cancel any timeout concerning the removed instance(s). */ | ||
1050 | if (!instance || hdev->cur_adv_instance == instance) | ||
1051 | cancel_adv_timeout(hdev); | ||
1052 | |||
1053 | /* Get the next instance to advertise BEFORE we remove | ||
1054 | * the current one. This can be the same instance again | ||
1055 | * if there is only one instance. | ||
1056 | */ | ||
1057 | if (instance && hdev->cur_adv_instance == instance) | ||
1058 | next_instance = hci_get_next_instance(hdev, instance); | ||
1059 | |||
1060 | if (instance == 0x00) { | ||
1061 | list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances, | ||
1062 | list) { | ||
1063 | if (!(force || adv_instance->timeout)) | ||
1064 | continue; | ||
1065 | |||
1066 | rem_inst = adv_instance->instance; | ||
1067 | err = hci_remove_adv_instance(hdev, rem_inst); | ||
1068 | if (!err) | ||
1069 | mgmt_advertising_removed(NULL, hdev, rem_inst); | ||
1070 | } | ||
1071 | hdev->cur_adv_instance = 0x00; | ||
1072 | } else { | ||
1073 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
1074 | |||
1075 | if (force || (adv_instance && adv_instance->timeout && | ||
1076 | !adv_instance->remaining_time)) { | ||
1077 | /* Don't advertise a removed instance. */ | ||
1078 | if (next_instance && | ||
1079 | next_instance->instance == instance) | ||
1080 | next_instance = NULL; | ||
1081 | |||
1082 | err = hci_remove_adv_instance(hdev, instance); | ||
1083 | if (!err) | ||
1084 | mgmt_advertising_removed(NULL, hdev, instance); | ||
1085 | } | ||
1086 | } | ||
1087 | |||
1088 | if (list_empty(&hdev->adv_instances)) { | ||
1089 | hdev->cur_adv_instance = 0x00; | ||
1090 | hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE); | ||
1091 | } | ||
1092 | |||
1093 | if (!req || !hdev_is_powered(hdev) || | ||
1094 | hci_dev_test_flag(hdev, HCI_ADVERTISING)) | ||
1095 | return; | ||
1096 | |||
1097 | if (next_instance) | ||
1098 | __hci_req_schedule_adv_instance(req, next_instance->instance, | ||
1099 | false); | ||
1100 | } | ||
1101 | |||
583 | static void set_random_addr(struct hci_request *req, bdaddr_t *rpa) | 1102 | static void set_random_addr(struct hci_request *req, bdaddr_t *rpa) |
584 | { | 1103 | { |
585 | struct hci_dev *hdev = req->hdev; | 1104 | struct hci_dev *hdev = req->hdev; |
@@ -1031,14 +1550,6 @@ unlock: | |||
1031 | hci_dev_unlock(hdev); | 1550 | hci_dev_unlock(hdev); |
1032 | } | 1551 | } |
1033 | 1552 | ||
1034 | static void cancel_adv_timeout(struct hci_dev *hdev) | ||
1035 | { | ||
1036 | if (hdev->adv_instance_timeout) { | ||
1037 | hdev->adv_instance_timeout = 0; | ||
1038 | cancel_delayed_work(&hdev->adv_instance_expire); | ||
1039 | } | ||
1040 | } | ||
1041 | |||
1042 | static void disable_advertising(struct hci_request *req) | 1553 | static void disable_advertising(struct hci_request *req) |
1043 | { | 1554 | { |
1044 | u8 enable = 0x00; | 1555 | u8 enable = 0x00; |
@@ -1280,6 +1791,7 @@ void hci_request_setup(struct hci_dev *hdev) | |||
1280 | INIT_WORK(&hdev->scan_update, scan_update_work); | 1791 | INIT_WORK(&hdev->scan_update, scan_update_work); |
1281 | INIT_DELAYED_WORK(&hdev->le_scan_disable, le_scan_disable_work); | 1792 | INIT_DELAYED_WORK(&hdev->le_scan_disable, le_scan_disable_work); |
1282 | INIT_DELAYED_WORK(&hdev->le_scan_restart, le_scan_restart_work); | 1793 | INIT_DELAYED_WORK(&hdev->le_scan_restart, le_scan_restart_work); |
1794 | INIT_DELAYED_WORK(&hdev->adv_instance_expire, adv_timeout_expire); | ||
1283 | } | 1795 | } |
1284 | 1796 | ||
1285 | void hci_request_cancel_all(struct hci_dev *hdev) | 1797 | void hci_request_cancel_all(struct hci_dev *hdev) |
@@ -1291,4 +1803,9 @@ void hci_request_cancel_all(struct hci_dev *hdev) | |||
1291 | cancel_work_sync(&hdev->scan_update); | 1803 | cancel_work_sync(&hdev->scan_update); |
1292 | cancel_delayed_work_sync(&hdev->le_scan_disable); | 1804 | cancel_delayed_work_sync(&hdev->le_scan_disable); |
1293 | cancel_delayed_work_sync(&hdev->le_scan_restart); | 1805 | cancel_delayed_work_sync(&hdev->le_scan_restart); |
1806 | |||
1807 | if (hdev->adv_instance_timeout) { | ||
1808 | cancel_delayed_work_sync(&hdev->adv_instance_expire); | ||
1809 | hdev->adv_instance_timeout = 0; | ||
1810 | } | ||
1294 | } | 1811 | } |
diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h index cc8275520fb2..5358b1b12ca0 100644 --- a/net/bluetooth/hci_request.h +++ b/net/bluetooth/hci_request.h | |||
@@ -58,6 +58,20 @@ struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen, | |||
58 | void hci_req_add_le_scan_disable(struct hci_request *req); | 58 | void hci_req_add_le_scan_disable(struct hci_request *req); |
59 | void hci_req_add_le_passive_scan(struct hci_request *req); | 59 | void hci_req_add_le_passive_scan(struct hci_request *req); |
60 | 60 | ||
61 | #define HCI_ADV_CURRENT (-1) | ||
62 | |||
63 | void hci_req_reenable_advertising(struct hci_dev *hdev); | ||
64 | void __hci_req_enable_advertising(struct hci_request *req); | ||
65 | void __hci_req_disable_advertising(struct hci_request *req); | ||
66 | void __hci_req_update_adv_data(struct hci_request *req, int instance); | ||
67 | int hci_req_update_adv_data(struct hci_dev *hdev, int instance); | ||
68 | void __hci_req_update_scan_rsp_data(struct hci_request *req, int instance); | ||
69 | |||
70 | int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance, | ||
71 | bool force); | ||
72 | void hci_req_clear_adv_instance(struct hci_dev *hdev, struct hci_request *req, | ||
73 | u8 instance, bool force); | ||
74 | |||
61 | /* Returns true if HCI commands were queued */ | 75 | /* Returns true if HCI commands were queued */ |
62 | bool hci_req_stop_discovery(struct hci_request *req); | 76 | bool hci_req_stop_discovery(struct hci_request *req); |
63 | 77 | ||
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 0d20e1328528..6d0f0025052f 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -841,98 +841,7 @@ static struct mgmt_pending_cmd *pending_find_data(u16 opcode, | |||
841 | return mgmt_pending_find_data(HCI_CHANNEL_CONTROL, opcode, hdev, data); | 841 | return mgmt_pending_find_data(HCI_CHANNEL_CONTROL, opcode, hdev, data); |
842 | } | 842 | } |
843 | 843 | ||
844 | static u8 get_current_adv_instance(struct hci_dev *hdev) | 844 | u8 mgmt_get_adv_discov_flags(struct hci_dev *hdev) |
845 | { | ||
846 | /* The "Set Advertising" setting supersedes the "Add Advertising" | ||
847 | * setting. Here we set the advertising data based on which | ||
848 | * setting was set. When neither apply, default to the global settings, | ||
849 | * represented by instance "0". | ||
850 | */ | ||
851 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) && | ||
852 | !hci_dev_test_flag(hdev, HCI_ADVERTISING)) | ||
853 | return hdev->cur_adv_instance; | ||
854 | |||
855 | return 0x00; | ||
856 | } | ||
857 | |||
858 | static u8 create_default_scan_rsp_data(struct hci_dev *hdev, u8 *ptr) | ||
859 | { | ||
860 | u8 ad_len = 0; | ||
861 | size_t name_len; | ||
862 | |||
863 | name_len = strlen(hdev->dev_name); | ||
864 | if (name_len > 0) { | ||
865 | size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2; | ||
866 | |||
867 | if (name_len > max_len) { | ||
868 | name_len = max_len; | ||
869 | ptr[1] = EIR_NAME_SHORT; | ||
870 | } else | ||
871 | ptr[1] = EIR_NAME_COMPLETE; | ||
872 | |||
873 | ptr[0] = name_len + 1; | ||
874 | |||
875 | memcpy(ptr + 2, hdev->dev_name, name_len); | ||
876 | |||
877 | ad_len += (name_len + 2); | ||
878 | ptr += (name_len + 2); | ||
879 | } | ||
880 | |||
881 | return ad_len; | ||
882 | } | ||
883 | |||
884 | static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 instance, | ||
885 | u8 *ptr) | ||
886 | { | ||
887 | struct adv_info *adv_instance; | ||
888 | |||
889 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
890 | if (!adv_instance) | ||
891 | return 0; | ||
892 | |||
893 | /* TODO: Set the appropriate entries based on advertising instance flags | ||
894 | * here once flags other than 0 are supported. | ||
895 | */ | ||
896 | memcpy(ptr, adv_instance->scan_rsp_data, | ||
897 | adv_instance->scan_rsp_len); | ||
898 | |||
899 | return adv_instance->scan_rsp_len; | ||
900 | } | ||
901 | |||
902 | static void update_inst_scan_rsp_data(struct hci_request *req, u8 instance) | ||
903 | { | ||
904 | struct hci_dev *hdev = req->hdev; | ||
905 | struct hci_cp_le_set_scan_rsp_data cp; | ||
906 | u8 len; | ||
907 | |||
908 | if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) | ||
909 | return; | ||
910 | |||
911 | memset(&cp, 0, sizeof(cp)); | ||
912 | |||
913 | if (instance) | ||
914 | len = create_instance_scan_rsp_data(hdev, instance, cp.data); | ||
915 | else | ||
916 | len = create_default_scan_rsp_data(hdev, cp.data); | ||
917 | |||
918 | if (hdev->scan_rsp_data_len == len && | ||
919 | !memcmp(cp.data, hdev->scan_rsp_data, len)) | ||
920 | return; | ||
921 | |||
922 | memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data)); | ||
923 | hdev->scan_rsp_data_len = len; | ||
924 | |||
925 | cp.length = len; | ||
926 | |||
927 | hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp); | ||
928 | } | ||
929 | |||
930 | static void update_scan_rsp_data(struct hci_request *req) | ||
931 | { | ||
932 | update_inst_scan_rsp_data(req, get_current_adv_instance(req->hdev)); | ||
933 | } | ||
934 | |||
935 | static u8 get_adv_discov_flags(struct hci_dev *hdev) | ||
936 | { | 845 | { |
937 | struct mgmt_pending_cmd *cmd; | 846 | struct mgmt_pending_cmd *cmd; |
938 | 847 | ||
@@ -956,7 +865,7 @@ static u8 get_adv_discov_flags(struct hci_dev *hdev) | |||
956 | return 0; | 865 | return 0; |
957 | } | 866 | } |
958 | 867 | ||
959 | static bool get_connectable(struct hci_dev *hdev) | 868 | bool mgmt_get_connectable(struct hci_dev *hdev) |
960 | { | 869 | { |
961 | struct mgmt_pending_cmd *cmd; | 870 | struct mgmt_pending_cmd *cmd; |
962 | 871 | ||
@@ -973,163 +882,6 @@ static bool get_connectable(struct hci_dev *hdev) | |||
973 | return hci_dev_test_flag(hdev, HCI_CONNECTABLE); | 882 | return hci_dev_test_flag(hdev, HCI_CONNECTABLE); |
974 | } | 883 | } |
975 | 884 | ||
976 | static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance) | ||
977 | { | ||
978 | u32 flags; | ||
979 | struct adv_info *adv_instance; | ||
980 | |||
981 | if (instance == 0x00) { | ||
982 | /* Instance 0 always manages the "Tx Power" and "Flags" | ||
983 | * fields | ||
984 | */ | ||
985 | flags = MGMT_ADV_FLAG_TX_POWER | MGMT_ADV_FLAG_MANAGED_FLAGS; | ||
986 | |||
987 | /* For instance 0, the HCI_ADVERTISING_CONNECTABLE setting | ||
988 | * corresponds to the "connectable" instance flag. | ||
989 | */ | ||
990 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) | ||
991 | flags |= MGMT_ADV_FLAG_CONNECTABLE; | ||
992 | |||
993 | return flags; | ||
994 | } | ||
995 | |||
996 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
997 | |||
998 | /* Return 0 when we got an invalid instance identifier. */ | ||
999 | if (!adv_instance) | ||
1000 | return 0; | ||
1001 | |||
1002 | return adv_instance->flags; | ||
1003 | } | ||
1004 | |||
1005 | static u8 get_cur_adv_instance_scan_rsp_len(struct hci_dev *hdev) | ||
1006 | { | ||
1007 | u8 instance = get_current_adv_instance(hdev); | ||
1008 | struct adv_info *adv_instance; | ||
1009 | |||
1010 | /* Ignore instance 0 */ | ||
1011 | if (instance == 0x00) | ||
1012 | return 0; | ||
1013 | |||
1014 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
1015 | if (!adv_instance) | ||
1016 | return 0; | ||
1017 | |||
1018 | /* TODO: Take into account the "appearance" and "local-name" flags here. | ||
1019 | * These are currently being ignored as they are not supported. | ||
1020 | */ | ||
1021 | return adv_instance->scan_rsp_len; | ||
1022 | } | ||
1023 | |||
1024 | static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr) | ||
1025 | { | ||
1026 | struct adv_info *adv_instance = NULL; | ||
1027 | u8 ad_len = 0, flags = 0; | ||
1028 | u32 instance_flags; | ||
1029 | |||
1030 | /* Return 0 when the current instance identifier is invalid. */ | ||
1031 | if (instance) { | ||
1032 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
1033 | if (!adv_instance) | ||
1034 | return 0; | ||
1035 | } | ||
1036 | |||
1037 | instance_flags = get_adv_instance_flags(hdev, instance); | ||
1038 | |||
1039 | /* The Add Advertising command allows userspace to set both the general | ||
1040 | * and limited discoverable flags. | ||
1041 | */ | ||
1042 | if (instance_flags & MGMT_ADV_FLAG_DISCOV) | ||
1043 | flags |= LE_AD_GENERAL; | ||
1044 | |||
1045 | if (instance_flags & MGMT_ADV_FLAG_LIMITED_DISCOV) | ||
1046 | flags |= LE_AD_LIMITED; | ||
1047 | |||
1048 | if (flags || (instance_flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) { | ||
1049 | /* If a discovery flag wasn't provided, simply use the global | ||
1050 | * settings. | ||
1051 | */ | ||
1052 | if (!flags) | ||
1053 | flags |= get_adv_discov_flags(hdev); | ||
1054 | |||
1055 | if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) | ||
1056 | flags |= LE_AD_NO_BREDR; | ||
1057 | |||
1058 | /* If flags would still be empty, then there is no need to | ||
1059 | * include the "Flags" AD field". | ||
1060 | */ | ||
1061 | if (flags) { | ||
1062 | ptr[0] = 0x02; | ||
1063 | ptr[1] = EIR_FLAGS; | ||
1064 | ptr[2] = flags; | ||
1065 | |||
1066 | ad_len += 3; | ||
1067 | ptr += 3; | ||
1068 | } | ||
1069 | } | ||
1070 | |||
1071 | if (adv_instance) { | ||
1072 | memcpy(ptr, adv_instance->adv_data, | ||
1073 | adv_instance->adv_data_len); | ||
1074 | ad_len += adv_instance->adv_data_len; | ||
1075 | ptr += adv_instance->adv_data_len; | ||
1076 | } | ||
1077 | |||
1078 | /* Provide Tx Power only if we can provide a valid value for it */ | ||
1079 | if (hdev->adv_tx_power != HCI_TX_POWER_INVALID && | ||
1080 | (instance_flags & MGMT_ADV_FLAG_TX_POWER)) { | ||
1081 | ptr[0] = 0x02; | ||
1082 | ptr[1] = EIR_TX_POWER; | ||
1083 | ptr[2] = (u8)hdev->adv_tx_power; | ||
1084 | |||
1085 | ad_len += 3; | ||
1086 | ptr += 3; | ||
1087 | } | ||
1088 | |||
1089 | return ad_len; | ||
1090 | } | ||
1091 | |||
1092 | static void update_inst_adv_data(struct hci_request *req, u8 instance) | ||
1093 | { | ||
1094 | struct hci_dev *hdev = req->hdev; | ||
1095 | struct hci_cp_le_set_adv_data cp; | ||
1096 | u8 len; | ||
1097 | |||
1098 | if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) | ||
1099 | return; | ||
1100 | |||
1101 | memset(&cp, 0, sizeof(cp)); | ||
1102 | |||
1103 | len = create_instance_adv_data(hdev, instance, cp.data); | ||
1104 | |||
1105 | /* There's nothing to do if the data hasn't changed */ | ||
1106 | if (hdev->adv_data_len == len && | ||
1107 | memcmp(cp.data, hdev->adv_data, len) == 0) | ||
1108 | return; | ||
1109 | |||
1110 | memcpy(hdev->adv_data, cp.data, sizeof(cp.data)); | ||
1111 | hdev->adv_data_len = len; | ||
1112 | |||
1113 | cp.length = len; | ||
1114 | |||
1115 | hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); | ||
1116 | } | ||
1117 | |||
1118 | static void update_adv_data(struct hci_request *req) | ||
1119 | { | ||
1120 | update_inst_adv_data(req, get_current_adv_instance(req->hdev)); | ||
1121 | } | ||
1122 | |||
1123 | int mgmt_update_adv_data(struct hci_dev *hdev) | ||
1124 | { | ||
1125 | struct hci_request req; | ||
1126 | |||
1127 | hci_req_init(&req, hdev); | ||
1128 | update_adv_data(&req); | ||
1129 | |||
1130 | return hci_req_run(&req, NULL); | ||
1131 | } | ||
1132 | |||
1133 | static void create_eir(struct hci_dev *hdev, u8 *data) | 885 | static void create_eir(struct hci_dev *hdev, u8 *data) |
1134 | { | 886 | { |
1135 | u8 *ptr = data; | 887 | u8 *ptr = data; |
@@ -1247,70 +999,6 @@ static void update_class(struct hci_request *req) | |||
1247 | hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); | 999 | hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); |
1248 | } | 1000 | } |
1249 | 1001 | ||
1250 | static void disable_advertising(struct hci_request *req) | ||
1251 | { | ||
1252 | u8 enable = 0x00; | ||
1253 | |||
1254 | hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); | ||
1255 | } | ||
1256 | |||
1257 | static void enable_advertising(struct hci_request *req) | ||
1258 | { | ||
1259 | struct hci_dev *hdev = req->hdev; | ||
1260 | struct hci_cp_le_set_adv_param cp; | ||
1261 | u8 own_addr_type, enable = 0x01; | ||
1262 | bool connectable; | ||
1263 | u8 instance; | ||
1264 | u32 flags; | ||
1265 | |||
1266 | if (hci_conn_num(hdev, LE_LINK) > 0) | ||
1267 | return; | ||
1268 | |||
1269 | if (hci_dev_test_flag(hdev, HCI_LE_ADV)) | ||
1270 | disable_advertising(req); | ||
1271 | |||
1272 | /* Clear the HCI_LE_ADV bit temporarily so that the | ||
1273 | * hci_update_random_address knows that it's safe to go ahead | ||
1274 | * and write a new random address. The flag will be set back on | ||
1275 | * as soon as the SET_ADV_ENABLE HCI command completes. | ||
1276 | */ | ||
1277 | hci_dev_clear_flag(hdev, HCI_LE_ADV); | ||
1278 | |||
1279 | instance = get_current_adv_instance(hdev); | ||
1280 | flags = get_adv_instance_flags(hdev, instance); | ||
1281 | |||
1282 | /* If the "connectable" instance flag was not set, then choose between | ||
1283 | * ADV_IND and ADV_NONCONN_IND based on the global connectable setting. | ||
1284 | */ | ||
1285 | connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) || | ||
1286 | get_connectable(hdev); | ||
1287 | |||
1288 | /* Set require_privacy to true only when non-connectable | ||
1289 | * advertising is used. In that case it is fine to use a | ||
1290 | * non-resolvable private address. | ||
1291 | */ | ||
1292 | if (hci_update_random_address(req, !connectable, &own_addr_type) < 0) | ||
1293 | return; | ||
1294 | |||
1295 | memset(&cp, 0, sizeof(cp)); | ||
1296 | cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval); | ||
1297 | cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval); | ||
1298 | |||
1299 | if (connectable) | ||
1300 | cp.type = LE_ADV_IND; | ||
1301 | else if (get_cur_adv_instance_scan_rsp_len(hdev)) | ||
1302 | cp.type = LE_ADV_SCAN_IND; | ||
1303 | else | ||
1304 | cp.type = LE_ADV_NONCONN_IND; | ||
1305 | |||
1306 | cp.own_address_type = own_addr_type; | ||
1307 | cp.channel_map = hdev->le_adv_channel_map; | ||
1308 | |||
1309 | hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp); | ||
1310 | |||
1311 | hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); | ||
1312 | } | ||
1313 | |||
1314 | static void service_cache_off(struct work_struct *work) | 1002 | static void service_cache_off(struct work_struct *work) |
1315 | { | 1003 | { |
1316 | struct hci_dev *hdev = container_of(work, struct hci_dev, | 1004 | struct hci_dev *hdev = container_of(work, struct hci_dev, |
@@ -1346,10 +1034,11 @@ static void rpa_expired(struct work_struct *work) | |||
1346 | return; | 1034 | return; |
1347 | 1035 | ||
1348 | /* The generation of a new RPA and programming it into the | 1036 | /* The generation of a new RPA and programming it into the |
1349 | * controller happens in the enable_advertising() function. | 1037 | * controller happens in the hci_req_enable_advertising() |
1038 | * function. | ||
1350 | */ | 1039 | */ |
1351 | hci_req_init(&req, hdev); | 1040 | hci_req_init(&req, hdev); |
1352 | enable_advertising(&req); | 1041 | __hci_req_enable_advertising(&req); |
1353 | hci_req_run(&req, NULL); | 1042 | hci_req_run(&req, NULL); |
1354 | } | 1043 | } |
1355 | 1044 | ||
@@ -1417,8 +1106,7 @@ static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode) | |||
1417 | } | 1106 | } |
1418 | } | 1107 | } |
1419 | 1108 | ||
1420 | static void advertising_added(struct sock *sk, struct hci_dev *hdev, | 1109 | void mgmt_advertising_added(struct sock *sk, struct hci_dev *hdev, u8 instance) |
1421 | u8 instance) | ||
1422 | { | 1110 | { |
1423 | struct mgmt_ev_advertising_added ev; | 1111 | struct mgmt_ev_advertising_added ev; |
1424 | 1112 | ||
@@ -1427,8 +1115,8 @@ static void advertising_added(struct sock *sk, struct hci_dev *hdev, | |||
1427 | mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk); | 1115 | mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk); |
1428 | } | 1116 | } |
1429 | 1117 | ||
1430 | static void advertising_removed(struct sock *sk, struct hci_dev *hdev, | 1118 | void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev, |
1431 | u8 instance) | 1119 | u8 instance) |
1432 | { | 1120 | { |
1433 | struct mgmt_ev_advertising_removed ev; | 1121 | struct mgmt_ev_advertising_removed ev; |
1434 | 1122 | ||
@@ -1437,65 +1125,6 @@ static void advertising_removed(struct sock *sk, struct hci_dev *hdev, | |||
1437 | mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk); | 1125 | mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk); |
1438 | } | 1126 | } |
1439 | 1127 | ||
1440 | static int schedule_adv_instance(struct hci_request *req, u8 instance, | ||
1441 | bool force) { | ||
1442 | struct hci_dev *hdev = req->hdev; | ||
1443 | struct adv_info *adv_instance = NULL; | ||
1444 | u16 timeout; | ||
1445 | |||
1446 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING) || | ||
1447 | !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) | ||
1448 | return -EPERM; | ||
1449 | |||
1450 | if (hdev->adv_instance_timeout) | ||
1451 | return -EBUSY; | ||
1452 | |||
1453 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
1454 | if (!adv_instance) | ||
1455 | return -ENOENT; | ||
1456 | |||
1457 | /* A zero timeout means unlimited advertising. As long as there is | ||
1458 | * only one instance, duration should be ignored. We still set a timeout | ||
1459 | * in case further instances are being added later on. | ||
1460 | * | ||
1461 | * If the remaining lifetime of the instance is more than the duration | ||
1462 | * then the timeout corresponds to the duration, otherwise it will be | ||
1463 | * reduced to the remaining instance lifetime. | ||
1464 | */ | ||
1465 | if (adv_instance->timeout == 0 || | ||
1466 | adv_instance->duration <= adv_instance->remaining_time) | ||
1467 | timeout = adv_instance->duration; | ||
1468 | else | ||
1469 | timeout = adv_instance->remaining_time; | ||
1470 | |||
1471 | /* The remaining time is being reduced unless the instance is being | ||
1472 | * advertised without time limit. | ||
1473 | */ | ||
1474 | if (adv_instance->timeout) | ||
1475 | adv_instance->remaining_time = | ||
1476 | adv_instance->remaining_time - timeout; | ||
1477 | |||
1478 | hdev->adv_instance_timeout = timeout; | ||
1479 | queue_delayed_work(hdev->workqueue, | ||
1480 | &hdev->adv_instance_expire, | ||
1481 | msecs_to_jiffies(timeout * 1000)); | ||
1482 | |||
1483 | /* If we're just re-scheduling the same instance again then do not | ||
1484 | * execute any HCI commands. This happens when a single instance is | ||
1485 | * being advertised. | ||
1486 | */ | ||
1487 | if (!force && hdev->cur_adv_instance == instance && | ||
1488 | hci_dev_test_flag(hdev, HCI_LE_ADV)) | ||
1489 | return 0; | ||
1490 | |||
1491 | hdev->cur_adv_instance = instance; | ||
1492 | update_adv_data(req); | ||
1493 | update_scan_rsp_data(req); | ||
1494 | enable_advertising(req); | ||
1495 | |||
1496 | return 0; | ||
1497 | } | ||
1498 | |||
1499 | static void cancel_adv_timeout(struct hci_dev *hdev) | 1128 | static void cancel_adv_timeout(struct hci_dev *hdev) |
1500 | { | 1129 | { |
1501 | if (hdev->adv_instance_timeout) { | 1130 | if (hdev->adv_instance_timeout) { |
@@ -1504,76 +1133,6 @@ static void cancel_adv_timeout(struct hci_dev *hdev) | |||
1504 | } | 1133 | } |
1505 | } | 1134 | } |
1506 | 1135 | ||
1507 | /* For a single instance: | ||
1508 | * - force == true: The instance will be removed even when its remaining | ||
1509 | * lifetime is not zero. | ||
1510 | * - force == false: the instance will be deactivated but kept stored unless | ||
1511 | * the remaining lifetime is zero. | ||
1512 | * | ||
1513 | * For instance == 0x00: | ||
1514 | * - force == true: All instances will be removed regardless of their timeout | ||
1515 | * setting. | ||
1516 | * - force == false: Only instances that have a timeout will be removed. | ||
1517 | */ | ||
1518 | static void clear_adv_instance(struct hci_dev *hdev, struct hci_request *req, | ||
1519 | u8 instance, bool force) | ||
1520 | { | ||
1521 | struct adv_info *adv_instance, *n, *next_instance = NULL; | ||
1522 | int err; | ||
1523 | u8 rem_inst; | ||
1524 | |||
1525 | /* Cancel any timeout concerning the removed instance(s). */ | ||
1526 | if (!instance || hdev->cur_adv_instance == instance) | ||
1527 | cancel_adv_timeout(hdev); | ||
1528 | |||
1529 | /* Get the next instance to advertise BEFORE we remove | ||
1530 | * the current one. This can be the same instance again | ||
1531 | * if there is only one instance. | ||
1532 | */ | ||
1533 | if (instance && hdev->cur_adv_instance == instance) | ||
1534 | next_instance = hci_get_next_instance(hdev, instance); | ||
1535 | |||
1536 | if (instance == 0x00) { | ||
1537 | list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances, | ||
1538 | list) { | ||
1539 | if (!(force || adv_instance->timeout)) | ||
1540 | continue; | ||
1541 | |||
1542 | rem_inst = adv_instance->instance; | ||
1543 | err = hci_remove_adv_instance(hdev, rem_inst); | ||
1544 | if (!err) | ||
1545 | advertising_removed(NULL, hdev, rem_inst); | ||
1546 | } | ||
1547 | hdev->cur_adv_instance = 0x00; | ||
1548 | } else { | ||
1549 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
1550 | |||
1551 | if (force || (adv_instance && adv_instance->timeout && | ||
1552 | !adv_instance->remaining_time)) { | ||
1553 | /* Don't advertise a removed instance. */ | ||
1554 | if (next_instance && | ||
1555 | next_instance->instance == instance) | ||
1556 | next_instance = NULL; | ||
1557 | |||
1558 | err = hci_remove_adv_instance(hdev, instance); | ||
1559 | if (!err) | ||
1560 | advertising_removed(NULL, hdev, instance); | ||
1561 | } | ||
1562 | } | ||
1563 | |||
1564 | if (list_empty(&hdev->adv_instances)) { | ||
1565 | hdev->cur_adv_instance = 0x00; | ||
1566 | hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE); | ||
1567 | } | ||
1568 | |||
1569 | if (!req || !hdev_is_powered(hdev) || | ||
1570 | hci_dev_test_flag(hdev, HCI_ADVERTISING)) | ||
1571 | return; | ||
1572 | |||
1573 | if (next_instance) | ||
1574 | schedule_adv_instance(req, next_instance->instance, false); | ||
1575 | } | ||
1576 | |||
1577 | static int clean_up_hci_state(struct hci_dev *hdev) | 1136 | static int clean_up_hci_state(struct hci_dev *hdev) |
1578 | { | 1137 | { |
1579 | struct hci_request req; | 1138 | struct hci_request req; |
@@ -1589,10 +1148,10 @@ static int clean_up_hci_state(struct hci_dev *hdev) | |||
1589 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | 1148 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); |
1590 | } | 1149 | } |
1591 | 1150 | ||
1592 | clear_adv_instance(hdev, NULL, 0x00, false); | 1151 | hci_req_clear_adv_instance(hdev, NULL, 0x00, false); |
1593 | 1152 | ||
1594 | if (hci_dev_test_flag(hdev, HCI_LE_ADV)) | 1153 | if (hci_dev_test_flag(hdev, HCI_LE_ADV)) |
1595 | disable_advertising(&req); | 1154 | __hci_req_disable_advertising(&req); |
1596 | 1155 | ||
1597 | discov_stopped = hci_req_stop_discovery(&req); | 1156 | discov_stopped = hci_req_stop_discovery(&req); |
1598 | 1157 | ||
@@ -1975,7 +1534,7 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1975 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan); | 1534 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan); |
1976 | 1535 | ||
1977 | update_ad: | 1536 | update_ad: |
1978 | update_adv_data(&req); | 1537 | __hci_req_update_adv_data(&req, HCI_ADV_CURRENT); |
1979 | 1538 | ||
1980 | err = hci_req_run(&req, set_discoverable_complete); | 1539 | err = hci_req_run(&req, set_discoverable_complete); |
1981 | if (err < 0) | 1540 | if (err < 0) |
@@ -2060,7 +1619,7 @@ static void set_connectable_complete(struct hci_dev *hdev, u8 status, | |||
2060 | new_settings(hdev, cmd->sk); | 1619 | new_settings(hdev, cmd->sk); |
2061 | hci_req_update_scan(hdev); | 1620 | hci_req_update_scan(hdev); |
2062 | if (discov_changed) | 1621 | if (discov_changed) |
2063 | mgmt_update_adv_data(hdev); | 1622 | hci_req_update_adv_data(hdev, HCI_ADV_CURRENT); |
2064 | hci_update_background_scan(hdev); | 1623 | hci_update_background_scan(hdev); |
2065 | } | 1624 | } |
2066 | 1625 | ||
@@ -2151,7 +1710,7 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2151 | hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE); | 1710 | hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE); |
2152 | hci_dev_clear_flag(hdev, HCI_DISCOVERABLE); | 1711 | hci_dev_clear_flag(hdev, HCI_DISCOVERABLE); |
2153 | } | 1712 | } |
2154 | update_adv_data(&req); | 1713 | __hci_req_update_adv_data(&req, HCI_ADV_CURRENT); |
2155 | } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) { | 1714 | } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) { |
2156 | if (cp->val) { | 1715 | if (cp->val) { |
2157 | scan = SCAN_PAGE; | 1716 | scan = SCAN_PAGE; |
@@ -2181,7 +1740,7 @@ no_scan_update: | |||
2181 | /* Update the advertising parameters if necessary */ | 1740 | /* Update the advertising parameters if necessary */ |
2182 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING) || | 1741 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING) || |
2183 | hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) | 1742 | hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) |
2184 | enable_advertising(&req); | 1743 | __hci_req_enable_advertising(&req); |
2185 | 1744 | ||
2186 | err = hci_req_run(&req, set_connectable_complete); | 1745 | err = hci_req_run(&req, set_connectable_complete); |
2187 | if (err < 0) { | 1746 | if (err < 0) { |
@@ -2466,8 +2025,8 @@ static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode) | |||
2466 | struct hci_request req; | 2025 | struct hci_request req; |
2467 | 2026 | ||
2468 | hci_req_init(&req, hdev); | 2027 | hci_req_init(&req, hdev); |
2469 | update_adv_data(&req); | 2028 | __hci_req_update_adv_data(&req, HCI_ADV_CURRENT); |
2470 | update_scan_rsp_data(&req); | 2029 | __hci_req_update_scan_rsp_data(&req, HCI_ADV_CURRENT); |
2471 | hci_req_run(&req, NULL); | 2030 | hci_req_run(&req, NULL); |
2472 | hci_update_background_scan(hdev); | 2031 | hci_update_background_scan(hdev); |
2473 | } | 2032 | } |
@@ -2518,7 +2077,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
2518 | enabled = lmp_host_le_capable(hdev); | 2077 | enabled = lmp_host_le_capable(hdev); |
2519 | 2078 | ||
2520 | if (!val) | 2079 | if (!val) |
2521 | clear_adv_instance(hdev, NULL, 0x00, true); | 2080 | hci_req_clear_adv_instance(hdev, NULL, 0x00, true); |
2522 | 2081 | ||
2523 | if (!hdev_is_powered(hdev) || val == enabled) { | 2082 | if (!hdev_is_powered(hdev) || val == enabled) { |
2524 | bool changed = false; | 2083 | bool changed = false; |
@@ -2565,7 +2124,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
2565 | hci_cp.simul = 0x00; | 2124 | hci_cp.simul = 0x00; |
2566 | } else { | 2125 | } else { |
2567 | if (hci_dev_test_flag(hdev, HCI_LE_ADV)) | 2126 | if (hci_dev_test_flag(hdev, HCI_LE_ADV)) |
2568 | disable_advertising(&req); | 2127 | __hci_req_disable_advertising(&req); |
2569 | } | 2128 | } |
2570 | 2129 | ||
2571 | hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), | 2130 | hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), |
@@ -3856,7 +3415,7 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, | |||
3856 | * no need to udpate the advertising data here. | 3415 | * no need to udpate the advertising data here. |
3857 | */ | 3416 | */ |
3858 | if (lmp_le_capable(hdev)) | 3417 | if (lmp_le_capable(hdev)) |
3859 | update_scan_rsp_data(&req); | 3418 | __hci_req_update_scan_rsp_data(&req, HCI_ADV_CURRENT); |
3860 | 3419 | ||
3861 | err = hci_req_run(&req, set_name_complete); | 3420 | err = hci_req_run(&req, set_name_complete); |
3862 | if (err < 0) | 3421 | if (err < 0) |
@@ -4600,7 +4159,7 @@ static void set_advertising_complete(struct hci_dev *hdev, u8 status, | |||
4600 | 4159 | ||
4601 | hci_req_init(&req, hdev); | 4160 | hci_req_init(&req, hdev); |
4602 | 4161 | ||
4603 | err = schedule_adv_instance(&req, instance, true); | 4162 | err = __hci_req_schedule_adv_instance(&req, instance, true); |
4604 | 4163 | ||
4605 | if (!err) | 4164 | if (!err) |
4606 | err = hci_req_run(&req, enable_advertising_instance); | 4165 | err = hci_req_run(&req, enable_advertising_instance); |
@@ -4697,11 +4256,11 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, | |||
4697 | * We cannot use update_[adv|scan_rsp]_data() here as the | 4256 | * We cannot use update_[adv|scan_rsp]_data() here as the |
4698 | * HCI_ADVERTISING flag is not yet set. | 4257 | * HCI_ADVERTISING flag is not yet set. |
4699 | */ | 4258 | */ |
4700 | update_inst_adv_data(&req, 0x00); | 4259 | __hci_req_update_adv_data(&req, 0x00); |
4701 | update_inst_scan_rsp_data(&req, 0x00); | 4260 | __hci_req_update_scan_rsp_data(&req, 0x00); |
4702 | enable_advertising(&req); | 4261 | __hci_req_enable_advertising(&req); |
4703 | } else { | 4262 | } else { |
4704 | disable_advertising(&req); | 4263 | __hci_req_disable_advertising(&req); |
4705 | } | 4264 | } |
4706 | 4265 | ||
4707 | err = hci_req_run(&req, set_advertising_complete); | 4266 | err = hci_req_run(&req, set_advertising_complete); |
@@ -5033,8 +4592,8 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
5033 | goto unlock; | 4592 | goto unlock; |
5034 | } | 4593 | } |
5035 | 4594 | ||
5036 | /* We need to flip the bit already here so that update_adv_data | 4595 | /* We need to flip the bit already here so that |
5037 | * generates the correct flags. | 4596 | * hci_req_update_adv_data generates the correct flags. |
5038 | */ | 4597 | */ |
5039 | hci_dev_set_flag(hdev, HCI_BREDR_ENABLED); | 4598 | hci_dev_set_flag(hdev, HCI_BREDR_ENABLED); |
5040 | 4599 | ||
@@ -5046,7 +4605,7 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
5046 | /* Since only the advertising data flags will change, there | 4605 | /* Since only the advertising data flags will change, there |
5047 | * is no need to update the scan response data. | 4606 | * is no need to update the scan response data. |
5048 | */ | 4607 | */ |
5049 | update_adv_data(&req); | 4608 | __hci_req_update_adv_data(&req, HCI_ADV_CURRENT); |
5050 | 4609 | ||
5051 | err = hci_req_run(&req, set_bredr_complete); | 4610 | err = hci_req_run(&req, set_bredr_complete); |
5052 | if (err < 0) | 4611 | if (err < 0) |
@@ -6583,7 +6142,7 @@ static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev, | |||
6583 | rand, sizeof(rand)); | 6142 | rand, sizeof(rand)); |
6584 | } | 6143 | } |
6585 | 6144 | ||
6586 | flags = get_adv_discov_flags(hdev); | 6145 | flags = mgmt_get_adv_discov_flags(hdev); |
6587 | 6146 | ||
6588 | if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) | 6147 | if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) |
6589 | flags |= LE_AD_NO_BREDR; | 6148 | flags |= LE_AD_NO_BREDR; |
@@ -6772,7 +6331,7 @@ static void add_advertising_complete(struct hci_dev *hdev, u8 status, | |||
6772 | cancel_adv_timeout(hdev); | 6331 | cancel_adv_timeout(hdev); |
6773 | 6332 | ||
6774 | hci_remove_adv_instance(hdev, instance); | 6333 | hci_remove_adv_instance(hdev, instance); |
6775 | advertising_removed(cmd ? cmd->sk : NULL, hdev, instance); | 6334 | mgmt_advertising_removed(cmd ? cmd->sk : NULL, hdev, instance); |
6776 | } | 6335 | } |
6777 | 6336 | ||
6778 | if (!cmd) | 6337 | if (!cmd) |
@@ -6794,31 +6353,6 @@ unlock: | |||
6794 | hci_dev_unlock(hdev); | 6353 | hci_dev_unlock(hdev); |
6795 | } | 6354 | } |
6796 | 6355 | ||
6797 | void mgmt_adv_timeout_expired(struct hci_dev *hdev) | ||
6798 | { | ||
6799 | u8 instance; | ||
6800 | struct hci_request req; | ||
6801 | |||
6802 | hdev->adv_instance_timeout = 0; | ||
6803 | |||
6804 | instance = get_current_adv_instance(hdev); | ||
6805 | if (instance == 0x00) | ||
6806 | return; | ||
6807 | |||
6808 | hci_dev_lock(hdev); | ||
6809 | hci_req_init(&req, hdev); | ||
6810 | |||
6811 | clear_adv_instance(hdev, &req, instance, false); | ||
6812 | |||
6813 | if (list_empty(&hdev->adv_instances)) | ||
6814 | disable_advertising(&req); | ||
6815 | |||
6816 | if (!skb_queue_empty(&req.cmd_q)) | ||
6817 | hci_req_run(&req, NULL); | ||
6818 | |||
6819 | hci_dev_unlock(hdev); | ||
6820 | } | ||
6821 | |||
6822 | static int add_advertising(struct sock *sk, struct hci_dev *hdev, | 6356 | static int add_advertising(struct sock *sk, struct hci_dev *hdev, |
6823 | void *data, u16 data_len) | 6357 | void *data, u16 data_len) |
6824 | { | 6358 | { |
@@ -6897,7 +6431,7 @@ static int add_advertising(struct sock *sk, struct hci_dev *hdev, | |||
6897 | * actually added. | 6431 | * actually added. |
6898 | */ | 6432 | */ |
6899 | if (hdev->adv_instance_cnt > prev_instance_cnt) | 6433 | if (hdev->adv_instance_cnt > prev_instance_cnt) |
6900 | advertising_added(sk, hdev, cp->instance); | 6434 | mgmt_advertising_added(sk, hdev, cp->instance); |
6901 | 6435 | ||
6902 | hci_dev_set_flag(hdev, HCI_ADVERTISING_INSTANCE); | 6436 | hci_dev_set_flag(hdev, HCI_ADVERTISING_INSTANCE); |
6903 | 6437 | ||
@@ -6944,7 +6478,7 @@ static int add_advertising(struct sock *sk, struct hci_dev *hdev, | |||
6944 | 6478 | ||
6945 | hci_req_init(&req, hdev); | 6479 | hci_req_init(&req, hdev); |
6946 | 6480 | ||
6947 | err = schedule_adv_instance(&req, schedule_instance, true); | 6481 | err = __hci_req_schedule_adv_instance(&req, schedule_instance, true); |
6948 | 6482 | ||
6949 | if (!err) | 6483 | if (!err) |
6950 | err = hci_req_run(&req, add_advertising_complete); | 6484 | err = hci_req_run(&req, add_advertising_complete); |
@@ -7024,10 +6558,10 @@ static int remove_advertising(struct sock *sk, struct hci_dev *hdev, | |||
7024 | 6558 | ||
7025 | hci_req_init(&req, hdev); | 6559 | hci_req_init(&req, hdev); |
7026 | 6560 | ||
7027 | clear_adv_instance(hdev, &req, cp->instance, true); | 6561 | hci_req_clear_adv_instance(hdev, &req, cp->instance, true); |
7028 | 6562 | ||
7029 | if (list_empty(&hdev->adv_instances)) | 6563 | if (list_empty(&hdev->adv_instances)) |
7030 | disable_advertising(&req); | 6564 | __hci_req_disable_advertising(&req); |
7031 | 6565 | ||
7032 | /* If no HCI commands have been collected so far or the HCI_ADVERTISING | 6566 | /* If no HCI commands have been collected so far or the HCI_ADVERTISING |
7033 | * flag is set or the device isn't powered then we have no HCI | 6567 | * flag is set or the device isn't powered then we have no HCI |
@@ -7367,8 +6901,8 @@ static int powered_update_hci(struct hci_dev *hdev) | |||
7367 | if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) && | 6901 | if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) && |
7368 | (hci_dev_test_flag(hdev, HCI_ADVERTISING) || | 6902 | (hci_dev_test_flag(hdev, HCI_ADVERTISING) || |
7369 | !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))) { | 6903 | !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))) { |
7370 | update_adv_data(&req); | 6904 | __hci_req_update_adv_data(&req, HCI_ADV_CURRENT); |
7371 | update_scan_rsp_data(&req); | 6905 | __hci_req_update_scan_rsp_data(&req, HCI_ADV_CURRENT); |
7372 | } | 6906 | } |
7373 | 6907 | ||
7374 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) && | 6908 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) && |
@@ -7380,11 +6914,12 @@ static int powered_update_hci(struct hci_dev *hdev) | |||
7380 | } | 6914 | } |
7381 | 6915 | ||
7382 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) | 6916 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) |
7383 | enable_advertising(&req); | 6917 | __hci_req_enable_advertising(&req); |
7384 | else if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) && | 6918 | else if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) && |
7385 | hdev->cur_adv_instance) | 6919 | hdev->cur_adv_instance) |
7386 | schedule_adv_instance(&req, hdev->cur_adv_instance, | 6920 | __hci_req_schedule_adv_instance(&req, |
7387 | true); | 6921 | hdev->cur_adv_instance, |
6922 | true); | ||
7388 | } | 6923 | } |
7389 | 6924 | ||
7390 | link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY); | 6925 | link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY); |
@@ -7505,7 +7040,7 @@ void mgmt_discoverable_timeout(struct hci_dev *hdev) | |||
7505 | * only update AD if advertising was enabled using Set Advertising. | 7040 | * only update AD if advertising was enabled using Set Advertising. |
7506 | */ | 7041 | */ |
7507 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) | 7042 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) |
7508 | update_adv_data(&req); | 7043 | __hci_req_update_adv_data(&req, HCI_ADV_CURRENT); |
7509 | 7044 | ||
7510 | hci_req_run(&req, NULL); | 7045 | hci_req_run(&req, NULL); |
7511 | 7046 | ||
@@ -8352,35 +7887,6 @@ void mgmt_discovering(struct hci_dev *hdev, u8 discovering) | |||
8352 | mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL); | 7887 | mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL); |
8353 | } | 7888 | } |
8354 | 7889 | ||
8355 | static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode) | ||
8356 | { | ||
8357 | BT_DBG("%s status %u", hdev->name, status); | ||
8358 | } | ||
8359 | |||
8360 | void mgmt_reenable_advertising(struct hci_dev *hdev) | ||
8361 | { | ||
8362 | struct hci_request req; | ||
8363 | u8 instance; | ||
8364 | |||
8365 | if (!hci_dev_test_flag(hdev, HCI_ADVERTISING) && | ||
8366 | !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) | ||
8367 | return; | ||
8368 | |||
8369 | instance = get_current_adv_instance(hdev); | ||
8370 | |||
8371 | hci_req_init(&req, hdev); | ||
8372 | |||
8373 | if (instance) { | ||
8374 | schedule_adv_instance(&req, instance, true); | ||
8375 | } else { | ||
8376 | update_adv_data(&req); | ||
8377 | update_scan_rsp_data(&req); | ||
8378 | enable_advertising(&req); | ||
8379 | } | ||
8380 | |||
8381 | hci_req_run(&req, adv_enable_complete); | ||
8382 | } | ||
8383 | |||
8384 | static struct hci_mgmt_chan chan = { | 7890 | static struct hci_mgmt_chan chan = { |
8385 | .channel = HCI_CHANNEL_CONTROL, | 7891 | .channel = HCI_CHANNEL_CONTROL, |
8386 | .handler_count = ARRAY_SIZE(mgmt_handlers), | 7892 | .handler_count = ARRAY_SIZE(mgmt_handlers), |