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/hci_request.c | |
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/hci_request.c')
-rw-r--r-- | net/bluetooth/hci_request.c | 533 |
1 files changed, 525 insertions, 8 deletions
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 | } |