Skip to content

Instantly share code, notes, and snippets.

@vitaliemiron
Last active March 13, 2026 08:59
Show Gist options
  • Select an option

  • Save vitaliemiron/c23d7b2e47ab67a7a0851f6ef0cada39 to your computer and use it in GitHub Desktop.

Select an option

Save vitaliemiron/c23d7b2e47ab67a7a0851f6ef0cada39 to your computer and use it in GitHub Desktop.
MediaTek MT7927 (MT6639) WiFi + Bluetooth on Ubuntu — ASUS ROG CROSSHAIR X870E HERO

MediaTek MT7927 (MT6639) WiFi + Bluetooth on Ubuntu — ASUS ROG CROSSHAIR X870E HERO

MediaTek MT7927 (MT6639) WiFi + Bluetooth on Ubuntu — ASUS ROG CROSSHAIR X870E HERO

Getting both WiFi and Bluetooth working on the MediaTek MT7927 (Filogic 380) combo chip on Ubuntu 24.04 with kernel 6.17+.

Hardware

  • Board: ASUS ROG CROSSHAIR X870E HERO
  • Chip: MediaTek MT6639 (PCI 14c3:6639), marketed as MT7927 (WiFi 7, Filogic 380)
  • WiFi: PCIe — works via patched mt7925e driver
  • Bluetooth: USB 13d3:3588 (IMC Networks / MediaTek) — requires btusb patch
  • OS: Ubuntu 24.04.4 LTS, kernel 6.17.0-14-generic

The Problem

  1. WiFi: The MT6639/MT7927 chip is not supported by the stock kernel mt76 driver (no 0x6639 chip ID handling)
  2. Bluetooth: The BT half of the chip appears as a USB device (13d3:3588) but btusb doesn't recognize the USB ID as a MediaTek device, so it never loads firmware — HCI reset fails with -16 (EBUSY)
  3. Boot timing race: The BT USB device needs the WiFi driver to initialize CONNINFRA first. If USB enumeration happens before WiFi init, the BT device hangs and needs a full PSU power cycle to recover

Solution Overview

  • WiFi: jetm's mediatek-mt7927-dkms package with patched mt76/mt7925e driver
  • Bluetooth: Patch btusb/btmtk to add 0x6639 device support + USB ID 13d3:3588 (based on max-prtsr's gist)
  • Boot timing: initramfs early loading + systemd xHCI rescan service

Step 1: Install Prerequisites

sudo apt update
sudo apt install -y build-essential dkms linux-headers-$(uname -r) git curl python3 zstd iw

Step 2: Install WiFi Driver via DKMS

# Clone jetm's DKMS package
cd ~
git clone https://github.com/jetm/mediatek-mt7927-dkms.git
cd mediatek-mt7927-dkms

# Copy DKMS source to /usr/src
sudo cp -r mediatek-mt7927-2.1 /usr/src/

# If kernel < 6.19: copy missing stub header needed by mt76
KVER=$(uname -r)
if [ ! -f /usr/src/linux-headers-${KVER}/include/linux/soc/airoha/airoha_offload.h ]; then
  sudo mkdir -p /usr/src/linux-headers-${KVER}/include/linux/soc/airoha/
  curl -sL "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/plain/include/linux/soc/airoha/airoha_offload.h?h=v6.19" \
    | sudo tee /usr/src/linux-headers-${KVER}/include/linux/soc/airoha/airoha_offload.h > /dev/null
  echo "Stub header installed"
fi

# Build and install DKMS modules
sudo dkms add mediatek-mt7927/2.1
sudo dkms build mediatek-mt7927/2.1 -k $(uname -r)
sudo dkms install mediatek-mt7927/2.1 -k $(uname -r)

Step 3: Install WiFi Firmware

# Create firmware directories
sudo mkdir -p /lib/firmware/mediatek/mt6639
sudo mkdir -p /lib/firmware/mediatek/mt7927

# Download WiFi firmware from jetm's repo (or copy from the cloned repo)
sudo cp ~/mediatek-mt7927-dkms/firmware/WIFI_MT6639_PATCH_MCU_2_1_hdr.bin /lib/firmware/mediatek/mt7927/
sudo cp ~/mediatek-mt7927-dkms/firmware/WIFI_RAM_CODE_MT6639_2_1.bin /lib/firmware/mediatek/mt7927/

Step 4: Install Bluetooth Firmware

Download the official MediaTek Bluetooth driver from your motherboard's ASUS support page (Drivers → Windows 11 → Bluetooth). Extract the zip.

# Extract BT firmware from the Windows driver's mtkbt.dat file
# Replace 'path/to/BT/mtkbt.dat' with the actual path to the extracted file
python3 -c "
import struct, sys
data = open(sys.argv[1], 'rb').read()
offset = 0x10
name = data[offset:offset+48].split(b'\x00')[0].decode()
data_offset = struct.unpack_from('<I', data, offset + 64)[0]
data_size = struct.unpack_from('<I', data, offset + 68)[0]
fw = data[data_offset:data_offset + data_size]
open('BT_RAM_CODE_MT6639_2_1_hdr.bin', 'wb').write(fw)
print(f'Extracted {name}: {len(fw)} bytes')
" path/to/BT/mtkbt.dat

# Install to firmware directory
sudo cp BT_RAM_CODE_MT6639_2_1_hdr.bin /lib/firmware/mediatek/mt6639/

Step 5: Add Your BT USB ID to the btusb patch

IMPORTANT: btusb has TWO device tables. New USB IDs must go in quirks_table (around line 733), NOT in btusb_table (around line 70). The generic USB_INTERFACE_INFO(0xe0,0x01,0x01) entry in btusb_table matches ALL Bluetooth USB devices first with driver_info=0. Then btusb_probe() does a second lookup in quirks_table for vendor-specific flags. If your entry is in the wrong table, BTUSB_MEDIATEK is never set, btmtk_usb_setup never runs, no firmware is downloaded, and HCI_Reset fails with status 0x0c (Command Disallowed) / errno -16.

The DKMS BT patch includes 0489:e13a by default. The ASUS ROG CROSSHAIR X870E HERO uses 13d3:3588 instead. Check yours:

# Find your BT USB ID (run after cold boot if device isn't visible)
lsusb | grep -iE 'mediatek|wireless_device'

If your ID is already in the patch, skip this step. Otherwise add it to the quirks_table section of the patch:

# This command adds USB ID 13d3:3588 to the btusb patch (quirks_table section)
# Change 0x13d3 and 0x3588 to match YOUR device if different
sudo python3 -c "
import re

with open('/usr/src/mediatek-mt7927-2.1/mt6639-bt-6.19.patch', 'r') as f:
    content = f.read()

# Check if already present
if '0x13d3, 0x3588' in content:
    print('USB ID 13d3:3588 already in patch, skipping')
    exit(0)

# Add new USB ID in the quirks_table section (after e0fa entry)
old = '''+\t{ USB_DEVICE(0x0489, 0xe0fa), .driver_info = BTUSB_MEDIATEK |
+\t\t\t\t\t\t     BTUSB_WIDEBAND_SPEECH },'''

new = '''+\t{ USB_DEVICE(0x0489, 0xe0fa), .driver_info = BTUSB_MEDIATEK |
+\t\t\t\t\t\t     BTUSB_WIDEBAND_SPEECH },
+\t{ USB_DEVICE(0x13d3, 0x3588), .driver_info = BTUSB_MEDIATEK |
+\t\t\t\t\t\t     BTUSB_WIDEBAND_SPEECH },'''

content = content.replace(old, new)

# Update hunk header line count (+2 lines added)
content = re.sub(
    r'@@ -733,6 \+733,(\d+) @@',
    lambda m: f'@@ -733,6 +733,{int(m.group(1))+2} @@',
    content
)

with open('/usr/src/mediatek-mt7927-2.1/mt6639-bt-6.19.patch', 'w') as f:
    f.write(content)
print('Added USB ID 13d3:3588 to btusb patch (quirks_table)')
"

Now rebuild the DKMS modules with the updated patch:

sudo dkms remove mediatek-mt7927/2.1 -k $(uname -r) --force
sudo dkms build mediatek-mt7927/2.1 -k $(uname -r)
sudo dkms install mediatek-mt7927/2.1 -k $(uname -r) --force

Step 6: Fix BT Boot Timing Race

The BT USB device needs CONNINFRA (initialized by the WiFi driver) before it can enumerate. These commands set up early loading and USB bus re-scan.

# 6a. Load WiFi driver early in initramfs
echo "mt7925e" | sudo tee -a /etc/initramfs-tools/modules

# 6b. Auto-load BT modules at boot
cat <<EOF | sudo tee /etc/modules-load.d/mt7927.conf
mt7925e
btmtk
btusb
EOF

# 6c. Include BT firmware in initramfs
cat <<'EOF' | sudo tee /etc/initramfs-tools/hooks/mt6639-bt-firmware
#!/bin/sh
PREREQ=""
prereqs() { echo "$PREREQ"; }
case $1 in prereqs) prereqs; exit 0;; esac
. /usr/share/initramfs-tools/hook-functions
copy_file firmware /lib/firmware/mediatek/mt6639/BT_RAM_CODE_MT6639_2_1_hdr.bin
EOF
sudo chmod +x /etc/initramfs-tools/hooks/mt6639-bt-firmware

Step 7: Create USB Rescan Service

This service re-scans the USB bus after WiFi has initialized CONNINFRA, giving BT a fresh enumeration attempt.

First, find your xHCI PCI address:

# Find which xHCI controller hosts the BT USB device (usually bus 1)
readlink -f /sys/bus/usb/devices/usb1 | grep -oP 'pci[0-9:]+/\K[0-9a-f:.]+(?=/usb)'
# Example output: 0000:0e:00.0

Then create the service (replace 0000:0e:00.0 with your address):

# Replace 0000:0e:00.0 with YOUR xHCI PCI address from above!
XHCI_ADDR="0000:0e:00.0"

cat <<EOF | sudo tee /etc/systemd/system/mt7927-bt-rescan.service
[Unit]
Description=Rescan USB bus for MT7927 Bluetooth after WiFi init
After=network-pre.target
Wants=network-pre.target

[Service]
Type=oneshot
ExecStartPre=/bin/sleep 5
ExecStart=/bin/bash -c 'echo "${XHCI_ADDR}" > /sys/bus/pci/drivers/xhci_hcd/unbind; sleep 3; echo "${XHCI_ADDR}" > /sys/bus/pci/drivers/xhci_hcd/bind'
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable mt7927-bt-rescan.service

Step 8: Rebuild Initramfs and Cold Boot

# Rebuild initramfs with all changes
sudo update-initramfs -u

# Power off completely (NOT reboot — warm reboot won't clear hung BT state)
sudo poweroff

After poweroff:

  1. Turn off the PSU switch (back of the PC)
  2. Wait 10+ seconds (clears hung MT6639 BT state)
  3. Turn PSU back on and power up

Step 9: Verify Everything Works

# Check WiFi
iw dev
# Expected: wlp9s0 interface listed

# Check BT USB device is visible
lsusb | grep -iE 'mediatek|wireless_device|13d3'
# Expected: Bus 001 Device 003: ID 13d3:3588 IMC Networks Wireless_Device

# Check Bluetooth controller
hciconfig -a
# Expected: hci0 UP RUNNING, real BD address (not 00:00:00:00:00:00)

# Check bluetoothctl
bluetoothctl show
# Expected: Controller with Powered: yes

# Check rescan service ran
systemctl status mt7927-bt-rescan
# Expected: active (exited)

# If BT not working, check kernel messages:
sudo dmesg | grep -iE 'btusb|btmtk|mt6639|hci|bluetooth|usb 1-6' | tail -20

Quick Test: Reload BT Modules Without Rebooting

If you just rebuilt DKMS and want to test without rebooting:

sudo modprobe -r btusb
sudo modprobe -r btmtk
sudo modprobe btmtk
sudo modprobe btusb
sudo rfkill unblock bluetooth

# Wait ~20 seconds for firmware to load, then check:
sleep 20 && hciconfig -a && bluetoothctl show

Known BT USB IDs for MT7927/MT6639

Different board manufacturers use different USB IDs for the same chip:

USB ID OEM Boards
0489:e13a Foxconn/Hon Hai ASUS ROG STRIX X870-I
0489:e0fa Foxconn/Hon Hai Various
0489:e116 Foxconn/Hon Hai Various
0489:e110 Foxconn/Hon Hai MSI X870E Ace Max
13d3:3588 IMC Networks ASUS ROG CROSSHAIR X870E HERO, ASUS ProArt X870E

If yours isn't listed, add it to the patch as shown in Step 5.

Troubleshooting

Problem Solution
BT USB not in lsusb Cold boot required: sudo poweroff → PSU off 10s → power on
hci0 BD address all zeros USB ID not in btusb quirks_table — see Step 5
Opcode 0x0c03 failed: -16 USB ID in wrong table or missing — must be in quirks_table, see Step 5
WiFi slow / drops Disable ASPM: echo 0 | sudo tee /sys/bus/pci/devices/0000:09:00.0/link/l1_aspm
CHIPID reads 0x0000 Normal — driver forces it to 0x7927
Build fails kernel < 6.19 Copy stub header — see Step 2
setting interface failed (22) Harmless warning, ignore
ISO intf not support (-19) Harmless warning, ignore

btusb table architecture (why Step 5 matters)

btusb.c has two USB device ID tables:

  1. btusb_table (line ~70) — Used for driver binding. Contains generic entries like USB_INTERFACE_INFO(0xe0, 0x01, 0x01) that match ALL Bluetooth USB devices with driver_info=0.
  2. quirks_table (line ~179) — Contains vendor-specific entries with flags like BTUSB_MEDIATEK. Looked up inside btusb_probe() when the initial driver_info is 0.

USB matching is first-match (not best-match). The generic entry always wins in btusb_table. New MT7927 USB IDs must go in quirks_table so btusb_probe() finds them on the second lookup and sets BTUSB_MEDIATEK, which triggers btmtk_usb_setup() for firmware download.

Tested On

  • Board: ASUS ROG CROSSHAIR X870E HERO
  • Chip: MediaTek MT6639 / MT7927 (Filogic 380)
  • Kernel: 6.17.0-14-generic
  • OS: Ubuntu 24.04.4 LTS (Noble)
  • WiFi: Working (wlp9s0, 2.4/5GHz)
  • Bluetooth: Working (hci0, BT 5.4, BD F8:3D:C6:94:CE:A9)

Credits & References

@webskin
Copy link

webskin commented Mar 1, 2026

wonderful ! I will give it a try

@themagicalmammal
Copy link

Damn finally some good news

@luoye2333
Copy link

luoye2333 commented Mar 6, 2026

好复杂...要不还是把mt7927拆了换ax210?

@syntesys87
Copy link

syntesys87 commented Mar 10, 2026

Not working on clean debian 13, this cp does not find the file: sudo cp -r mediatek-mt7927-2.1 /usr/src/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment