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>
This commit is contained in:
parent
6cd29ec6ae
commit
4fc9857ab8
|
@ -783,6 +783,12 @@ extern struct mutex hci_cb_list_lock;
|
||||||
hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT); \
|
hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define hci_dev_le_state_simultaneous(hdev) \
|
||||||
|
(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 */
|
||||||
|
|
||||||
/* ----- HCI interface to upper protocols ----- */
|
/* ----- HCI interface to upper protocols ----- */
|
||||||
int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
|
int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
|
||||||
int l2cap_disconn_ind(struct hci_conn *hcon);
|
int l2cap_disconn_ind(struct hci_conn *hcon);
|
||||||
|
|
|
@ -5195,30 +5195,29 @@ int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn)
|
||||||
u8 own_addr_type;
|
u8 own_addr_type;
|
||||||
int err;
|
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 requested to connect as peripheral use directed advertising */
|
||||||
if (conn->role == HCI_ROLE_SLAVE) {
|
if (conn->role == HCI_ROLE_SLAVE) {
|
||||||
/* If we're active scanning most controllers are unable
|
/* If we're active scanning and the controller doesn't support
|
||||||
* to initiate advertising. Simply reject the attempt.
|
* simultaneous roles simply reject the attempt.
|
||||||
*/
|
*/
|
||||||
if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
|
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);
|
hci_conn_del(conn);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Pause advertising while doing directed advertising. */
|
||||||
|
hci_pause_advertising_sync(hdev);
|
||||||
|
|
||||||
err = hci_le_directed_advertising_sync(hdev, conn);
|
err = hci_le_directed_advertising_sync(hdev, conn);
|
||||||
goto done;
|
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);
|
params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
|
||||||
if (params) {
|
if (params) {
|
||||||
conn->le_conn_min_interval = params->conn_min_interval;
|
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);
|
HCI_CMD_TIMEOUT, NULL);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
/* Re-enable advertising after the connection attempt is finished. */
|
||||||
hci_resume_advertising_sync(hdev);
|
hci_resume_advertising_sync(hdev);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3916,10 +3916,7 @@ static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (hdev) {
|
if (hdev) {
|
||||||
if (test_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks) &&
|
if (hci_dev_le_state_simultaneous(hdev))
|
||||||
(hdev->le_states[4] & 0x08) && /* Central */
|
|
||||||
(hdev->le_states[4] & 0x40) && /* Peripheral */
|
|
||||||
(hdev->le_states[3] & 0x10)) /* Simultaneous */
|
|
||||||
flags = BIT(0);
|
flags = BIT(0);
|
||||||
else
|
else
|
||||||
flags = 0;
|
flags = 0;
|
||||||
|
|
Loading…
Reference in New Issue