feat: unify Bluetooth support and add ZLP quirk

This commit is contained in:
Shen Mintao
2026-07-25 15:49:53 +08:00
parent 6550131e18
commit 13baa9b0b1
14 changed files with 267 additions and 101 deletions
+2 -3
View File
@@ -1,7 +1,6 @@
/.gitattributes text eol=lf /.gitattributes text eol=lf
tests/issue63-btusb-zlp/*.patch -whitespace drivers/aic8800/aic_zlp_quirk/*.c text eol=lf
tests/issue63-btusb-zlp/*.sh text eol=lf drivers/aic8800/aic_zlp_quirk/Makefile text eol=lf
tests/issue63-zlp-quirk/*.c text eol=lf
tests/issue63-zlp-quirk/*.conf text eol=lf tests/issue63-zlp-quirk/*.conf text eol=lf
tests/issue63-zlp-quirk/*.md text eol=lf tests/issue63-zlp-quirk/*.md text eol=lf
tests/issue63-zlp-quirk/*.sh text eol=lf tests/issue63-zlp-quirk/*.sh text eol=lf
+4 -1
View File
@@ -4,13 +4,16 @@
This automated installation script (`install.sh`) installs the AIC8800 Wi-Fi This automated installation script (`install.sh`) installs the AIC8800 Wi-Fi
driver and firmware loader on Linux systems. Wi-Fi/Bluetooth combo adapters use driver and firmware loader on Linux systems. Wi-Fi/Bluetooth combo adapters use
the standard kernel `btusb` driver after firmware initialization. the standard kernel `btusb` driver after firmware initialization. For USB
device `368b:8d81`, it also installs a device-scoped ACL bulk TX ZLP companion
module without replacing the distribution's `btusb.ko`.
- Automatic Secure Boot detection - Automatic Secure Boot detection
- Automatic dependency installation - Automatic dependency installation
- Automatic driver compilation and installation - Automatic driver compilation and installation
- Automatic module loading on boot - Automatic module loading on boot
- Automatic cleanup of obsolete `aic_btusb` configuration - Automatic cleanup of obsolete `aic_btusb` configuration
- Automatic `aic_zlp_quirk` handling for the validated `368b:8d81` device
- Wi-Fi-only and Wi-Fi/Bluetooth combo adapter support from the same branch - Wi-Fi-only and Wi-Fi/Bluetooth combo adapter support from the same branch
- Comprehensive error handling - Comprehensive error handling
- Colored output and logging - Colored output and logging
+23 -3
View File
@@ -10,8 +10,8 @@ This driver is for the AIC8800D80 chipset, supported by devices such as the Tend
> to avoid the deterministic firmware upload timeout at `0x170400`. Use > to avoid the deterministic firmware upload timeout at `0x170400`. Use
> `main` when `chip_mcu_id=0` or when the MCU revision is unknown. > `main` when `chip_mcu_id=0` or when the MCU revision is unknown.
> >
> Hardware revision takes precedence over the Bluetooth feature branch. MCU1 > Hardware revision determines the firmware branch. MCU1 devices should use
> devices should remain on `legacy-mcu1`, which initializes Bluetooth for the > `legacy-mcu1`, which also initializes Bluetooth for the
> kernel's standard `btusb` driver. After switching branches, rerun > kernel's standard `btusb` driver. After switching branches, rerun
> `sudo ./install.sh` and reboot; switching the Git branch alone does not > `sudo ./install.sh` and reboot; switching the Git branch alone does not
> replace the firmware already installed under `/lib/firmware`. > replace the firmware already installed under `/lib/firmware`.
@@ -25,6 +25,13 @@ adapters. On combo devices, `aic_load_fw` uploads the AIC firmware and the
standard Linux `btusb` driver handles the Bluetooth HCI interface. The obsolete standard Linux `btusb` driver handles the Bluetooth HCI interface. The obsolete
custom `aic_btusb` module is not used. custom `aic_btusb` module is not used.
USB device `368b:8d81` also uses the bundled `aic_zlp_quirk` companion module.
It adds the Bluetooth ACL bulk TX zero-length-packet behavior validated in
[issue #63](https://github.com/shenmintao/aic8800d80/issues/63), while leaving
the distribution's original `btusb.ko` installed and bound to the device. The
quirk is filtered to that VID:PID and fails closed when the required kernel
probe support is unavailable.
### Disclaimer ### Disclaimer
I did not develop this software, The code is sourced from the Tenda U11 driver. I only made some modifications to the code to adapt it to newer kernel versions. Apart from compilation issues, I am unable to address other problems. I did not develop this software, The code is sourced from the Tenda U11 driver. I only made some modifications to the code to adapt it to newer kernel versions. Apart from compilation issues, I am unable to address other problems.
@@ -126,7 +133,7 @@ interface, so the Bluetooth path remains inactive.
Verify the expected modules and controller with: Verify the expected modules and controller with:
```bash ```bash
lsmod | grep -E 'aic_load_fw|aic8800_fdrv|btusb' lsmod | grep -E 'aic_load_fw|aic8800_fdrv|aic_zlp_quirk|btusb'
lsusb -t lsusb -t
bluetoothctl list bluetoothctl list
``` ```
@@ -152,3 +159,16 @@ The installer removes active references to the retired `aic_btusb` integration.
It does not force-load `btusb` or globally change the Bluetooth rfkill state; It does not force-load `btusb` or globally change the Bluetooth rfkill state;
normal kernel device matching and the user's system policy remain in control. normal kernel device matching and the user's system policy remain in control.
For `368b:8d81`, verify the ZLP hook and its injection counter while Bluetooth
traffic is active:
```bash
cat /sys/module/aic_zlp_quirk/parameters/hook
cat /sys/module/aic_zlp_quirk/parameters/injections
```
The Wi-Fi-reset recovery behavior tracked in
[issue #53](https://github.com/shenmintao/aic8800d80/issues/53) remains a known
limitation: after an airplane-mode or hotspot reset, Bluetooth may require a
physical unplug/replug of the adapter.
+3 -1
View File
@@ -58,7 +58,9 @@ sudo systemctl reboot
After reboot, the Wi-Fi module and firmware loader will be available. On combo After reboot, the Wi-Fi module and firmware loader will be available. On combo
adapters, Bluetooth is handled by the standard `btusb` kernel module after adapters, Bluetooth is handled by the standard `btusb` kernel module after
firmware initialization. firmware initialization. USB device `368b:8d81` also autoloads the packaged
`aic_zlp_quirk` companion module for its required Bluetooth ACL bulk TX zero
packet behavior; the distribution's `btusb` module is not replaced.
This RPM is built for the kernel reported by `uname -r`. Rebuild and reinstall This RPM is built for the kernel reported by `uname -r`. Rebuild and reinstall
it after a Bazzite kernel upgrade. it after a Bazzite kernel upgrade.
+9 -2
View File
@@ -5,7 +5,7 @@
Name: aic8800d80 Name: aic8800d80
Version: %{shortcommit} Version: %{shortcommit}
Release: 1%{?dist} Release: 1%{?dist}
Summary: AIC8800 USB Wi-Fi and Bluetooth firmware driver Summary: AIC8800 USB Wi-Fi, Bluetooth firmware, and ZLP quirk driver
License: GPL-2.0-only License: GPL-2.0-only
URL: https://github.com/shenmintao/aic8800d80 URL: https://github.com/shenmintao/aic8800d80
@@ -24,7 +24,9 @@ Requires(postun): /usr/sbin/depmod
%description %description
Out-of-tree AIC8800 USB driver with Wi-Fi support, Bluetooth firmware loading, Out-of-tree AIC8800 USB driver with Wi-Fi support, Bluetooth firmware loading,
udev mode-switch rules, and all firmware variants shipped by the upstream udev mode-switch rules, and all firmware variants shipped by the upstream
repository. Combo adapters use the standard Linux btusb transport driver. repository. Combo adapters use the standard Linux btusb transport driver. A
device-scoped companion module supplies the required ACL bulk TX ZLP behavior
for USB device 368b:8d81 without replacing the distribution btusb module.
%prep %prep
%autosetup -n %{name}-%{commit} %autosetup -n %{name}-%{commit}
@@ -44,6 +46,10 @@ install -Dpm0644 \
drivers/aic8800/aic_load_fw/aic_load_fw.ko \ drivers/aic8800/aic_load_fw/aic_load_fw.ko \
%{buildroot}/usr/lib/modules/%{kver}/kernel/drivers/net/wireless/aic8800/aic_load_fw.ko %{buildroot}/usr/lib/modules/%{kver}/kernel/drivers/net/wireless/aic8800/aic_load_fw.ko
install -Dpm0644 \
drivers/aic8800/aic_zlp_quirk/aic_zlp_quirk.ko \
%{buildroot}/usr/lib/modules/%{kver}/kernel/drivers/bluetooth/aic8800/aic_zlp_quirk.ko
install -Dpm0644 \ install -Dpm0644 \
aic.rules \ aic.rules \
%{buildroot}/usr/lib/udev/rules.d/90-aic8800-mode-switch.rules %{buildroot}/usr/lib/udev/rules.d/90-aic8800-mode-switch.rules
@@ -65,6 +71,7 @@ cp -a fw/aic8800* %{buildroot}/usr/lib/firmware/
%dir /usr/lib/modules/%{kver}/kernel/drivers/net/wireless/aic8800 %dir /usr/lib/modules/%{kver}/kernel/drivers/net/wireless/aic8800
/usr/lib/modules/%{kver}/kernel/drivers/net/wireless/aic8800/aic8800_fdrv.ko /usr/lib/modules/%{kver}/kernel/drivers/net/wireless/aic8800/aic8800_fdrv.ko
/usr/lib/modules/%{kver}/kernel/drivers/net/wireless/aic8800/aic_load_fw.ko /usr/lib/modules/%{kver}/kernel/drivers/net/wireless/aic8800/aic_load_fw.ko
/usr/lib/modules/%{kver}/kernel/drivers/bluetooth/aic8800/aic_zlp_quirk.ko
/usr/lib/udev/rules.d/90-aic8800-mode-switch.rules /usr/lib/udev/rules.d/90-aic8800-mode-switch.rules
%config(noreplace) /etc/usb_modeswitch.d/1111:1111 %config(noreplace) /etc/usb_modeswitch.d/1111:1111
/usr/lib/firmware/aic8800* /usr/lib/firmware/aic8800*
+32 -3
View File
@@ -19,6 +19,7 @@ echo ""
echo "2. USB interfaces and bound drivers:" echo "2. USB interfaces and bound drivers:"
bt_interface_found=false bt_interface_found=false
btusb_bound=false btusb_bound=false
zlp_target_found=false
for dev in /sys/bus/usb/devices/*; do for dev in /sys/bus/usb/devices/*; do
[ -f "$dev/idVendor" ] || continue [ -f "$dev/idVendor" ] || continue
[ -f "$dev/idProduct" ] || continue [ -f "$dev/idProduct" ] || continue
@@ -31,6 +32,9 @@ for dev in /sys/bus/usb/devices/*; do
esac esac
echo " Device: $vid:$pid" echo " Device: $vid:$pid"
if [ "$vid" = "368b" ] && [ "$pid" = "8d81" ]; then
zlp_target_found=true
fi
for intf in "$dev"/*:*; do for intf in "$dev"/*:*; do
[ -d "$intf" ] || continue [ -d "$intf" ] || continue
class=$(cat "$intf/bInterfaceClass" 2>/dev/null) class=$(cat "$intf/bInterfaceClass" 2>/dev/null)
@@ -50,7 +54,7 @@ done
echo "" echo ""
echo "3. Relevant kernel modules (combo expectation: aic_load_fw + btusb):" echo "3. Relevant kernel modules (combo expectation: aic_load_fw + btusb):"
lsmod | grep -E '^(aic_load_fw|aic8800_fdrv|aic_btusb|btusb|bluetooth)[[:space:]]' || \ lsmod | grep -E '^(aic_load_fw|aic8800_fdrv|aic_zlp_quirk|aic_btusb|btusb|bluetooth)[[:space:]]' || \
echo " No related module is currently loaded" echo " No related module is currently loaded"
echo "" echo ""
@@ -64,8 +68,8 @@ else
fi fi
echo "" echo ""
echo "5. Firmware, btusb, and HCI log messages:" echo "5. Firmware, btusb, ZLP quirk, and HCI log messages:"
dmesg 2>/dev/null | grep -iE 'fw_patch|fw_adid|aicbt|bluetooth|btusb|hci' | tail -80 || true dmesg 2>/dev/null | grep -iE 'fw_patch|fw_adid|aicbt|aic_zlp_quirk|bluetooth|btusb|hci' | tail -80 || true
echo "" echo ""
echo "6. Bluetooth rfkill state:" echo "6. Bluetooth rfkill state:"
@@ -110,6 +114,27 @@ if [ "$legacy_refs_found" = false ]; then
fi fi
echo "" echo ""
echo "8. Device-scoped Bluetooth ACL ZLP quirk:"
if [ "$zlp_target_found" = true ]; then
if [ -d /sys/module/aic_zlp_quirk ]; then
zlp_hook="unknown"
zlp_injections="unavailable"
[ -r /sys/module/aic_zlp_quirk/parameters/hook ] && \
zlp_hook=$(cat /sys/module/aic_zlp_quirk/parameters/hook)
[ -r /sys/module/aic_zlp_quirk/parameters/injections ] && \
zlp_injections=$(cat /sys/module/aic_zlp_quirk/parameters/injections)
echo " Target 368b:8d81 present"
echo " aic_zlp_quirk loaded: yes"
echo " active hook: $zlp_hook"
echo " ZLP injections: $zlp_injections"
else
echo " Target 368b:8d81 present, but aic_zlp_quirk is not loaded"
fi
else
echo " Target 368b:8d81 not present; quirk is not required"
fi
echo ""
echo "=== Assessment ===" echo "=== Assessment ==="
if ! lsmod | awk '{print $1}' | grep -qx 'aic_load_fw'; then if ! lsmod | awk '{print $1}' | grep -qx 'aic_load_fw'; then
echo "- aic_load_fw is not loaded; run: sudo modprobe aic8800_fdrv" echo "- aic_load_fw is not loaded; run: sudo modprobe aic8800_fdrv"
@@ -125,5 +150,9 @@ fi
if [ "$bt_interface_found" = false ]; then if [ "$bt_interface_found" = false ]; then
echo "- No Bluetooth HCI USB interface was found. This is normal for a Wi-Fi-only adapter." echo "- No Bluetooth HCI USB interface was found. This is normal for a Wi-Fi-only adapter."
fi fi
if [ "$zlp_target_found" = true ] && [ ! -d /sys/module/aic_zlp_quirk ]; then
echo "- Device 368b:8d81 requires the ACL ZLP quirk, but the module is not loaded."
echo " Try: sudo modprobe aic_zlp_quirk"
fi
echo "=== Diagnostics complete ===" echo "=== Diagnostics complete ==="
+5
View File
@@ -13,4 +13,9 @@ BUILT_MODULE_NAME[1]="aic_load_fw"
BUILT_MODULE_LOCATION[1]="drivers/aic8800/aic_load_fw" BUILT_MODULE_LOCATION[1]="drivers/aic8800/aic_load_fw"
DEST_MODULE_LOCATION[1]="/updates/dkms" DEST_MODULE_LOCATION[1]="/updates/dkms"
# Device-scoped standard-btusb ACL bulk TX ZLP quirk (368b:8d81 only)
BUILT_MODULE_NAME[2]="aic_zlp_quirk"
BUILT_MODULE_LOCATION[2]="drivers/aic8800/aic_zlp_quirk"
DEST_MODULE_LOCATION[2]="/updates/dkms"
AUTOINSTALL="yes" AUTOINSTALL="yes"
+7
View File
@@ -1,8 +1,10 @@
CONFIG_AIC_LOADFW_SUPPORT := m CONFIG_AIC_LOADFW_SUPPORT := m
CONFIG_AIC8800_WLAN_SUPPORT := m CONFIG_AIC8800_WLAN_SUPPORT := m
CONFIG_AIC_ZLP_QUIRK := m
obj-$(CONFIG_AIC_LOADFW_SUPPORT) += aic_load_fw/ obj-$(CONFIG_AIC_LOADFW_SUPPORT) += aic_load_fw/
obj-$(CONFIG_AIC8800_WLAN_SUPPORT) += aic8800_fdrv/ obj-$(CONFIG_AIC8800_WLAN_SUPPORT) += aic8800_fdrv/
obj-$(CONFIG_AIC_ZLP_QUIRK) += aic_zlp_quirk/
########## config option ########## ########## config option ##########
export CONFIG_USE_FW_REQUEST = n export CONFIG_USE_FW_REQUEST = n
@@ -51,6 +53,7 @@ KVER ?= $(shell uname -r)
KDIR ?= /lib/modules/$(KVER)/build KDIR ?= /lib/modules/$(KVER)/build
PWD = $(shell pwd) PWD = $(shell pwd)
MODDESTDIR = /lib/modules/$(KVER)/kernel/drivers/net/wireless/aic8800 MODDESTDIR = /lib/modules/$(KVER)/kernel/drivers/net/wireless/aic8800
BTMODDESTDIR = /lib/modules/$(KVER)/kernel/drivers/bluetooth/aic8800
SUBARCH = $(shell uname -m | sed -e s/i.86/i386/ -e s/armv.l/arm/ -e s/aarch64/arm64/ -e s/loongarch64/loongarch/ -e s/loong64/loongarch/ -e s/riscv64/riscv/) SUBARCH = $(shell uname -m | sed -e s/i.86/i386/ -e s/armv.l/arm/ -e s/aarch64/arm64/ -e s/loongarch64/loongarch/ -e s/loong64/loongarch/ -e s/riscv64/riscv/)
ARCH ?= $(SUBARCH) ARCH ?= $(SUBARCH)
CROSS_COMPILE ?= CROSS_COMPILE ?=
@@ -78,16 +81,20 @@ modules:
install: install:
mkdir -p $(MODDESTDIR) mkdir -p $(MODDESTDIR)
mkdir -p $(BTMODDESTDIR)
install -p -m 644 aic_load_fw/aic_load_fw.ko $(MODDESTDIR)/ install -p -m 644 aic_load_fw/aic_load_fw.ko $(MODDESTDIR)/
install -p -m 644 aic8800_fdrv/aic8800_fdrv.ko $(MODDESTDIR)/ install -p -m 644 aic8800_fdrv/aic8800_fdrv.ko $(MODDESTDIR)/
install -p -m 644 aic_zlp_quirk/aic_zlp_quirk.ko $(BTMODDESTDIR)/
/sbin/depmod -a ${KVER} /sbin/depmod -a ${KVER}
uninstall: uninstall:
rm -rfv $(MODDESTDIR)/aic_load_fw.ko rm -rfv $(MODDESTDIR)/aic_load_fw.ko
rm -rfv $(MODDESTDIR)/aic8800_fdrv.ko rm -rfv $(MODDESTDIR)/aic8800_fdrv.ko
rm -rfv $(BTMODDESTDIR)/aic_zlp_quirk.ko
/sbin/depmod -a ${KVER} /sbin/depmod -a ${KVER}
clean: clean:
cd aic_load_fw/;make clean;cd .. cd aic_load_fw/;make clean;cd ..
cd aic8800_fdrv/;make clean;cd .. cd aic8800_fdrv/;make clean;cd ..
cd aic_zlp_quirk/;make clean;cd ..
rm -rf modules.order Module.symvers .modules.order.cmd .Module.symvers.cmd .tmp_versions/ rm -rf modules.order Module.symvers .modules.order.cmd .Module.symvers.cmd .tmp_versions/
+18
View File
@@ -0,0 +1,18 @@
ifneq ($(KERNELRELEASE),)
obj-m += aic_zlp_quirk.o
else
KVER ?= $(shell uname -r)
KDIR ?= /lib/modules/$(KVER)/build
.PHONY: all clean
all:
$(MAKE) -C $(KDIR) M=$(CURDIR) modules
clean:
$(MAKE) -C $(KDIR) M=$(CURDIR) clean
endif
@@ -224,5 +224,6 @@ module_exit(aic_zlp_quirk_exit);
MODULE_AUTHOR("Shen Mintao <cx330.shen@autocore.ai>"); MODULE_AUTHOR("Shen Mintao <cx330.shen@autocore.ai>");
MODULE_DESCRIPTION("AIC 8800D80 standard btusb ACL bulk TX ZLP quirk"); MODULE_DESCRIPTION("AIC 8800D80 standard btusb ACL bulk TX ZLP quirk");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_VERSION("0.1"); MODULE_VERSION("1.0");
MODULE_SOFTDEP("pre: btusb"); MODULE_SOFTDEP("pre: btusb");
MODULE_ALIAS("usb:v368Bp8D81d*dc*dsc*dp*ic*isc*ip*in*");
+64
View File
@@ -326,6 +326,7 @@ check_kernel_build_tree() {
cleanup_legacy_bluetooth_config() { cleanup_legacy_bluetooth_config() {
local legacy_conf="/etc/modprobe.d/aic8800-bt.conf" local legacy_conf="/etc/modprobe.d/aic8800-bt.conf"
local legacy_udev="/etc/udev/rules.d/90-aic8800-mode-switch.rules" local legacy_udev="/etc/udev/rules.d/90-aic8800-mode-switch.rules"
local legacy_package
local changed=false local changed=false
if [ -f "$legacy_conf" ] && grep -Eq '^[[:space:]]*(softdep|alias)[^#]*aic_btusb([[:space:]]|$)' "$legacy_conf"; then if [ -f "$legacy_conf" ] && grep -Eq '^[[:space:]]*(softdep|alias)[^#]*aic_btusb([[:space:]]|$)' "$legacy_conf"; then
@@ -358,6 +359,21 @@ cleanup_legacy_bluetooth_config() {
fi fi
fi fi
# Remove the two issue #63 diagnostic DKMS packages before the production
# quirk is installed as part of aic8800/1.0.0. A patched btusb may remain
# active in memory until reboot, but DKMS restores the distribution module
# on disk when its test package is removed.
for legacy_package in "btusb-aic-zlp/0.1" "aic-zlp-quirk/0.1"; do
if dkms status 2>/dev/null | grep -q "^${legacy_package},"; then
print_info "Removing superseded test package ${legacy_package}..."
if dkms remove "$legacy_package" --all >> "$LOG_FILE" 2>&1; then
changed=true
else
print_warning "Could not remove ${legacy_package}; remove it manually before reboot."
fi
fi
done
if [ "$changed" = true ]; then if [ "$changed" = true ]; then
print_success "Legacy Bluetooth configuration cleaned up." print_success "Legacy Bluetooth configuration cleaned up."
fi fi
@@ -460,6 +476,11 @@ BUILT_MODULE_NAME[1]="aic_load_fw"
BUILT_MODULE_LOCATION[1]="drivers/aic8800/aic_load_fw" BUILT_MODULE_LOCATION[1]="drivers/aic8800/aic_load_fw"
DEST_MODULE_LOCATION[1]="/updates/dkms" DEST_MODULE_LOCATION[1]="/updates/dkms"
# Quirk ZLP para Bluetooth ACL bulk TX (somente 368b:8d81)
BUILT_MODULE_NAME[2]="aic_zlp_quirk"
BUILT_MODULE_LOCATION[2]="drivers/aic8800/aic_zlp_quirk"
DEST_MODULE_LOCATION[2]="/updates/dkms"
AUTOINSTALL="yes" AUTOINSTALL="yes"
EOF EOF
@@ -569,6 +590,20 @@ refresh_initramfs() {
# Module Loading # Module Loading
############################################################################# #############################################################################
aic_zlp_target_present() {
local device
for device in /sys/bus/usb/devices/*; do
[ -r "$device/idVendor" ] || continue
[ -r "$device/idProduct" ] || continue
[ "$(cat "$device/idVendor")" = "368b" ] || continue
[ "$(cat "$device/idProduct")" = "8d81" ] || continue
return 0
done
return 1
}
load_module() { load_module() {
print_step "Loading kernel modules..." print_step "Loading kernel modules..."
@@ -611,6 +646,19 @@ load_module() {
fi fi
print_info "Combo adapters use the standard btusb driver when their Bluetooth interface appears." print_info "Combo adapters use the standard btusb driver when their Bluetooth interface appears."
# The module has a USB alias and normally autoloads when 368b:8d81 appears.
# Explicitly load it here as well when that device was already present before
# DKMS installation and therefore did not generate a new modalias event.
if aic_zlp_target_present; then
print_info "Loading the 368b:8d81 Bluetooth ACL ZLP quirk..."
if modprobe aic_zlp_quirk >> "$LOG_FILE" 2>&1; then
print_success "Device-scoped Bluetooth ZLP quirk is active."
else
print_warning "The ZLP quirk could not attach; system btusb remains unchanged."
print_info "Check CONFIG_KPROBES, Secure Boot, and: sudo dmesg | grep aic_zlp_quirk"
fi
fi
} }
############################################################################# #############################################################################
@@ -643,6 +691,20 @@ verify_installation() {
print_info "No Bluetooth controller is present (normal for Wi-Fi-only adapters or when no combo adapter is connected)." print_info "No Bluetooth controller is present (normal for Wi-Fi-only adapters or when no combo adapter is connected)."
fi fi
if aic_zlp_target_present; then
if lsmod | awk '{print $1}' | grep -qx 'aic_zlp_quirk'; then
local zlp_hook="unknown"
if [ -r /sys/module/aic_zlp_quirk/parameters/hook ]; then
zlp_hook=$(cat /sys/module/aic_zlp_quirk/parameters/hook)
fi
print_success "Bluetooth ACL ZLP quirk is loaded (hook: $zlp_hook)."
else
print_warning "USB device 368b:8d81 is present but aic_zlp_quirk is not loaded."
fi
else
print_info "Bluetooth ZLP quirk is installed but inactive (no 368b:8d81 device present)."
fi
echo "" echo ""
print_info "Loaded AIC modules:" print_info "Loaded AIC modules:"
lsmod | grep aic || echo " (none)" lsmod | grep aic || echo " (none)"
@@ -690,6 +752,7 @@ show_final_instructions() {
echo "" echo ""
echo "✓ Wi-Fi driver and firmware loader installed via DKMS" echo "✓ Wi-Fi driver and firmware loader installed via DKMS"
echo "✓ Combo adapters use the standard Linux btusb driver" echo "✓ Combo adapters use the standard Linux btusb driver"
echo "✓ Device-scoped Bluetooth ACL ZLP quirk installed for 368b:8d81"
echo "✓ Automatic rebuild enabled for kernel updates" echo "✓ Automatic rebuild enabled for kernel updates"
echo "✓ Firmware installed in /lib/firmware/" echo "✓ Firmware installed in /lib/firmware/"
echo "" echo ""
@@ -721,6 +784,7 @@ show_final_instructions() {
echo "" echo ""
echo "• Check loaded modules:" echo "• Check loaded modules:"
echo " ${BLUE}lsmod | grep -E 'aic|btusb'${NC}" echo " ${BLUE}lsmod | grep -E 'aic|btusb'${NC}"
echo " ${BLUE}cat /sys/module/aic_zlp_quirk/parameters/{hook,injections}${NC}"
echo "" echo ""
echo "• Manually load the Wi-Fi module and firmware loader:" echo "• Manually load the Wi-Fi module and firmware loader:"
echo " ${BLUE}sudo modprobe aic8800_fdrv${NC}" echo " ${BLUE}sudo modprobe aic8800_fdrv${NC}"
+74 -80
View File
@@ -1,104 +1,100 @@
# Issue #63: standard `btusb` ZLP companion-module test # Issue #63: standard `btusb` ACL ZLP support
This experiment keeps the normal `aic_load_fw + system btusb` architecture. The `aic_zlp_quirk` companion module supplies the Bluetooth ACL bulk TX
It does not install or bind the vendor `aic_btusb` transport, and it does not zero-length-packet behavior confirmed in
replace the distribution's `btusb.ko`. [issue #63](https://github.com/shenmintao/aic8800d80/issues/63). It is now part
of the normal `aic8800` DKMS build rather than a replacement for the
distribution's Bluetooth driver.
The underlying ZLP behavior was confirmed in The validated failure was specific and reproducible: AAC playback through USB
[issue #63](https://github.com/shenmintao/aic8800d80/issues/63): AAC playback device `368b:8d81` stalled after about one minute, while SBC remained stable.
that previously stalled after about one minute remained stable for more than Adding `URB_ZERO_PACKET` to the ACL bulk OUT URBs kept AAC connected for more
one hour with the standard `btusb` ZLP patch, including after the obsolete than one hour. The standalone module was then verified with the system
`aic_btusb` module was removed. `btusb`, no loaded `aic_btusb`, and 2,113 observed ZLP injections.
The small `aic_zlp_quirk.ko` module first tries to attach a kretprobe to the ## Architecture and scope
standard `btusb` function that allocates Bluetooth ACL bulk OUT URBs. The
target is module-qualified as `btusb:alloc_bulk_urb`, avoiding similarly named
symbols in unrelated USB drivers.
Some distribution builds inline that private `btusb` function. When the The module first tries to attach a kretprobe to the standard `btusb` function
preferred hook is unavailable, the same module falls back to the stable that allocates ACL bulk OUT URBs. The target is module-qualified as
`usb_submit_urb` entry point. The fallback requires all of the following before `btusb:alloc_bulk_urb`, avoiding similarly named symbols in unrelated USB
changing an URB: drivers.
- USB device `368b:8d81`; Some distribution builds inline that private function. When the preferred hook
- bulk OUT transfer; is unavailable, the module falls back to the stable `usb_submit_urb` entry
- endpoint declared by Bluetooth interface 0 (`e0/01/01`). point. The fallback changes an URB only when all of these checks pass:
Both paths add `URB_ZERO_PACKET` before the USB core submits the transfer. The - USB device is exactly `368b:8d81`;
Wi-Fi interface and unrelated USB devices are left unchanged. - the transfer is bulk OUT;
- the endpoint belongs to Bluetooth interface 0 (`e0/01/01`).
The hook fails closed: if neither probe can be installed or kprobes are Both paths add only `URB_ZERO_PACKET`. Wi-Fi interfaces and unrelated USB
disabled, the companion module refuses to load and the system `btusb` remains devices are unchanged. If neither probe can be installed or kprobes are
unchanged. disabled, the module refuses to load and system `btusb` remains unchanged.
## Before installing The module carries a USB modalias for `368b:8d81`, so it is inactive on other
hardware and normally autoloads only when the validated device appears.
First remove the earlier patched-`btusb` diagnostic build, if installed: ## Install from the unified branch
```bash ```bash
cd ../issue63-btusb-zlp git fetch origin
sudo ./btusb-zlp-test.sh remove git switch test/unified-wifi-bt-zlp
git pull --ff-only
sudo ./install.sh
sudo reboot
``` ```
An obsolete `aic_btusb` installation must also be unloaded and removed before The installer removes the earlier `btusb-aic-zlp/0.1` and
this test. Verify that the AIC Bluetooth interfaces use the system driver: `aic-zlp-quirk/0.1` diagnostic DKMS packages when present. To remove them
manually before installation, use:
```bash
sudo dkms remove btusb-aic-zlp/0.1 --all
sudo dkms remove aic-zlp-quirk/0.1 --all
sudo depmod -a
```
The unified installer also removes active configuration left by the obsolete
custom `aic_btusb` transport.
## Verify
Confirm that system `btusb` owns Bluetooth interfaces 0/1 and that the quirk is
loaded:
```bash ```bash
lsusb -t lsusb -t
lsmod | grep -E '^(btusb|aic_btusb)\b' lsmod | grep -E '^(btusb|aic_zlp_quirk|aic_btusb)\b'
modinfo -n btusb
modinfo -n aic_zlp_quirk
cat /sys/module/aic_zlp_quirk/parameters/hook
cat /sys/module/aic_zlp_quirk/parameters/injections
sudo ./diagnose_bt.sh
``` ```
## Install Expected results include:
Install the normal build dependencies. For Fedora:
```bash
sudo dnf install dkms gcc make kernel-devel-$(uname -r)
```
Then install and load the companion module:
```bash
cd tests/issue63-zlp-quirk
sudo ./aic-zlp-quirk-test.sh install
./aic-zlp-quirk-test.sh status
```
Expected status includes:
```text ```text
quirk loaded: yes Bluetooth interfaces 0/1: btusb
aic_btusb: not loaded
aic_zlp_quirk: loaded
active hook: btusb:alloc_bulk_urb active hook: btusb:alloc_bulk_urb
legacy aic_btusb: not loaded
AIC BT driver: btusb
``` ```
`active hook: usb_submit_urb` is also valid when the distribution compiler `active hook: usb_submit_urb` is also valid when the compiler inlined the
inlined the preferred private `btusb` function. preferred function. During Bluetooth traffic, the `injections` value must
increase.
Select AAC and play audio for at least one hour: For the promotion test, select AAC and play audio for at least one hour while
also confirming that Wi-Fi scan, association, DHCP, and real traffic remain
working.
```bash ## Isolated retest helper
bluetoothctl scan off
pactl set-card-profile bluez_card.28_6F_40_46_AB_B1 a2dp-sink-aac
```
While audio is playing, the `ZLP injections` counter should increase: `aic-zlp-quirk-test.sh` remains available only for isolated issue #63 retests.
It builds the same canonical source from
```bash `drivers/aic8800/aic_zlp_quirk/aic_zlp_quirk.c` as a separate DKMS package. A
./aic-zlp-quirk-test.sh status normal installation should use the repository-level `install.sh` instead.
sudo dmesg | grep -i aic_zlp_quirk
```
## Remove
```bash
sudo ./aic-zlp-quirk-test.sh remove
./aic-zlp-quirk-test.sh status
```
Removal unloads only `aic_zlp_quirk.ko`. The distribution `btusb.ko` was never
overwritten and remains the Bluetooth transport throughout the test.
## Kernel requirements ## Kernel requirements
@@ -108,8 +104,6 @@ overwritten and remains the Bluetooth transport throughout the test.
`usb_submit_urb` symbol; `usb_submit_urb` symbol;
- a valid module signature when Secure Boot policy requires one. - a valid module signature when Secure Boot policy requires one.
The `alloc_bulk_urb` function is present with the same signature in Linux The preferred function has the same signature in Linux 5.15, 6.1, 6.6, 6.12,
5.15, 6.1, 6.6, 6.12, 6.18, and 7.1.3, although compilers may inline it. The 6.18, and 7.1.3, although compilers may inline it. DKMS builds one module for
fallback avoids depending on that implementation detail. DKMS compiles a each installed kernel from the single canonical source file.
separate binary for each installed kernel while the repository maintains one
small source file.
@@ -9,6 +9,8 @@ KERNEL_BUILD_DIR="/lib/modules/${KERNEL_RELEASE}/build"
SOURCE_DIR="/usr/src/${PACKAGE_NAME}-${PACKAGE_VERSION}" SOURCE_DIR="/usr/src/${PACKAGE_NAME}-${PACKAGE_VERSION}"
MODULES_LOAD_FILE="/etc/modules-load.d/${PACKAGE_NAME}.conf" MODULES_LOAD_FILE="/etc/modules-load.d/${PACKAGE_NAME}.conf"
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd -- "${SCRIPT_DIR}/../.." && pwd)"
QUIRK_SOURCE="${REPO_ROOT}/drivers/aic8800/aic_zlp_quirk/aic_zlp_quirk.c"
log() { log() {
printf '[aic-zlp-quirk-test] %s\n' "$*" printf '[aic-zlp-quirk-test] %s\n' "$*"
@@ -53,7 +55,7 @@ patched_btusb_installed() {
copy_sources() { copy_sources() {
install -d "${SOURCE_DIR}" install -d "${SOURCE_DIR}"
install -m 0644 "${SCRIPT_DIR}/aic_zlp_quirk.c" "${SOURCE_DIR}/" install -m 0644 "${QUIRK_SOURCE}" "${SOURCE_DIR}/"
install -m 0644 "${SCRIPT_DIR}/Makefile" "${SOURCE_DIR}/" install -m 0644 "${SCRIPT_DIR}/Makefile" "${SOURCE_DIR}/"
install -m 0644 "${SCRIPT_DIR}/dkms.conf" "${SOURCE_DIR}/" install -m 0644 "${SCRIPT_DIR}/dkms.conf" "${SOURCE_DIR}/"
} }
+20 -5
View File
@@ -1,9 +1,10 @@
# Unified Wi-Fi and Bluetooth branch test # Unified Wi-Fi, Bluetooth, and ZLP branch test
This branch tests replacing the separate `main` and `bluetooth` branches with This branch tests replacing the separate `main` and `bluetooth` branches with
one driver and installer. The kernel driver, firmware, and DKMS configuration one driver and installer. The Wi-Fi driver and firmware were already identical
were already identical on both branches. This test unifies their installer, on both branches. This test unifies their installer, migration, diagnostics,
migration, diagnostics, packaging description, and documentation. packaging, and documentation, and adds the device-scoped ZLP fix from issue
#63 as a third DKMS module.
The expected architecture is: The expected architecture is:
@@ -13,6 +14,9 @@ The expected architecture is:
the standard Linux `btusb` driver binds through normal USB device matching. the standard Linux `btusb` driver binds through normal USB device matching.
- A Wi-Fi-only adapter exposes no HCI interface and does not need `btusb`. - A Wi-Fi-only adapter exposes no HCI interface and does not need `btusb`.
- The retired custom `aic_btusb` module is never installed or used. - The retired custom `aic_btusb` module is never installed or used.
- USB device `368b:8d81` autoloads `aic_zlp_quirk`, which adds
`URB_ZERO_PACKET` only to its Bluetooth ACL bulk OUT transfers.
- The distribution's original `btusb.ko` is never replaced.
The installer deliberately does not force-load `btusb` and does not globally The installer deliberately does not force-load `btusb` and does not globally
unblock Bluetooth through rfkill. unblock Bluetooth through rfkill.
@@ -21,7 +25,7 @@ unblock Bluetooth through rfkill.
```bash ```bash
git fetch origin git fetch origin
git switch test/unified-wifi-bt git switch test/unified-wifi-bt-zlp
git pull --ff-only git pull --ff-only
sudo ./install.sh sudo ./install.sh
sudo reboot sudo reboot
@@ -46,6 +50,16 @@ Confirm that:
4. `bluetoothctl` can power on, scan, pair, and exchange real traffic. 4. `bluetoothctl` can power on, scan, pair, and exchange real traffic.
5. No `aic_btusb` module, alias, soft dependency, or udev binding rule remains. 5. No `aic_btusb` module, alias, soft dependency, or udev binding rule remains.
## Test the `368b:8d81` ZLP path
In addition to the combo-adapter checks, confirm that:
1. `aic_zlp_quirk` loads automatically and system `btusb` owns interfaces 0/1.
2. `hook` reports `btusb:alloc_bulk_urb` or `usb_submit_urb`.
3. The `injections` counter increases during Bluetooth audio traffic.
4. AAC playback remains connected for at least one hour.
5. Wi-Fi scan, association, and traffic remain unaffected during the test.
## Collect results ## Collect results
```bash ```bash
@@ -55,6 +69,7 @@ lsusb -t
lsmod | grep -E 'aic|btusb|bluetooth' lsmod | grep -E 'aic|btusb|bluetooth'
iw dev iw dev
bluetoothctl list bluetoothctl list
cat /sys/module/aic_zlp_quirk/parameters/{hook,injections} 2>/dev/null || true
sudo ./diagnose_bt.sh | tee unified-wifi-bt-diagnostic.log sudo ./diagnose_bt.sh | tee unified-wifi-bt-diagnostic.log
sudo journalctl -k -b --no-pager | tee unified-wifi-bt-kernel.log sudo journalctl -k -b --no-pager | tee unified-wifi-bt-kernel.log
``` ```