diff options
author | Łukasz Rymanowski <lukasz.rymanowski@codecoup.pl> | 2017-12-08 07:40:57 -0500 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2017-12-13 03:41:37 -0500 |
commit | 9e1e9f20ca96026c56ac613317ea4bf01c6c3385 (patch) | |
tree | 56117e225b5e1ecea03a1158131da87f5278b8df /net/bluetooth/hci_request.c | |
parent | 4166493c97c0c70e8d7678422c2214dc5ec6e9d3 (diff) |
Bluetooth: Add support to advertise when connected
So far, kernel did not allow to advertise when there was a connection
established. With this patch kernel does allow it if controller
supports it.
If controller supports non-connectable advertising when connected, then
only non-connectable advertising instances will be advertised.
Signed-off-by: Łukasz Rymanowski <lukasz.rymanowski@codecoup.pl>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/hci_request.c')
-rw-r--r-- | net/bluetooth/hci_request.c | 55 |
1 files changed, 46 insertions, 9 deletions
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index da59f82754bc..3394e6791673 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c | |||
@@ -919,6 +919,43 @@ static bool adv_use_rpa(struct hci_dev *hdev, uint32_t flags) | |||
919 | return true; | 919 | return true; |
920 | } | 920 | } |
921 | 921 | ||
922 | static bool is_advertising_allowed(struct hci_dev *hdev, bool connectable) | ||
923 | { | ||
924 | /* If there is no connection we are OK to advertise. */ | ||
925 | if (hci_conn_num(hdev, LE_LINK) == 0) | ||
926 | return true; | ||
927 | |||
928 | /* Check le_states if there is any connection in slave role. */ | ||
929 | if (hdev->conn_hash.le_num_slave > 0) { | ||
930 | /* Slave connection state and non connectable mode bit 20. */ | ||
931 | if (!connectable && !(hdev->le_states[2] & 0x10)) | ||
932 | return false; | ||
933 | |||
934 | /* Slave connection state and connectable mode bit 38 | ||
935 | * and scannable bit 21. | ||
936 | */ | ||
937 | if (connectable && (!(hdev->le_states[4] & 0x01) || | ||
938 | !(hdev->le_states[2] & 0x40))) | ||
939 | return false; | ||
940 | } | ||
941 | |||
942 | /* Check le_states if there is any connection in master role. */ | ||
943 | if (hci_conn_num(hdev, LE_LINK) != hdev->conn_hash.le_num_slave) { | ||
944 | /* Master connection state and non connectable mode bit 18. */ | ||
945 | if (!connectable && !(hdev->le_states[2] & 0x02)) | ||
946 | return false; | ||
947 | |||
948 | /* Master connection state and connectable mode bit 35 and | ||
949 | * scannable 19. | ||
950 | */ | ||
951 | if (connectable && (!(hdev->le_states[4] & 0x10) || | ||
952 | !(hdev->le_states[2] & 0x08))) | ||
953 | return false; | ||
954 | } | ||
955 | |||
956 | return true; | ||
957 | } | ||
958 | |||
922 | void __hci_req_enable_advertising(struct hci_request *req) | 959 | void __hci_req_enable_advertising(struct hci_request *req) |
923 | { | 960 | { |
924 | struct hci_dev *hdev = req->hdev; | 961 | struct hci_dev *hdev = req->hdev; |
@@ -927,7 +964,15 @@ void __hci_req_enable_advertising(struct hci_request *req) | |||
927 | bool connectable; | 964 | bool connectable; |
928 | u32 flags; | 965 | u32 flags; |
929 | 966 | ||
930 | if (hci_conn_num(hdev, LE_LINK) > 0) | 967 | flags = get_adv_instance_flags(hdev, hdev->cur_adv_instance); |
968 | |||
969 | /* If the "connectable" instance flag was not set, then choose between | ||
970 | * ADV_IND and ADV_NONCONN_IND based on the global connectable setting. | ||
971 | */ | ||
972 | connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) || | ||
973 | mgmt_get_connectable(hdev); | ||
974 | |||
975 | if (!is_advertising_allowed(hdev, connectable)) | ||
931 | return; | 976 | return; |
932 | 977 | ||
933 | if (hci_dev_test_flag(hdev, HCI_LE_ADV)) | 978 | if (hci_dev_test_flag(hdev, HCI_LE_ADV)) |
@@ -940,14 +985,6 @@ void __hci_req_enable_advertising(struct hci_request *req) | |||
940 | */ | 985 | */ |
941 | hci_dev_clear_flag(hdev, HCI_LE_ADV); | 986 | hci_dev_clear_flag(hdev, HCI_LE_ADV); |
942 | 987 | ||
943 | flags = get_adv_instance_flags(hdev, hdev->cur_adv_instance); | ||
944 | |||
945 | /* If the "connectable" instance flag was not set, then choose between | ||
946 | * ADV_IND and ADV_NONCONN_IND based on the global connectable setting. | ||
947 | */ | ||
948 | connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) || | ||
949 | mgmt_get_connectable(hdev); | ||
950 | |||
951 | /* Set require_privacy to true only when non-connectable | 988 | /* Set require_privacy to true only when non-connectable |
952 | * advertising is used. In that case it is fine to use a | 989 | * advertising is used. In that case it is fine to use a |
953 | * non-resolvable private address. | 990 | * non-resolvable private address. |