| From bd76287003539353e7442baadfb2aff8f2827d8c Mon Sep 17 00:00:00 2001 |
| From: Alain Michaud <alainm@chromium.org> |
| Date: Fri, 9 Apr 2021 15:21:27 +0000 |
| Subject: [PATCH] CHROMIUM: Use link policies to disallow role switches |
| |
| Some peripherals will attempt to role switch the host device into a |
| peripheral role mode. When combined with other peripherals such as mice |
| and keyboards, this forces the controller to maintain a complicated |
| topology which results in audio glitches or mouse movement glitches. |
| |
| The solution implemented by this patch is to leverage the link_policy to |
| attempt to disallow the peripheral from switching roles once the host |
| settles into the central role. |
| |
| This is submitted as a chromium patch to gain some feedback on |
| improvement before proposing upstream. |
| |
| Signed-off-by: Alain Michaud <alainm@chromium.org> |
| |
| BUG=none |
| TEST=build |
| |
| Change-Id: I8209b0b1073c0b2d03a2631c64423e67ff96184f |
| Signed-off-by: Zhengping Jiang <jiangzp@google.com> |
| Kcr-patch: 2651373bd21928a45d21c88602ed1535423fe062aff4c93be8d231e5.patch |
| --- |
| net/bluetooth/hci_conn.c | 1 + |
| net/bluetooth/hci_event.c | 19 +++++++++++++++++++ |
| 2 files changed, 20 insertions(+) |
| |
| diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c |
| index ebdd7f83eb476c142005417ee68a8f64b78c0ca6..0c44c5d9d6746afe99c4dbf1d0a3879d675d00a3 100644 |
| --- a/net/bluetooth/hci_conn.c |
| +++ b/net/bluetooth/hci_conn.c |
| @@ -931,6 +931,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst, |
| conn->tx_power = HCI_TX_POWER_INVALID; |
| conn->max_tx_power = HCI_TX_POWER_INVALID; |
| conn->sync_handle = HCI_SYNC_HANDLE_INVALID; |
| + conn->link_policy = hdev->link_policy; |
| |
| set_bit(HCI_CONN_POWER_SAVE, &conn->flags); |
| conn->disc_timeout = HCI_DISCONN_TIMEOUT; |
| diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c |
| index a8b8cfebe0180cce2fb661e8e5f21a79bf7a7656..b44b1cf1431584bf3a4433fc6a83c3c75152faab 100644 |
| --- a/net/bluetooth/hci_event.c |
| +++ b/net/bluetooth/hci_event.c |
| @@ -3183,6 +3183,12 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data, |
| } |
| |
| if (!status) { |
| + int mask = hdev->link_mode; |
| + __u8 flags = 0; |
| + |
| + mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type, |
| + &flags); |
| + |
| status = hci_conn_set_handle(conn, __le16_to_cpu(ev->handle)); |
| if (status) |
| goto done; |
| @@ -3208,6 +3214,19 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data, |
| if (test_bit(HCI_ENCRYPT, &hdev->flags)) |
| set_bit(HCI_CONN_ENCRYPT, &conn->flags); |
| |
| + /* Attempt to remain in the central role if preferred */ |
| + if ((conn->mode == HCI_ROLE_MASTER && (mask & HCI_LM_MASTER)) && |
| + (conn->link_policy & HCI_LP_RSWITCH)) { |
| + struct hci_cp_write_link_policy cp; |
| + |
| + conn->link_policy &= ~HCI_LP_RSWITCH; |
| + |
| + cp.handle = ev->handle; |
| + cp.policy = conn->link_policy; |
| + hci_send_cmd(hdev, HCI_OP_WRITE_LINK_POLICY, |
| + sizeof(cp), &cp); |
| + } |
| + |
| /* "Link key request" completed ahead of "connect request" completes */ |
| if (ev->encr_mode == 1 && !test_bit(HCI_CONN_ENCRYPT, &conn->flags) && |
| ev->link_type == ACL_LINK) { |
| -- |
| 2.44.0.478.gd926399ef9-goog |
| |