diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2015-11-25 09:15:42 -0500 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2015-12-09 18:51:48 -0500 |
commit | b1a8917c9bcbf42113dfacb6492228e094c96862 (patch) | |
tree | 30fbfaacbca3bc8775596c2107fa76cbe0cb8827 /net/bluetooth/mgmt.c | |
parent | 00cf5040b39638588cd10ae4ffcc76a1be6ecf2c (diff) |
Bluetooth: Move EIR update to hci_request.c
We'll soon need to update the EIR both from hci_request.c and mgmt.c
so move update_eir() as a more generic request helper to
hci_request.c.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r-- | net/bluetooth/mgmt.c | 203 |
1 files changed, 8 insertions, 195 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 001a29a320e6..fa5dc67a800a 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -719,116 +719,6 @@ static u32 get_current_settings(struct hci_dev *hdev) | |||
719 | return settings; | 719 | return settings; |
720 | } | 720 | } |
721 | 721 | ||
722 | #define PNP_INFO_SVCLASS_ID 0x1200 | ||
723 | |||
724 | static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len) | ||
725 | { | ||
726 | u8 *ptr = data, *uuids_start = NULL; | ||
727 | struct bt_uuid *uuid; | ||
728 | |||
729 | if (len < 4) | ||
730 | return ptr; | ||
731 | |||
732 | list_for_each_entry(uuid, &hdev->uuids, list) { | ||
733 | u16 uuid16; | ||
734 | |||
735 | if (uuid->size != 16) | ||
736 | continue; | ||
737 | |||
738 | uuid16 = get_unaligned_le16(&uuid->uuid[12]); | ||
739 | if (uuid16 < 0x1100) | ||
740 | continue; | ||
741 | |||
742 | if (uuid16 == PNP_INFO_SVCLASS_ID) | ||
743 | continue; | ||
744 | |||
745 | if (!uuids_start) { | ||
746 | uuids_start = ptr; | ||
747 | uuids_start[0] = 1; | ||
748 | uuids_start[1] = EIR_UUID16_ALL; | ||
749 | ptr += 2; | ||
750 | } | ||
751 | |||
752 | /* Stop if not enough space to put next UUID */ | ||
753 | if ((ptr - data) + sizeof(u16) > len) { | ||
754 | uuids_start[1] = EIR_UUID16_SOME; | ||
755 | break; | ||
756 | } | ||
757 | |||
758 | *ptr++ = (uuid16 & 0x00ff); | ||
759 | *ptr++ = (uuid16 & 0xff00) >> 8; | ||
760 | uuids_start[0] += sizeof(uuid16); | ||
761 | } | ||
762 | |||
763 | return ptr; | ||
764 | } | ||
765 | |||
766 | static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len) | ||
767 | { | ||
768 | u8 *ptr = data, *uuids_start = NULL; | ||
769 | struct bt_uuid *uuid; | ||
770 | |||
771 | if (len < 6) | ||
772 | return ptr; | ||
773 | |||
774 | list_for_each_entry(uuid, &hdev->uuids, list) { | ||
775 | if (uuid->size != 32) | ||
776 | continue; | ||
777 | |||
778 | if (!uuids_start) { | ||
779 | uuids_start = ptr; | ||
780 | uuids_start[0] = 1; | ||
781 | uuids_start[1] = EIR_UUID32_ALL; | ||
782 | ptr += 2; | ||
783 | } | ||
784 | |||
785 | /* Stop if not enough space to put next UUID */ | ||
786 | if ((ptr - data) + sizeof(u32) > len) { | ||
787 | uuids_start[1] = EIR_UUID32_SOME; | ||
788 | break; | ||
789 | } | ||
790 | |||
791 | memcpy(ptr, &uuid->uuid[12], sizeof(u32)); | ||
792 | ptr += sizeof(u32); | ||
793 | uuids_start[0] += sizeof(u32); | ||
794 | } | ||
795 | |||
796 | return ptr; | ||
797 | } | ||
798 | |||
799 | static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len) | ||
800 | { | ||
801 | u8 *ptr = data, *uuids_start = NULL; | ||
802 | struct bt_uuid *uuid; | ||
803 | |||
804 | if (len < 18) | ||
805 | return ptr; | ||
806 | |||
807 | list_for_each_entry(uuid, &hdev->uuids, list) { | ||
808 | if (uuid->size != 128) | ||
809 | continue; | ||
810 | |||
811 | if (!uuids_start) { | ||
812 | uuids_start = ptr; | ||
813 | uuids_start[0] = 1; | ||
814 | uuids_start[1] = EIR_UUID128_ALL; | ||
815 | ptr += 2; | ||
816 | } | ||
817 | |||
818 | /* Stop if not enough space to put next UUID */ | ||
819 | if ((ptr - data) + 16 > len) { | ||
820 | uuids_start[1] = EIR_UUID128_SOME; | ||
821 | break; | ||
822 | } | ||
823 | |||
824 | memcpy(ptr, uuid->uuid, 16); | ||
825 | ptr += 16; | ||
826 | uuids_start[0] += 16; | ||
827 | } | ||
828 | |||
829 | return ptr; | ||
830 | } | ||
831 | |||
832 | static struct mgmt_pending_cmd *pending_find(u16 opcode, struct hci_dev *hdev) | 722 | static struct mgmt_pending_cmd *pending_find(u16 opcode, struct hci_dev *hdev) |
833 | { | 723 | { |
834 | return mgmt_pending_find(HCI_CHANNEL_CONTROL, opcode, hdev); | 724 | return mgmt_pending_find(HCI_CHANNEL_CONTROL, opcode, hdev); |
@@ -882,83 +772,6 @@ bool mgmt_get_connectable(struct hci_dev *hdev) | |||
882 | return hci_dev_test_flag(hdev, HCI_CONNECTABLE); | 772 | return hci_dev_test_flag(hdev, HCI_CONNECTABLE); |
883 | } | 773 | } |
884 | 774 | ||
885 | static void create_eir(struct hci_dev *hdev, u8 *data) | ||
886 | { | ||
887 | u8 *ptr = data; | ||
888 | size_t name_len; | ||
889 | |||
890 | name_len = strlen(hdev->dev_name); | ||
891 | |||
892 | if (name_len > 0) { | ||
893 | /* EIR Data type */ | ||
894 | if (name_len > 48) { | ||
895 | name_len = 48; | ||
896 | ptr[1] = EIR_NAME_SHORT; | ||
897 | } else | ||
898 | ptr[1] = EIR_NAME_COMPLETE; | ||
899 | |||
900 | /* EIR Data length */ | ||
901 | ptr[0] = name_len + 1; | ||
902 | |||
903 | memcpy(ptr + 2, hdev->dev_name, name_len); | ||
904 | |||
905 | ptr += (name_len + 2); | ||
906 | } | ||
907 | |||
908 | if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) { | ||
909 | ptr[0] = 2; | ||
910 | ptr[1] = EIR_TX_POWER; | ||
911 | ptr[2] = (u8) hdev->inq_tx_power; | ||
912 | |||
913 | ptr += 3; | ||
914 | } | ||
915 | |||
916 | if (hdev->devid_source > 0) { | ||
917 | ptr[0] = 9; | ||
918 | ptr[1] = EIR_DEVICE_ID; | ||
919 | |||
920 | put_unaligned_le16(hdev->devid_source, ptr + 2); | ||
921 | put_unaligned_le16(hdev->devid_vendor, ptr + 4); | ||
922 | put_unaligned_le16(hdev->devid_product, ptr + 6); | ||
923 | put_unaligned_le16(hdev->devid_version, ptr + 8); | ||
924 | |||
925 | ptr += 10; | ||
926 | } | ||
927 | |||
928 | ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); | ||
929 | ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); | ||
930 | ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); | ||
931 | } | ||
932 | |||
933 | static void update_eir(struct hci_request *req) | ||
934 | { | ||
935 | struct hci_dev *hdev = req->hdev; | ||
936 | struct hci_cp_write_eir cp; | ||
937 | |||
938 | if (!hdev_is_powered(hdev)) | ||
939 | return; | ||
940 | |||
941 | if (!lmp_ext_inq_capable(hdev)) | ||
942 | return; | ||
943 | |||
944 | if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) | ||
945 | return; | ||
946 | |||
947 | if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE)) | ||
948 | return; | ||
949 | |||
950 | memset(&cp, 0, sizeof(cp)); | ||
951 | |||
952 | create_eir(hdev, cp.data); | ||
953 | |||
954 | if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0) | ||
955 | return; | ||
956 | |||
957 | memcpy(hdev->eir, cp.data, sizeof(cp.data)); | ||
958 | |||
959 | hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp); | ||
960 | } | ||
961 | |||
962 | static void service_cache_off(struct work_struct *work) | 775 | static void service_cache_off(struct work_struct *work) |
963 | { | 776 | { |
964 | struct hci_dev *hdev = container_of(work, struct hci_dev, | 777 | struct hci_dev *hdev = container_of(work, struct hci_dev, |
@@ -972,7 +785,7 @@ static void service_cache_off(struct work_struct *work) | |||
972 | 785 | ||
973 | hci_dev_lock(hdev); | 786 | hci_dev_lock(hdev); |
974 | 787 | ||
975 | update_eir(&req); | 788 | __hci_req_update_eir(&req); |
976 | __hci_req_update_class(&req); | 789 | __hci_req_update_class(&req); |
977 | 790 | ||
978 | hci_dev_unlock(hdev); | 791 | hci_dev_unlock(hdev); |
@@ -2074,7 +1887,7 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
2074 | hci_req_init(&req, hdev); | 1887 | hci_req_init(&req, hdev); |
2075 | 1888 | ||
2076 | __hci_req_update_class(&req); | 1889 | __hci_req_update_class(&req); |
2077 | update_eir(&req); | 1890 | __hci_req_update_eir(&req); |
2078 | 1891 | ||
2079 | err = hci_req_run(&req, add_uuid_complete); | 1892 | err = hci_req_run(&req, add_uuid_complete); |
2080 | if (err < 0) { | 1893 | if (err < 0) { |
@@ -2174,7 +1987,7 @@ update_class: | |||
2174 | hci_req_init(&req, hdev); | 1987 | hci_req_init(&req, hdev); |
2175 | 1988 | ||
2176 | __hci_req_update_class(&req); | 1989 | __hci_req_update_class(&req); |
2177 | update_eir(&req); | 1990 | __hci_req_update_eir(&req); |
2178 | 1991 | ||
2179 | err = hci_req_run(&req, remove_uuid_complete); | 1992 | err = hci_req_run(&req, remove_uuid_complete); |
2180 | if (err < 0) { | 1993 | if (err < 0) { |
@@ -2249,7 +2062,7 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2249 | hci_dev_unlock(hdev); | 2062 | hci_dev_unlock(hdev); |
2250 | cancel_delayed_work_sync(&hdev->service_cache); | 2063 | cancel_delayed_work_sync(&hdev->service_cache); |
2251 | hci_dev_lock(hdev); | 2064 | hci_dev_lock(hdev); |
2252 | update_eir(&req); | 2065 | __hci_req_update_eir(&req); |
2253 | } | 2066 | } |
2254 | 2067 | ||
2255 | __hci_req_update_class(&req); | 2068 | __hci_req_update_class(&req); |
@@ -3232,7 +3045,7 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, | |||
3232 | 3045 | ||
3233 | if (lmp_bredr_capable(hdev)) { | 3046 | if (lmp_bredr_capable(hdev)) { |
3234 | __hci_req_update_name(&req); | 3047 | __hci_req_update_name(&req); |
3235 | update_eir(&req); | 3048 | __hci_req_update_eir(&req); |
3236 | } | 3049 | } |
3237 | 3050 | ||
3238 | /* The name is stored in the scan response data and so | 3051 | /* The name is stored in the scan response data and so |
@@ -3917,7 +3730,7 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data, | |||
3917 | NULL, 0); | 3730 | NULL, 0); |
3918 | 3731 | ||
3919 | hci_req_init(&req, hdev); | 3732 | hci_req_init(&req, hdev); |
3920 | update_eir(&req); | 3733 | __hci_req_update_eir(&req); |
3921 | hci_req_run(&req, NULL); | 3734 | hci_req_run(&req, NULL); |
3922 | 3735 | ||
3923 | hci_dev_unlock(hdev); | 3736 | hci_dev_unlock(hdev); |
@@ -6759,7 +6572,7 @@ static int powered_update_hci(struct hci_dev *hdev) | |||
6759 | __hci_req_update_scan(&req); | 6572 | __hci_req_update_scan(&req); |
6760 | __hci_req_update_class(&req); | 6573 | __hci_req_update_class(&req); |
6761 | __hci_req_update_name(&req); | 6574 | __hci_req_update_name(&req); |
6762 | update_eir(&req); | 6575 | __hci_req_update_eir(&req); |
6763 | } | 6576 | } |
6764 | 6577 | ||
6765 | return hci_req_run(&req, powered_complete); | 6578 | return hci_req_run(&req, powered_complete); |
@@ -7380,7 +7193,7 @@ void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) | |||
7380 | if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS)) | 7193 | if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS)) |
7381 | hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE, | 7194 | hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE, |
7382 | sizeof(enable), &enable); | 7195 | sizeof(enable), &enable); |
7383 | update_eir(&req); | 7196 | __hci_req_update_eir(&req); |
7384 | } else { | 7197 | } else { |
7385 | clear_eir(&req); | 7198 | clear_eir(&req); |
7386 | } | 7199 | } |