aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2021-12-22 12:21:59 -0800
committerMarcel Holtmann <marcel@holtmann.org>2021-12-22 23:01:35 +0100
commit4fc9857ab8c6cfe2152df3288c8cf3300b929f1a (patch)
treee06266d1052627f279fe3785f98777831e9398e2 /net/bluetooth
parentBluetooth: hci_sync: Wait for proper events when connecting LE (diff)
downloadlinux-dev-4fc9857ab8c6cfe2152df3288c8cf3300b929f1a.tar.xz
linux-dev-4fc9857ab8c6cfe2152df3288c8cf3300b929f1a.zip
Bluetooth: hci_sync: Add check simultaneous roles support
This attempts to check if the controller can act as both central and peripheral simultaneously and in case it does skip suspending advertising or in case of directed advertising don't fail if scanning. Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/hci_sync.c24
-rw-r--r--net/bluetooth/mgmt.c5
2 files changed, 13 insertions, 16 deletions
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index 8c50a12ba5f5..61d8a076a3f3 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -5195,30 +5195,29 @@ int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn)
u8 own_addr_type;
int err;
- /* Disable advertising if we're active. For central role
- * connections most controllers will refuse to connect if
- * advertising is enabled, and for peripheral role connections we
- * anyway have to disable it in order to start directed
- * advertising. Any registered advertisements will be
- * re-enabled after the connection attempt is finished.
- */
- hci_pause_advertising_sync(hdev);
-
/* If requested to connect as peripheral use directed advertising */
if (conn->role == HCI_ROLE_SLAVE) {
- /* If we're active scanning most controllers are unable
- * to initiate advertising. Simply reject the attempt.
+ /* If we're active scanning and the controller doesn't support
+ * simultaneous roles simply reject the attempt.
*/
if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
- hdev->le_scan_type == LE_SCAN_ACTIVE) {
+ hdev->le_scan_type == LE_SCAN_ACTIVE &&
+ !hci_dev_le_state_simultaneous(hdev)) {
hci_conn_del(conn);
return -EBUSY;
}
+ /* Pause advertising while doing directed advertising. */
+ hci_pause_advertising_sync(hdev);
+
err = hci_le_directed_advertising_sync(hdev, conn);
goto done;
}
+ /* Disable advertising if simultaneous roles is not supported. */
+ if (!hci_dev_le_state_simultaneous(hdev))
+ hci_pause_advertising_sync(hdev);
+
params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
if (params) {
conn->le_conn_min_interval = params->conn_min_interval;
@@ -5276,6 +5275,7 @@ int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn)
HCI_CMD_TIMEOUT, NULL);
done:
+ /* Re-enable advertising after the connection attempt is finished. */
hci_resume_advertising_sync(hdev);
return err;
}
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 962bb747d2cd..3326d9459dd3 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3916,10 +3916,7 @@ static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
#endif
if (hdev) {
- if (test_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks) &&
- (hdev->le_states[4] & 0x08) && /* Central */
- (hdev->le_states[4] & 0x40) && /* Peripheral */
- (hdev->le_states[3] & 0x10)) /* Simultaneous */
+ if (hci_dev_le_state_simultaneous(hdev))
flags = BIT(0);
else
flags = 0;