From: <hildawu@realtek.com>
To: <marcel@holtmann.org>
Cc: <johan.hedberg@gmail.com>, <luiz.dentz@gmail.com>,
<linux-bluetooth@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
<apusaka@chromium.org>, <yinghsu@chromium.org>,
<max.chou@realtek.com>, <alex_lu@realsil.com.cn>,
<kidman@realtek.com>
Subject: [PATCH v3 2/3] Bluetooth: btusb: Workaround for spotty SCO quality
Date: Thu, 29 Sep 2022 19:44:25 +0800 [thread overview]
Message-ID: <20220929114426.4413-3-hildawu@realtek.com> (raw)
In-Reply-To: <20220929114426.4413-1-hildawu@realtek.com>
From: Hilda Wu <hildawu@realtek.com>
When streaming HFP, once a few minutes a brief pause in audio can be
heard on some platform with Realtek Bluetooth. When the issue occurs,
the system will see the SCO packet for unknown connection handle messages.
Note: This issue affects (e)SCO only, does not affect ACLs.
Because the duplicate packet causing the problem only occurs in Realtek BT.
This is to filter out duplicate packet for avoiding influence.
Signed-off-by: Alex Lu <alex_lu@realsil.com.cn>
Signed-off-by: Hilda Wu <hildawu@realtek.com>
---
Changes in v3:
- Use the vendor function to replace btus_recv_isoc
- Additional info: The comparison of btrtl_usb_recv_isoc here is for invalid handle,
the invalid handle shouldn't appear. So we try to find out the rule and filter out this.
Changes in v2:
- Seperate commits for functions
---
---
drivers/bluetooth/btrtl.c | 27 ++++++++++++++
drivers/bluetooth/btrtl.h | 8 ++++
drivers/bluetooth/btusb.c | 77 ++++++++++++++++++++++++++++++++++++++-
3 files changed, 111 insertions(+), 1 deletion(-)
diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c
index fb52313a1d45..272f90621a10 100644
--- a/drivers/bluetooth/btrtl.c
+++ b/drivers/bluetooth/btrtl.c
@@ -937,6 +937,33 @@ int btrtl_get_uart_settings(struct hci_dev *hdev,
}
EXPORT_SYMBOL_GPL(btrtl_get_uart_settings);
+int btrtl_usb_recv_isoc(u16 pos, u8 *data, u8 *p, int len,
+ u16 wMaxPacketSize)
+{
+ u8 *prev;
+
+ if (pos >= HCI_SCO_HDR_SIZE && pos >= wMaxPacketSize &&
+ len == wMaxPacketSize && !(pos % wMaxPacketSize) &&
+ wMaxPacketSize >= 10 && p[0] == data[0] && p[1] == data[1]) {
+ prev = data + (pos - wMaxPacketSize);
+
+ /* Detect the sco data of usb isoc pkt duplication. */
+ if (!memcmp(p + 2, prev + 2, 8))
+ return -EILSEQ;
+
+ if (wMaxPacketSize >= 12 &&
+ p[2] == prev[6] && p[3] == prev[7] &&
+ p[4] == prev[4] && p[5] == prev[5] &&
+ p[6] == prev[10] && p[7] == prev[11] &&
+ p[8] == prev[8] && p[9] == prev[9]) {
+ return -EILSEQ;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(btrtl_usb_recv_isoc);
+
MODULE_AUTHOR("Daniel Drake <drake@endlessm.com>");
MODULE_DESCRIPTION("Bluetooth support for Realtek devices ver " VERSION);
MODULE_VERSION(VERSION);
diff --git a/drivers/bluetooth/btrtl.h b/drivers/bluetooth/btrtl.h
index ebf0101c959b..c9783e8fe0aa 100644
--- a/drivers/bluetooth/btrtl.h
+++ b/drivers/bluetooth/btrtl.h
@@ -83,6 +83,8 @@ int btrtl_get_uart_settings(struct hci_dev *hdev,
struct btrtl_device_info *btrtl_dev,
unsigned int *controller_baudrate,
u32 *device_baudrate, bool *flow_control);
+int btrtl_usb_recv_isoc(u16 pos, u8 *data, u8 *buffer, int len,
+ u16 wMaxPacketSize);
#else
@@ -126,4 +128,10 @@ static inline int btrtl_get_uart_settings(struct hci_dev *hdev,
return -ENOENT;
}
+static inline int btrtl_usb_recv_isoc(u16 pos, u8 *data, u8 *buffer, int len,
+ u16 wMaxPacketSize)
+{
+ return -EOPNOTSUPP;
+}
+
#endif
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 4c3aed89ff05..7583059e3b2c 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -683,6 +683,7 @@ struct btusb_data {
int (*recv_event)(struct hci_dev *hdev, struct sk_buff *skb);
int (*recv_acl)(struct hci_dev *hdev, struct sk_buff *skb);
int (*recv_bulk)(struct btusb_data *data, void *buffer, int count);
+ int (*recv_isoc)(struct btusb_data *data, void *buffer, int count);
int (*setup_on_usb)(struct hci_dev *hdev);
@@ -1239,7 +1240,7 @@ static void btusb_isoc_complete(struct urb *urb)
hdev->stat.byte_rx += length;
- if (btusb_recv_isoc(data, urb->transfer_buffer + offset,
+ if (data->recv_isoc(data, urb->transfer_buffer + offset,
length) < 0) {
bt_dev_err(hdev, "corrupted SCO packet");
hdev->stat.err_rx++;
@@ -2309,6 +2310,77 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
return -EILSEQ;
}
+static int btusb_recv_isoc_realtek(struct btusb_data *data, void *buffer,
+ int count)
+{
+ struct sk_buff *skb;
+ unsigned long flags;
+ int err = 0;
+ u16 wMaxPacketSize = le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize);
+
+ spin_lock_irqsave(&data->rxlock, flags);
+ skb = data->sco_skb;
+
+ while (count) {
+ int len;
+
+ if (!skb) {
+ skb = bt_skb_alloc(HCI_MAX_SCO_SIZE, GFP_ATOMIC);
+ if (!skb) {
+ err = -ENOMEM;
+ break;
+ }
+
+ hci_skb_pkt_type(skb) = HCI_SCODATA_PKT;
+ hci_skb_expect(skb) = HCI_SCO_HDR_SIZE;
+ }
+
+ len = min_t(uint, hci_skb_expect(skb), count);
+
+ /* Gaps in audio could be heard while streaming WBS using USB
+ * alt settings 3 on some platforms, since this is only used
+ * with RTK chips so let vendor function detect it.
+ */
+ if (!btusb_find_altsetting(data, 6) &&
+ test_bit(BTUSB_USE_ALT3_FOR_WBS, &data->flags)) {
+ err = btrtl_usb_recv_isoc(skb->len, skb->data, buffer,
+ len, wMaxPacketSize);
+ if (err)
+ break;
+ }
+
+ skb_put_data(skb, buffer, len);
+
+ count -= len;
+ buffer += len;
+ hci_skb_expect(skb) -= len;
+
+ if (skb->len == HCI_SCO_HDR_SIZE) {
+ /* Complete SCO header */
+ hci_skb_expect(skb) = hci_sco_hdr(skb)->dlen;
+
+ if (skb_tailroom(skb) < hci_skb_expect(skb)) {
+ kfree_skb(skb);
+ skb = NULL;
+
+ err = -EILSEQ;
+ break;
+ }
+ }
+
+ if (!hci_skb_expect(skb)) {
+ /* Complete frame */
+ hci_recv_frame(data->hdev, skb);
+ skb = NULL;
+ }
+ }
+
+ data->sco_skb = skb;
+ spin_unlock_irqrestore(&data->rxlock, flags);
+
+ return err;
+}
+
/* UHW CR mapping */
#define MTK_BT_MISC 0x70002510
#define MTK_BT_SUBSYS_RST 0x70002610
@@ -3741,6 +3813,7 @@ static int btusb_probe(struct usb_interface *intf,
data->recv_event = hci_recv_frame;
data->recv_bulk = btusb_recv_bulk;
+ data->recv_isoc = btusb_recv_isoc;
if (id->driver_info & BTUSB_INTEL_COMBINED) {
/* Allocate extra space for Intel device */
@@ -3914,6 +3987,8 @@ static int btusb_probe(struct usb_interface *intf,
hdev->shutdown = btrtl_shutdown_realtek;
hdev->cmd_timeout = btusb_rtl_cmd_timeout;
+ data->recv_isoc = btusb_recv_isoc_realtek;
+
/* Realtek devices need to set remote wakeup on auto-suspend */
set_bit(BTUSB_WAKEUP_AUTOSUSPEND, &data->flags);
set_bit(BTUSB_USE_ALT3_FOR_WBS, &data->flags);
--
2.17.1
next prev parent reply other threads:[~2022-09-29 11:44 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-09-29 11:44 [PATCH v3 0/3] Bluetooth: Add btrealtek data struct and improve SCO sound quality of RTK chips hildawu
2022-09-29 11:44 ` [PATCH v3 1/3] Bluetooth: btrtl: Add btrealtek data struct hildawu
2022-09-29 12:11 ` Bluetooth: Add btrealtek data struct and improve SCO sound quality of RTK chips bluez.test.bot
2022-09-29 11:44 ` hildawu [this message]
2022-09-29 19:35 ` [PATCH v3 2/3] Bluetooth: btusb: Workaround for spotty SCO quality Luiz Augusto von Dentz
2022-09-29 11:44 ` [PATCH v3 3/3] Bluetooth:btsub:Ignore zero length of USB packets on ALT 6 for specific chip hildawu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220929114426.4413-3-hildawu@realtek.com \
--to=hildawu@realtek.com \
--cc=alex_lu@realsil.com.cn \
--cc=apusaka@chromium.org \
--cc=johan.hedberg@gmail.com \
--cc=kidman@realtek.com \
--cc=linux-bluetooth@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luiz.dentz@gmail.com \
--cc=marcel@holtmann.org \
--cc=max.chou@realtek.com \
--cc=yinghsu@chromium.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox