Skip to content

Commit 4fd22ab

Browse files
committed
Bluetooth: btusb: Enable Mediatek modules to work on USB 3.0 busses
MT7921U and possibly other related chips expose a different configuration on USB 3.0 vs. USB 2.0. Current driver logic only works with the USB 2.0 configuration, while connecting the module to a USB 3.0-only bus results in enumeration and scanning succeeding but connections silently failing. Add a special case for Mediatek modules on SuperSpeed busses to select the right bulk OUT endpoint (second not first) to make them work. Signed-off-by: Alexey Charkov <alchark@flipper.net>
1 parent 09246e1 commit 4fd22ab

1 file changed

Lines changed: 43 additions & 0 deletions

File tree

drivers/bluetooth/btusb.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4090,6 +4090,49 @@ static int btusb_probe(struct usb_interface *intf,
40904090
return -ENODEV;
40914091
}
40924092

4093+
/*
4094+
* MediaTek MT7921U (and likely related MTK combo chips), when
4095+
* attached over the SuperSpeed lanes, present a HCI interface with
4096+
* *two* bulk OUT endpoints: the lower-numbered one is a vendor /
4097+
* diagnostic pipe that silently consumes data without ever raising
4098+
* a transfer-complete event, and the higher-numbered one is the
4099+
* actual ACL OUT. usb_find_common_endpoints() returns the first
4100+
* match, which sinks all outbound HCI traffic and leaves the device
4101+
* able to scan but unable to complete any connection.
4102+
*
4103+
* Most MT7921U deployments wire the Bluetooth function to the USB
4104+
* 2.0 differential pair and enumerate at High-Speed, where the
4105+
* descriptor only exposes a single bulk OUT and this code path is
4106+
* a no-op.
4107+
*/
4108+
if ((id->driver_info & BTUSB_MEDIATEK) &&
4109+
interface_to_usbdev(intf)->speed >= USB_SPEED_SUPER) {
4110+
struct usb_host_interface *alt = intf->cur_altsetting;
4111+
struct usb_endpoint_descriptor *ep, *second_bulk_out = NULL;
4112+
int i, bulk_out_count = 0;
4113+
4114+
for (i = 0; i < alt->desc.bNumEndpoints; i++) {
4115+
ep = &alt->endpoint[i].desc;
4116+
if (!usb_endpoint_is_bulk_out(ep))
4117+
continue;
4118+
if (++bulk_out_count == 2)
4119+
second_bulk_out = ep;
4120+
}
4121+
4122+
if (bulk_out_count == 2 && second_bulk_out &&
4123+
second_bulk_out != data->bulk_tx_ep) {
4124+
dev_info(&intf->dev,
4125+
"btusb: MTK: SuperSpeed: using bEP 0x%02x as ACL OUT (overrides diag bEP 0x%02x)\n",
4126+
second_bulk_out->bEndpointAddress,
4127+
data->bulk_tx_ep->bEndpointAddress);
4128+
data->bulk_tx_ep = second_bulk_out;
4129+
} else if (bulk_out_count > 2) {
4130+
dev_warn(&intf->dev,
4131+
"btusb: MTK: SuperSpeed: unexpected bulk OUT count %d, leaving default selection\n",
4132+
bulk_out_count);
4133+
}
4134+
}
4135+
40934136
if (id->driver_info & BTUSB_AMP) {
40944137
data->cmdreq_type = USB_TYPE_CLASS | 0x01;
40954138
data->cmdreq = 0x2b;

0 commit comments

Comments
 (0)