Getting a clone AIC8800D80 Wi-Fi dongle working on Linux

in progress

Code github.com/rtk94/aic8800d80-clone-dongle

Cheap AX900 and AX300 class Wi-Fi 6 USB dongles built on AICSemi's AIC8800D80 are everywhere on Temu, AliExpress, and eBay. Some of the unbranded ones plug into Linux and show up as a USB CD-ROM instead of a network interface, and no existing driver package recognizes them. This is how I got one working, and how the repo packages it so it keeps working.

The problem

Branded AIC8800D80 adapters (Tenda U11, Cudy, UGREEN, and others) also start out as USB mass storage. They enumerate as a69c:5721 through a69c:572f, appear as a virtual disc, and switch into Wi-Fi mode when that disc is ejected. Existing packages handle this with a udev rule that runs eject on the block device.

The unbranded "Pandora" clones are different. They enumerate as 1111:1111, a placeholder vendor and product ID that matches no known device. Because of that:

  • no driver package lists that ID, so nothing claims the device
  • usb_modeswitch has no entry for it
  • the eject trick that works for the Tenda units does nothing

The device just sits there as storage.

The mode switch

The clone needs a vendor-specific 16-byte SCSI command descriptor block:

FD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F2

It's sent as an ordinary USB mass-storage command, wrapped in the standard 31-byte Command Block Wrapper (CBW). After it lands, the device drops off the bus and re-enumerates as a69c:8d80, the ID the AIC8800 driver already knows.

usb_modeswitch can send arbitrary CBWs, so the fix is a config entry:

DefaultVendor=0x1111
DefaultProduct=0x1111
TargetVendor=0xa69c
TargetProduct=0x8d80
MessageContent="555342438765432100000000000010fd0000000000000000000000000000f2"

Here is that MessageContent byte by byte:

BytesFieldValue
55 53 42 43dCBWSignature"USBC", fixed
87 65 43 21dCBWTagArbitrary tag, echoed back in the status reply
00 00 00 00dCBWDataTransferLength0, no data phase
00bmCBWFlagsDirection bit unused with no data
00bCBWLUNLUN 0
10bCBWCBLength16-byte command
fd 00 … 00 f2CBWCBThe vendor command

Making it automatic

A mode switch you have to run by hand on every plug-in isn't a fix. A udev rule fires it on hotplug:

ACTION=="add", ATTRS{idVendor}=="1111", ATTRS{idProduct}=="1111", \
  RUN+="/bin/sh -c 'if [ -x /usr/sbin/usb_modeswitch ]; then exec /usr/sbin/usb_modeswitch -c /etc/usb_modeswitch.d/1111:1111; elif [ -x /usr/bin/usb_modeswitch ]; then exec /usr/bin/usb_modeswitch -c /etc/usb_modeswitch.d/1111:1111; fi'"

It checks both /usr/sbin and /usr/bin because distros disagree on where usb_modeswitch lives. A few more rules handle firmware variants that re-enumerate as a69c:8d81, a69c:8d83, or 368b:8d81. If the driver doesn't bind those on its own, they write the ID to the driver's new_id in sysfs, and they clear any rfkill soft block on Bluetooth.

One small trap: the config has to be installed as /etc/usb_modeswitch.d/1111:1111, with a colon in the filename. Windows can't check out filenames containing colons, so the repo stores it as 1111_1111 and the installer renames it.

Packaging

The AIC8800 driver isn't in mainline, so it has to be built out of tree for every kernel. The repo's install.sh is a multi-distro DKMS installer. It:

  • detects the package manager (apt, dnf, yum, pacman, zypper) and installs the build dependencies
  • removes any existing aic8800* firmware directories under /lib/firmware, because mismatched firmware versions can hard-freeze the machine
  • installs the firmware, udev rules, and mode-switch config
  • registers the tree with DKMS so the modules rebuild automatically on kernel updates

Bluetooth needs no custom module. Once aic_load_fw uploads the firmware patch, the stock btusb driver handles the HCI interface. Upstream's diagnose_bt.sh checks the usual failure points: missing firmware patch files, a leftover aic_btusb module from another package, and rfkill.

What's mine and what isn't

The driver itself is AICSemi's. It reached me by way of the Tenda U11 vendor drop and shenmintao/aic8800d80, which carried it forward to modern kernels and established that Bluetooth works through stock btusb. My part is the clone-dongle support: the mode-switch config and the udev rules that fire it.

The driver source is GPL-2.0. That isn't a choice I made: it descends from GPL vendor source and its modules declare MODULE_LICENSE("GPL"). Upstream shipped no license file, so the repo adds one. The firmware under fw/ is a proprietary AICSemi binary with no explicit redistribution grant. The repo's NOTICE.md spells out that posture rather than pretending it's a permission.

Tested on

DistroKernelArchResult
Debian 13 (trixie)6.12.95, 6.12.96, 6.12.100x86_64Wi-Fi and Bluetooth working
Ubuntu 25.046.16x86_64Reported upstream
Debian 126.1.0-27x86_64Reported upstream

The repo also has notes for installing on a 2008-era polycarbonate MacBook. USB 2.0 caps real throughput there at roughly 150 to 250 Mb/s whatever the radio negotiates, but it still adds WPA3 and more reliable association with modern access points than the built-in Broadcom card manages.