Author SHA1 Message Date
Shen Mintao 8006daf6c7 fix: refresh Bazzite package for bluetooth branch
Pin the package to the current code commit, ship both maintained modules and all firmware variants, remove obsolete Bluetooth configuration, and document kernel-specific rebuilds.
2026-07-14 17:39:29 +08:00
Shen Mintao 6b8cb98e96 fix: clean up legacy aic_btusb configuration
Sanitize obsolete modprobe and udev rules during upgrades, unload the removed module when possible, and expand Bluetooth diagnostics for stale configuration. Continues the cleanup for #44 and #53.
2026-07-14 17:30:03 +08:00
Shen Mintao 7dc7569312 fix: improve dependency installation diagnostics
Install mode-switch dependencies, support a69c:572f, avoid redundant generic headers when a usable kernel build tree exists, and discover DKMS logs dynamically. Addresses installer portions of #28, #55, #65, #66, and #68.
2026-07-14 17:23:53 +08:00
Shen Mintao 0ed5afba03 fix: retry DKMS install when existing modules block install 2026-06-25 19:55:34 +08:00
Shen Mintao df8a44bf88 fix: handle Volumio and early firmware loading 2026-06-25 19:48:08 +08:00
Shen Mintao 18d4be4228 fix: write radiotap HE fields without struct copy 2026-06-25 19:38:40 +08:00
Shen Mintao 0c9e2f1bca fix: avoid fortify warning in patch info unpack 2026-06-25 19:32:42 +08:00
Shen Mintao 35c077823c fix: support newer kernel cfg80211 APIs 2026-06-25 19:26:59 +08:00
Shen MintaoandClaude Opus 4.7 7d7d9547b8 clean up stale aic_btusb references on bluetooth branch (#53)
This branch already switched to standard btusb (commit 86aa95f), but
several pieces still pointed back at the removed aic_btusb module:

- drivers/aic8800/aic_btusb/ source tree (no longer in build)
- modprobe/aic8800-bt.conf installed to /etc/modprobe.d/, which
  softdep'd btusb to a nonexistent aic_btusb and aliased AIC BT
  interfaces to it. This caused btusb to load without firmware
  having been uploaded, producing HCI_Reset timeout -110 on hci0.
- install.sh still copied that conf into /etc/modprobe.d/
- diagnose_bt.sh still told users to modprobe aic_btusb

diagnose_bt.sh rewritten to flag the residual /etc/modprobe.d/aic8800-bt.conf
on already-installed systems and to advise the correct flow
(aic_load_fw uploads BT firmware, btusb takes over).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 15:00:10 +08:00
Nurmukhamed Artykaly f40bda47c3 fixed README.md after requests of telegram users. 2026-05-20 13:38:56 +08:00
Nurmukhamed Artykaly f1f825850b fixed error after trying build. 2026-05-20 13:38:56 +08:00
Nurmukhamed Artykaly 7779c8a285 fixed after comment on github. 2026-05-20 13:38:56 +08:00
Nurmukhamed Artykaly 6510278218 refactored, added bluetooth branch. 2026-05-20 13:38:56 +08:00
Nurmukhamed Artykaly bfe239c9af fixed github raw url. 2026-05-20 13:38:56 +08:00
Nurmukhamed Artykaly 43878adc39 small fix. 2026-05-20 13:38:56 +08:00
Nurmukhamed Artykaly 58dff473e8 added Bazzite SRPM instructions. 2026-05-20 13:38:56 +08:00
Vladislav Tatyanin 16b5d4af33 fix: map riscv64 to riscv for kernel ARCH 2026-05-20 13:38:43 +08:00
Shen MintaoandClaude Sonnet 4.5 d8a8048929 Add support for TP-Link/Mercury branded AIC8800D80 USB WiFi adapters
Added USB VID/PID for TP-Link vendor (0x2357) and Mercury product (0x014b)
to support WiFi adapters that re-enumerate with these IDs after firmware
loading. The device is recognized as AIC8800D81 chip with RX aggregation.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-20 13:38:23 +08:00
toor11 13cccb953c Add USB ID 368b:8d84 (AIC 8800D80 variant)
Device 368b:8d84 is an AIC 8800D80 variant not included in the USB
device table. Add it as AIC8800M80_CUS0 alongside the other M80 CUS
variants; it maps to PRODUCT_ID_AIC8800D81 like its siblings.

Tested on kernel 6.19.8-arch1 with a physical dongle (Bus 001 Device
005: ID 368b:8d84 AICSemi AIC 8800D80).
2026-05-20 13:37:53 +08:00
Shen MintaoandClaude Opus 4.6 52e968e765 fix: add -b bluetooth to git clone command in INSTALL_SCRIPT.md
Closes #48

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-08 17:01:02 +08:00
Shen Mintao ebab65c042 更新aic_btusb Makefile 2026-03-24 10:47:23 +08:00
Shen Mintao 3e0c941337 更新Makefile配置 2026-03-24 10:40:21 +08:00
Shen Mintao 3aa0191c7e Merge branch 'bluetooth' of https://github.com/shenmintao/aic8800d80 into bluetooth
# Conflicts:
#	drivers/aic8800/Makefile
2026-03-23 22:21:02 +08:00
Shen Mintao 089be7c4ff Merge main into bluetooth: apply KDIR fix and remove aic_btusb
- Apply PR #34 KDIR fix to dkms.conf for correct kernel header usage
- Remove remaining aic_btusb references from Makefile (standard btusb is used)
2026-03-23 22:17:53 +08:00
Shen MintaoandClaude Sonnet 4.5 41b5208909 feat: auto-load btusb driver in install.sh
Add automatic loading of btusb (standard Linux Bluetooth driver) after
WiFi module installation. This enables Bluetooth functionality without
requiring manual intervention.

The aic_load_fw module uploads Bluetooth firmware including ext0 patches,
then btusb driver handles the actual Bluetooth interface.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-11 10:48:42 +08:00
Shen MintaoandClaude Sonnet 4.5 f2e73a92ab fix: add Linux 6.17+ compatibility for get_tx_power callback
Add radio_idx and changed parameters to rwnx_cfg80211_get_tx_power function
to match the updated cfg80211 API signature introduced in Linux 6.17+. This
fixes compilation errors on kernel 6.19 and later versions.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-11 10:33:27 +08:00
Shen MintaoandClaude Sonnet 4.5 6a2d56d055 fix: update install.sh to install all firmware variants
Changes:
- Install firmware for all chip variants (D80, D80N, D80X2, DC, DW, DLN)
- Automatically detect and copy all firmware directories from fw/
- Update verification to check all installed firmware
- Update uninstallation instructions to remove all firmware

This ensures support for all newly added devices:
- AIC8800D80N series
- AIC8800DLN series
- AIC8800D80X2 with extended firmware
- All other chip variants

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-11 10:14:10 +08:00
Shen MintaoandClaude Sonnet 4.5 165a346c4d feat: update to SDK v5.0 with comprehensive kernel and device support
Major updates:
- Add Linux kernel 6.12-6.19 compatibility support
- Add Linux 6.16 timer_container_of and wakelock API support
- Add Debian 6.1.0-26 backport support
- Fix Bluetooth firmware upload for chip_mcu_id == 1 (cache_mem_addr)
- Add USB device ID 368b:8d81 support
- Add AIC8800DW device support
- Add TP-Link Archer TX1U Nano support (USB_VENDOR_ID_TENDA_V2:0x0110)
- Add TENDA series device support (U2, U11, U11 PRO)
- Add AIC8800FC_CUS4/5/6 series support
- Add AIC8800M80_CUS7/8 series support
- Add UGREEN AIC8800D80 adapter support
- Fix CONFIG_USB_BT interface number check (allow 1 or 3 interfaces)
- Update firmware files for all chip variants

Device support:
- AIC8800D80/D81/DC/DW series
- AIC8800D80X2/D81X2/D89X2 series
- AIC8800D80N/D80LN/D80WN/DLN/DWN series
- TENDA U2/U11/U11 PRO/TX1U Nano adapters
- Multiple OEM variants (FC_CUS1-6, M80_CUS1-8)

Kernel compatibility:
- Linux 3.10 - 6.19+
- Debian 6.1.0-26 with backported APIs
- Ubuntu and other distributions

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-11 10:10:30 +08:00
Shen Mintao b0787d9989 fix: fix usb_modeswitch message content 2026-03-04 21:55:41 +08:00
Shen Mintao 86aa95ffcb refactor: remove aic_btusb module, use standard btusb driver for Bluetooth 2026-03-04 18:12:08 +08:00
Shen Mintao cf63c8e0ee docs: update README with full Bluetooth support documentation 2026-03-04 16:48:49 +08:00
MinQ f2d9cc9ff0 Merge pull request #35 from bnister/bluetooth
Bluetooth firmware upload fix
2026-03-04 16:37:27 +08:00
bnister f36a0afeb4 Bluetooth fw upload fix: chip_mcu_id == 1 needs cache_mem_addr |= 1 2026-03-04 04:49:04 +03:00
Shen Mintao b771774f40 fix: pass KDIR to DKMS make command for proper kernel build path 2026-02-28 14:37:30 +08:00
Shen Mintao 600cdf5ef4 feat: add Kconfig for aic_btusb module 2026-02-28 14:34:52 +08:00
Shen Mintao 8a5af5cfdb fix: export CONFIG_AIC8800_BTUSB_SUPPORT for aic_btusb module compilation 2026-02-28 14:32:37 +08:00
Shen Mintao 85a412e5b8 feat: add aic_btusb bluetooth module support to install.sh 2026-02-28 14:27:02 +08:00
Shen Mintao 4f288d90b2 fix: fix 2026-02-28 09:11:25 +08:00
Shen Mintao 8b90bd8f45 feat: 添加蓝牙支持及固件更新 2026-02-27 18:19:39 +08:00
Shen Mintao 96e1d9cd3d feat: 增加对Linux 6.13+内核的MODULE_IMPORT_NS支持 2026-02-27 18:17:43 +08:00
54 changed files with 1402 additions and 2081 deletions
-11
View File
@@ -1,11 +0,0 @@
fw/aic8800D80/*.txt text eol=lf
fw/aic8800D80/*.bin binary
fw/aic8800DC/*.txt text eol=lf
fw/aic8800DC/*.bin binary
/.gitattributes text eol=lf
drivers/aic8800/aic_zlp_quirk/*.c text eol=lf
drivers/aic8800/aic_zlp_quirk/Makefile text eol=lf
tests/issue63-zlp-quirk/*.conf text eol=lf
tests/issue63-zlp-quirk/*.md text eol=lf
tests/issue63-zlp-quirk/*.sh text eol=lf
tests/issue63-zlp-quirk/Makefile text eol=lf
+2 -9
View File
@@ -2,19 +2,12 @@
## Overview
This automated installation script (`install.sh`) installs the AIC8800 Wi-Fi
driver and firmware loader on Linux systems. Wi-Fi/Bluetooth combo adapters use
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`.
This automated installation script (`install.sh`) simplifies the process of installing the AIC8800D80 WiFi driver on Linux systems.
- Automatic Secure Boot detection
- Automatic dependency installation
- Automatic driver compilation and installation
- Automatic module loading on boot
- 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
- Comprehensive error handling
- Colored output and logging
- Compatible with Ubuntu, Debian, Fedora, and derivatives (DKMS supported `dkms.conf`)
@@ -23,7 +16,7 @@ module without replacing the distribution's `btusb.ko`.
```bash
# Clone the repository and download the script, make the script executable
git clone https://github.com/shenmintao/aic8800d80.git && cd aic8800d80 && chmod +x install.sh
git clone -b bluetooth https://github.com/shenmintao/aic8800d80.git && cd aic8800d80 && chmod +x install.sh
# Run the installation
sudo ./install.sh
+38 -68
View File
@@ -1,45 +1,11 @@
# AIC8800 Linux Wi-Fi and Bluetooth Driver
This driver supports AIC8800-family chipsets used by devices such as the Tenda U11, AX913B, and TP-Link Archer TX1U Nano.
> **Legacy MCU revision 1 branch:** You are viewing `legacy-mcu1`. This branch
> is only for AIC8800D80 or AIC8800DC/DW devices that report
> `chip_id=7, chip_mcu_id=1`. It provides complete matched V3 firmware and
> loader profiles for the D80 upload-limit failure validated in
> [issue #58](https://github.com/shenmintao/aic8800d80/issues/58) and the DC/DW
> V5 main-application timeout validated in
> [issue #71](https://github.com/shenmintao/aic8800d80/issues/71). Use
> [`main`](https://github.com/shenmintao/aic8800d80/tree/main) for newer
> `chip_mcu_id=0` hardware or when the MCU revision is unknown. See the
> [D80](tests/issue58-mcu1-legacy-fw/README.md) and
> [DC/DW](tests/issue71-mcu1-v3-profile/README.md) support notes before installing.
>
> After switching branches, rerun `sudo ./install.sh` and reboot; switching the
> Git branch alone does not replace firmware already installed under
> `/lib/firmware`.
# AIC8800D80 Linux Driver
This driver is for the AIC8800D80 chipset, supported by devices such as the Tenda U11 and AX913B.
Added support for devices with Vendor ID 368B (tested).
Tested on Linux kernel 6.16 with Ubuntu 25.04 and 6.1.0.27 with Debian 12.
The same driver supports Wi-Fi-only adapters and Wi-Fi/Bluetooth combo
adapters. On combo devices, `aic_load_fw` uploads the AIC firmware and the
standard Linux `btusb` driver handles the Bluetooth HCI interface. The obsolete
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.
> [!NOTE]
> **Maintained branches:** This repository now maintains only `main` and
> `legacy-mcu1`. You are viewing the branch for `chip_mcu_id=1`; do not switch
> this hardware to the former separate `bluetooth` branch, which is retired.
> Wi-Fi, the kernel's standard `btusb` Bluetooth path, and the device-scoped
> `368b:8d81` ZLP support are integrated here. The ZLP module remains inactive
> on other VID:PID combinations.
This branch (`bluetooth`) fully supports both **Wi-Fi** and **Bluetooth**.
### 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.
@@ -54,18 +20,18 @@ Before installing the driver, delete all aic8800-related folders under /lib/firm
#### Method 2: Manual Installation
#### Copy udev rules:
Copy the aic.rules file to /usr/lib/udev/rules.d/:
Copy the aic.rules file to /lib/udev/rules.d/:
```bash
sudo cp aic.rules /usr/lib/udev/rules.d/
sudo cp aic.rules /lib/udev/rules.d/
```
#### Copy firmware:
Copy the firmware directories from `./fw` to `/lib/firmware/`:
Copy the aic8800D80 folder from ./fw to /lib/firmware/:
```bash
sudo cp -r ./fw/aic8800* /lib/firmware/
sudo cp -r ./fw/aic8800D80 /lib/firmware/
```
#### Navigate to the driver directory:
@@ -132,52 +98,56 @@ If the device is still not active, check the kernel logs for any errors related
sudo dmesg
```
### Bluetooth on Combo Adapters
### Bluetooth Support
Bluetooth support does not require a separate AIC transport module. After
`aic_load_fw` initializes a combo adapter, the kernel automatically binds its
Bluetooth interface to `btusb`. A Wi-Fi-only adapter does not expose that
interface, so the Bluetooth path remains inactive.
The `aic_load_fw` module loads the Bluetooth firmware during initialization. After the firmware is correctly uploaded, the standard Linux `btusb` driver handles the Bluetooth interface — no custom `aic_btusb` module is needed (see [PR #35](https://github.com/shenmintao/aic8800d80/pull/35) for details).
Verify the expected modules and controller with:
#### Verify Bluetooth is Working
After loading the driver and plugging in the USB device, check if the Bluetooth HCI device is registered:
```bash
lsmod | grep -E 'aic_load_fw|aic8800_fdrv|aic_zlp_quirk|btusb'
lsusb -t
bluetoothctl list
hciconfig -a
```
To scan after a controller appears:
You should see an HCI device (e.g., `hci0`) listed. If the device is down, bring it up:
```bash
sudo hciconfig hci0 up
```
You can also use `bluetoothctl` to scan and connect to Bluetooth devices:
```bash
bluetoothctl
# Inside bluetoothctl:
power on
scan on
```
If Bluetooth is missing or reports HCI timeouts, run the read-only diagnostic
script and attach its output together with the current boot log:
#### Bluetooth Troubleshooting
If Bluetooth is not working, run the diagnostic script:
```bash
chmod +x diagnose_bt.sh
sudo ./diagnose_bt.sh
sudo journalctl -k -b --no-pager
```
The installer removes active references to the retired `aic_btusb` integration.
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.
Common issues and solutions:
For `368b:8d81`, verify the ZLP hook and its injection counter while Bluetooth
traffic is active:
1. **Firmware not found**: Ensure the firmware files are correctly copied to `/lib/firmware/aic8800D80/`. Key Bluetooth firmware files include:
- `fw_patch_8800d80_u02.bin`
- `fw_patch_table_8800d80_u02.bin`
- `fw_adid_8800d80_u02.bin`
```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.
2. **Check kernel logs** for Bluetooth-related errors:
```bash
sudo dmesg | grep -iE "aicbt|bluetooth|hci|fw_patch"
```
3. **RF-Kill blocking Bluetooth**:
```bash
rfkill list bluetooth
sudo rfkill unblock bluetooth
```
+18 -3
View File
@@ -1,4 +1,4 @@
# AIC8800 USB mass-storage mode switch rules
# AIC8800 USB Mass Storage mode switch rules
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5721", SYMLINK+="aicudisk", RUN+="/usr/bin/eject /dev/%k"
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5723", SYMLINK+="tendaudisk", RUN+="/usr/bin/eject /dev/%k"
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5724", SYMLINK+="ugreenax900", RUN+="/usr/bin/eject /dev/%k"
@@ -9,5 +9,20 @@ KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="572a", SYMLINK+="ten
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="572c", SYMLINK+="cudydiskv2", RUN+="/usr/bin/eject /dev/%k"
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="572f", SYMLINK+="aicudisk572f", RUN+="/usr/bin/eject /dev/%k"
# AIC8800D80 "Pandora" clone: switch 1111:1111 to its operational USB ID.
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="1111", ATTR{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'"
# AIC8800D80 "Pandora" clone adapter - automatic mode switch & driver binding
# Triggers usb_modeswitch when the device is plugged in as 1111:1111
# --- Mode Switch ---
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'"
# --- WiFi Driver Binding ---
# After mode switch, the device re-enumerates as a69c:8d81 (Radxa fw) or a69c:8d83 (Brostrend fw).
# If aic8800_fdrv doesn't auto-bind to the WiFi interface, add the VID:PID dynamically:
ACTION=="add", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="8d81", RUN+="/bin/sh -c 'echo a69c 8d81 > /sys/bus/usb/drivers/aic8800_fdrv/new_id 2>/dev/null || true'"
ACTION=="add", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="8d83", RUN+="/bin/sh -c 'echo a69c 8d83 > /sys/bus/usb/drivers/aic8800_fdrv/new_id 2>/dev/null || true'"
ACTION=="add", ATTRS{idVendor}=="368b", ATTRS{idProduct}=="8d81", RUN+="/bin/sh -c 'echo 368b 8d81 > /sys/bus/usb/drivers/aic8800_fdrv/new_id 2>/dev/null || true'"
# Unblock rfkill for Bluetooth
ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="8d81", RUN+="/bin/sh -c 'rfkill unblock bluetooth 2>/dev/null || true'"
ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="8d83", RUN+="/bin/sh -c 'rfkill unblock bluetooth 2>/dev/null || true'"
ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="368b", ATTRS{idProduct}=="8d81", RUN+="/bin/sh -c 'rfkill unblock bluetooth 2>/dev/null || true'"
+3 -6
View File
@@ -32,7 +32,7 @@ Copy aic8800d80.spec to rpmbuild/SPECS
~~~bash
cd $HOME/rpmbuild/SPECS
curl -LO -s https://raw.githubusercontent.com/shenmintao/aic8800d80/refs/heads/main/bazzite/aic8800d80.spec
curl -LO -s https://raw.githubusercontent.com/shenmintao/aic8800d80/refs/heads/bluetooth/bazzite/aic8800d80.spec
~~~
Prepare and download required files.
@@ -56,11 +56,8 @@ sudo rpm-ostree install "$rpm_path"
sudo systemctl reboot
~~~
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
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.
After reboot, the Wi-Fi module and firmware loader will be available. Bluetooth
is handled by the standard `btusb` kernel module after firmware initialization.
This RPM is built for the kernel reported by `uname -r`. Rebuild and reinstall
it after a Bazzite kernel upgrade.
+10 -28
View File
@@ -1,11 +1,11 @@
%global commit 51b7b6e72989afe4d21f52e55b70f5a4d6b21e5b
%global commit 6b8cb98e969b04236f8726f7591393a040171735
%global shortcommit %(echo %{commit} | cut -c1-7)
%{!?kver:%global kver %(uname -r)}
Name: aic8800d80
Version: %{shortcommit}
Release: 1%{?dist}
Summary: AIC8800 USB Wi-Fi, Bluetooth firmware, and ZLP quirk driver
Summary: AIC8800D80 USB Wi-Fi and Bluetooth driver
License: GPL-2.0-only
URL: https://github.com/shenmintao/aic8800d80
@@ -18,15 +18,15 @@ BuildRequires: kernel-devel-uname-r = %{kver}
Requires: kernel-uname-r = %{kver}
Requires: /usr/bin/eject
Requires: /usr/sbin/usb_modeswitch
Requires: /usr/sbin/rfkill
Requires(post): /usr/sbin/depmod
Requires(postun): /usr/sbin/depmod
%description
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
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.
Out-of-tree AIC8800D80 USB driver with Wi-Fi support, Bluetooth firmware
loading, udev mode-switch rules, and all firmware variants shipped by the
upstream repository. Bluetooth interfaces are handled by the standard Linux
btusb driver after aic_load_fw initializes the device.
%prep
%autosetup -n %{name}-%{commit}
@@ -46,10 +46,6 @@ install -Dpm0644 \
drivers/aic8800/aic_load_fw/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 \
aic.rules \
%{buildroot}/usr/lib/udev/rules.d/90-aic8800-mode-switch.rules
@@ -71,26 +67,12 @@ cp -a fw/aic8800* %{buildroot}/usr/lib/firmware/
%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/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
%config(noreplace) /etc/usb_modeswitch.d/1111:1111
/usr/lib/firmware/aic8800*
%changelog
* Sat Jul 25 2026 Shen Mintao <shenmintao@gmail.com> - 51b7b6e-1
- Package the unified installer and ZLP quirk with the legacy MCU1 profiles.
- Preserve the matched D80 and DC/DW firmware and loader combinations.
* Sat Jul 25 2026 Shen Mintao <shenmintao@gmail.com> - 13baa9b-1
- Unify Wi-Fi and standard-btusb Bluetooth support in one package.
- Add the device-scoped 368b:8d81 ACL bulk TX ZLP companion module.
- Clean up obsolete aic_btusb and issue #63 diagnostic installations.
* Fri Jul 24 2026 Shen Mintao <shenmintao@gmail.com> - 88dbc0a-1
- Use the unified Wi-Fi and Bluetooth installer/package description.
- Keep Bluetooth transport on the standard Linux btusb driver.
* Tue Jul 14 2026 Shen Mintao <shenmintao@gmail.com> - d10bc52-1
- Build the current main branch without the legacy custom Bluetooth module.
* Tue Jul 14 2026 Shen Mintao <shenmintao@gmail.com> - 6b8cb98-1
- Build the current bluetooth branch without the removed aic_btusb module.
- Package all firmware variants and current mode-switch rules.
- Remove obsolete Bluetooth-specific configuration from the Wi-Fi package.
- Remove the obsolete custom Bluetooth module integration.
+103 -121
View File
@@ -1,160 +1,142 @@
#!/bin/bash
# Diagnose Bluetooth on AIC8800 Wi-Fi/Bluetooth combo adapters.
#
# aic_load_fw initializes the device and uploads the AIC firmware. The
# standard in-kernel btusb driver must then bind to the Bluetooth HCI USB
# interface. The removed aic_btusb module must not be installed or loaded.
# AIC8800D80 Bluetooth Diagnostic Script
# 用于诊断蓝牙问题
#
# 本分支 (bluetooth) 使用内核标准 btusb 驱动接管蓝牙,
# aic_load_fw 负责把蓝牙固件上传到芯片。
# 不应该再安装/加载 aic_btusb。
#
echo "=== AIC8800 Bluetooth diagnostics ==="
echo "=== AIC8800D80 蓝牙诊断 ==="
echo ""
echo "1. AIC USB devices:"
if command -v lsusb >/dev/null 2>&1; then
lsusb | grep -iE 'a69c|368b|3625' || echo " No known AIC USB ID found"
else
echo " lsusb is not installed"
fi
# 1. 检查 USB 设备
echo "1. USB 设备状态:"
echo " 当前 AIC 设备:"
lsusb | grep -iE "a69c|368b|1111" || echo " 未找到 AIC 设备"
echo ""
echo "2. USB interfaces and bound drivers:"
bt_interface_found=false
btusb_bound=false
zlp_target_found=false
# 2. 检查 USB 接口数量
echo "2. USB 接口详情:"
for dev in /sys/bus/usb/devices/*; do
[ -f "$dev/idVendor" ] || continue
[ -f "$dev/idProduct" ] || continue
vid=$(cat "$dev/idVendor" 2>/dev/null)
pid=$(cat "$dev/idProduct" 2>/dev/null)
case "$vid" in
a69c|368b|3625) ;;
*) continue ;;
esac
echo " Device: $vid:$pid"
if [ "$vid" = "368b" ] && [ "$pid" = "8d81" ]; then
zlp_target_found=true
fi
for intf in "$dev"/*:*; do
[ -d "$intf" ] || continue
class=$(cat "$intf/bInterfaceClass" 2>/dev/null)
subclass=$(cat "$intf/bInterfaceSubClass" 2>/dev/null)
protocol=$(cat "$intf/bInterfaceProtocol" 2>/dev/null)
driver=$(basename "$(readlink "$intf/driver" 2>/dev/null)" 2>/dev/null)
echo " $(basename "$intf"): ${class:-??}/${subclass:-??}/${protocol:-??} -> ${driver:-unbound}"
if [ "$driver" = "btusb" ]; then
btusb_bound=true
bt_interface_found=true
elif [ "$class" = "e0" ] && [ "$subclass" = "01" ] && [ "$protocol" = "01" ]; then
bt_interface_found=true
if [ -f "$dev/idVendor" ] && [ -f "$dev/idProduct" ]; then
vid=$(cat "$dev/idVendor" 2>/dev/null)
pid=$(cat "$dev/idProduct" 2>/dev/null)
if [[ "$vid" == "a69c" || "$vid" == "368b" ]]; then
echo " 设备: $vid:$pid"
if [ -d "$dev" ]; then
for intf in "$dev"/*:*; do
if [ -d "$intf" ]; then
class=$(cat "$intf/bInterfaceClass" 2>/dev/null)
subclass=$(cat "$intf/bInterfaceSubClass" 2>/dev/null)
protocol=$(cat "$intf/bInterfaceProtocol" 2>/dev/null)
driver=$(basename "$(readlink "$intf/driver" 2>/dev/null)" 2>/dev/null)
echo " 接口: $class/$subclass/$protocol -> 驱动: ${driver:-未绑定}"
fi
done
fi
fi
done
fi
done
echo ""
echo "3. Relevant kernel modules (combo expectation: aic_load_fw + btusb):"
lsmod | grep -E '^(aic_load_fw|aic8800_fdrv|aic_zlp_quirk|aic_btusb|btusb|bluetooth)[[:space:]]' || \
echo " No related module is currently loaded"
# 3. 检查已加载的模块
echo "3. 已加载的相关模块 (期望: aic_load_fw + btusb):"
lsmod | grep -E "aic_load_fw|aicwf|aic_btusb|btusb|bluetooth" || echo " 未找到相关模块"
echo ""
echo "4. Bluetooth controllers:"
if command -v bluetoothctl >/dev/null 2>&1; then
bluetoothctl list 2>/dev/null || echo " No controller reported by bluetoothctl"
elif command -v hciconfig >/dev/null 2>&1; then
hciconfig -a 2>/dev/null || echo " No controller reported by hciconfig"
else
echo " BlueZ command-line tools are not installed"
fi
# 4. 检查 HCI 设备
echo "4. HCI 设备:"
hciconfig -a 2>/dev/null || echo " 无法获取 HCI 信息 (可能需要 root 权限)"
echo ""
echo "5. Firmware, btusb, ZLP quirk, and HCI log messages:"
dmesg 2>/dev/null | grep -iE 'fw_patch|fw_adid|aicbt|aic_zlp_quirk|bluetooth|btusb|hci' | tail -80 || true
# 5. 检查蓝牙固件加载日志
echo "5. 蓝牙固件加载日志 (最近 50 行):"
dmesg | grep -iE "fw_patch|fw_adid|aicbt|bluetooth|btusb|hci" | tail -50
echo ""
echo "6. Bluetooth rfkill state:"
if command -v rfkill >/dev/null 2>&1; then
rfkill list bluetooth 2>/dev/null || echo " No Bluetooth rfkill entry"
else
echo " rfkill is not installed"
fi
# 6. 检查 rfkill 状态
echo "6. RF-Kill 状态:"
rfkill list bluetooth 2>/dev/null || echo " 无法获取 rfkill 信息"
echo ""
echo "7. Obsolete aic_btusb installation/configuration:"
# 7. 检查残留的旧 aic_btusb 配置 (issue #53)
echo "7. 残留旧配置检查:"
legacy_refs_found=false
mapfile -t legacy_modprobe_files < <(
grep -RIlE '^[[:space:]]*(softdep|alias)[^#]*aic_btusb([[:space:]]|$)' \
/etc/modprobe.d /run/modprobe.d /usr/local/lib/modprobe.d \
/usr/lib/modprobe.d /lib/modprobe.d 2>/dev/null | \
grep -vE '\.aic8800-backup$' || true
/etc/modprobe.d /run/modprobe.d /usr/local/lib/modprobe.d /usr/lib/modprobe.d /lib/modprobe.d \
2>/dev/null || true
)
mapfile -t legacy_udev_files < <(
grep -RIl 'aic_btusb/new_id' \
/etc/udev/rules.d /run/udev/rules.d \
/usr/lib/udev/rules.d /lib/udev/rules.d 2>/dev/null | \
grep -vE '\.aic8800-backup$' || true
/etc/udev/rules.d /run/udev/rules.d /usr/lib/udev/rules.d /lib/udev/rules.d \
2>/dev/null || true
)
for legacy_file in "${legacy_modprobe_files[@]}"; do
echo " Obsolete modprobe directive: $legacy_file"
echo " ⚠️ 发现旧 modprobe 指令: $legacy_file"
legacy_refs_found=true
done
for legacy_file in "${legacy_udev_files[@]}"; do
echo " Obsolete udev binding rule: $legacy_file"
legacy_refs_found=true
done
if lsmod | awk '{print $1}' | grep -qx 'aic_btusb'; then
echo " Obsolete aic_btusb module is loaded"
legacy_refs_found=true
fi
if modinfo -n aic_btusb >/dev/null 2>&1; then
echo " Obsolete module file: $(modinfo -n aic_btusb 2>/dev/null)"
legacy_refs_found=true
fi
if [ "$legacy_refs_found" = false ]; then
echo " No active aic_btusb module, directive, or binding rule found (expected)"
fi
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"
for legacy_file in "${legacy_udev_files[@]}"; do
echo " ⚠️ 发现旧 udev 绑定规则: $legacy_file"
legacy_refs_found=true
done
if lsmod | awk '{print $1}' | grep -qx 'aic_btusb'; then
echo " ⚠️ 旧 aic_btusb 模块当前仍已加载"
legacy_refs_found=true
fi
if modinfo -n aic_btusb >/dev/null 2>&1; then
echo " ⚠️ 系统中仍存在 aic_btusb 模块: $(modinfo -n aic_btusb 2>/dev/null)"
legacy_refs_found=true
fi
if [ "$legacy_refs_found" = true ]; then
echo " 这些残留会尝试加载已删除的模块, 并干扰标准 btusb 的自动加载/绑定顺序。"
echo " 修复: 拉取最新 bluetooth 分支后重新运行 sudo ./install.sh"
if command -v update-initramfs >/dev/null 2>&1; then
echo " 然后执行: sudo update-initramfs -u"
elif command -v dracut >/dev/null 2>&1; then
echo " 然后执行: sudo dracut -f"
elif command -v mkinitcpio >/dev/null 2>&1; then
echo " 然后执行: sudo mkinitcpio -P"
fi
else
echo " Target 368b:8d81 not present; quirk is not required"
echo " 未发现活动的 aic_btusb 配置、规则或模块 (正常)"
fi
echo ""
echo "=== Assessment ==="
if ! lsmod | awk '{print $1}' | grep -qx 'aic_load_fw'; then
echo "- aic_load_fw is not loaded; run: sudo modprobe aic8800_fdrv"
fi
if [ "$bt_interface_found" = true ] && [ "$btusb_bound" = false ]; then
echo "- A Bluetooth USB interface exists but is not bound to btusb."
echo " Check for a btusb blacklist, then try: sudo modprobe btusb"
fi
if dmesg 2>/dev/null | grep -iE 'hci[0-9]+:.*(command|opcode|tx).*timed out|hci[0-9]+: link tx timeout' | tail -1 | grep -q .; then
echo "- HCI timeout detected. Confirm that aic_load_fw uploaded the firmware before btusb bound."
echo " Also check for obsolete aic_btusb configuration above."
fi
if [ "$bt_interface_found" = false ]; then
echo "- No Bluetooth HCI USB interface was found. This is normal for a Wi-Fi-only adapter."
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"
# 8. 建议
echo "=== 诊断建议 ==="
echo ""
# 检查 aic_load_fw 是否加载 (它负责上传 WiFi + BT 固件)
if ! lsmod | grep -q "^aic_load_fw"; then
echo "⚠️ aic_load_fw 未加载"
echo " 该模块负责把蓝牙固件上传到芯片, 必须先于 btusb 工作"
echo " 解决方案: sudo modprobe aic_load_fw"
echo ""
fi
echo "=== Diagnostics complete ==="
# 检查 HCI_Reset 超时 (典型症状: 固件未上传却让 btusb 接管)
if dmesg | grep -iE "hci0:.*command (0x|tx) timed out|hci0.*opcode.*0x0c03" | tail -5 | grep -q .; then
echo "⚠️ 检测到 HCI 命令超时 (HCI_Reset/-110)"
echo " 常见原因:"
echo " a) 旧 aic_btusb 配置或 udev 规则残留 (见第 7 项)"
echo " b) aic_load_fw 没有先把蓝牙固件 patch 上传到芯片"
echo " c) usb_modeswitch 没把 1111:1111 切换到真实 VID:PID"
echo " 排查: 看上面第 5 项日志, 应能看到 fw_patch_table_8800d80 / fw_adid 字样"
echo " 临时缓解: 拔插一次设备 (软件复位/飞行模式切换通常无法救活)"
echo ""
fi
# btusb 是否已接管 BT 接口 (这是正常预期)
if lsmod | grep -q "^btusb"; then
echo "✅ btusb 已加载 (正常, 本分支由 btusb 接管蓝牙)"
fi
echo "=== 诊断完成 ==="
-5
View File
@@ -13,9 +13,4 @@ BUILT_MODULE_NAME[1]="aic_load_fw"
BUILT_MODULE_LOCATION[1]="drivers/aic8800/aic_load_fw"
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"
-7
View File
@@ -1,10 +1,8 @@
CONFIG_AIC_LOADFW_SUPPORT := m
CONFIG_AIC8800_WLAN_SUPPORT := m
CONFIG_AIC_ZLP_QUIRK := m
obj-$(CONFIG_AIC_LOADFW_SUPPORT) += aic_load_fw/
obj-$(CONFIG_AIC8800_WLAN_SUPPORT) += aic8800_fdrv/
obj-$(CONFIG_AIC_ZLP_QUIRK) += aic_zlp_quirk/
########## config option ##########
export CONFIG_USE_FW_REQUEST = n
@@ -53,7 +51,6 @@ KVER ?= $(shell uname -r)
KDIR ?= /lib/modules/$(KVER)/build
PWD = $(shell pwd)
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/)
ARCH ?= $(SUBARCH)
CROSS_COMPILE ?=
@@ -81,20 +78,16 @@ modules:
install:
mkdir -p $(MODDESTDIR)
mkdir -p $(BTMODDESTDIR)
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 aic_zlp_quirk/aic_zlp_quirk.ko $(BTMODDESTDIR)/
/sbin/depmod -a ${KVER}
uninstall:
rm -rfv $(MODDESTDIR)/aic_load_fw.ko
rm -rfv $(MODDESTDIR)/aic8800_fdrv.ko
rm -rfv $(BTMODDESTDIR)/aic_zlp_quirk.ko
/sbin/depmod -a ${KVER}
clean:
cd aic_load_fw/;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/
+288 -206
View File
@@ -45,8 +45,6 @@
#define FW_USERCONFIG_NAME_8800DW "aic_userconfig_8800dw.txt"
#define FW_POWERLIMIT_NAME_8800DC "aic_powerlimit_8800dc.txt"
#define FW_POWERLIMIT_NAME_8800DW "aic_powerlimit_8800dw.txt"
#define FW_USERCONFIG_NAME_8800DW_W311 "aic_userconfig_8800dw_w311.txt"
#define FW_USERCONFIG_NAME_8800DW_U2 "aic_userconfig_8800dw_u2.txt"
#ifdef CONFIG_LOAD_BT_PATCH_IN_FDRV
enum aicbt_patch_table_type {
@@ -169,6 +167,7 @@ u32 syscfg_tbl_masked_8800dc[][3] = {
{0x700010A0, (0x1 << 11), (0x1 << 11)},
{0x70001034, ((0x1 << 20) | (0x7 << 26)), ((0x0 << 20) | (0x2 << 26))},
{0x70001038, (0x1 << 8), (0x1 << 8)},
{0x70001084, (0x3 << 13), (0x0 << 13)},
{0x70001094, (0x3 << 2), (0x0 << 2)},
{0x700021D0, ((0x1 << 5) | (0x1 << 6)), ((0x1 << 5) | (0x1 << 6))},
{0x70001000, ((0x1 << 0) | (0x1 << 20) | (0x1 << 22)),
@@ -186,6 +185,7 @@ u32 syscfg_tbl_masked_8800dc[][3] = {
{0x700010A0, (0x1 << 11), (0x1 << 11)},
{0x70001034, ((0x1 << 20) | (0x7 << 26)), ((0x0 << 20) | (0x2 << 26))},
{0x70001038, (0x1 << 8), (0x1 << 8)},
{0x70001084, (0x3 << 13), (0x0 << 13)},
{0x70001094, (0x3 << 2), (0x0 << 2)},
{0x700021D0, ((0x1 << 5) | (0x1 << 6)), ((0x1 << 5) | (0x1 << 6))},
{0x70001000, ((0x1 << 0) | (0x1 << 20) | (0x1 << 22)),
@@ -211,6 +211,7 @@ u32 syscfg_tbl_masked_8800dc_h[][3] = {
{0x700010A0, (0x1 << 11), (0x1 << 11)},
//{0x70001034, ((0x1 << 20) | (0x7 << 26)), ((0x0 << 20) | (0x2 << 26))},
{0x70001038, (0x1 << 8), (0x1 << 8)},
{0x70001084, (0x3 << 13), (0x0 << 13)},
{0x70001094, (0x3 << 2), (0x0 << 2)},
{0x700021D0, ((0x1 << 5) | (0x1 << 6)), ((0x1 << 5) | (0x1 << 6))},
#if defined(CONFIG_VRF_DCDC_MODE)
@@ -242,7 +243,6 @@ u32 syscfg_tbl_8800dc[][2] = {
u32 patch_tbl_wifisetting[][2] =
{
{0x0004, 0x00020010}, //wdt_reboot_type, wdt_period_sec
#if !defined(CONFIG_FPGA_VERIFICATION)
{0x0090, 0x0013FC00}, //rx_ringbuf_start2
#endif
@@ -251,10 +251,9 @@ u32 patch_tbl_wifisetting[][2] =
{0x0120, 0x140A0100}, //usb agg tx params(total cnt, aggr cnt, out en, global out nak)
#endif //CONFIG_USB_TX_AGGR
{0x00b0, 0xAD180100},
#ifdef CONFIG_BAND_STEERING
#ifdef CONFIG_PRBREQ_REPORT
{0x0138, 0x00010a00}, //apm probe resp offload en
#endif
{0x0084, 0x00000040},
};
u32 jump_tbl[][2] =
@@ -1872,104 +1871,104 @@ const uint32_t txgain_map_femkct[96] =
const uint32_t txgain_map_femkct_h[96] =
{
//11b
0x00ffd872,//15
0x00ffd880,//16
0x00ffd972,//17
0x00ffd980,//18
0x00ffd990,//19
0x00ffda72,//20
0x00ffda80,//21
0x00ffdb72,//22
0x00ffdb80,//23
0x00ffdc72,//24
0x00ffdc80,//25
0x00ffdd72,//26
0x00ffdd80,//27
0x00ffde72,//28
0x00ffde80,//29
0x00ffdf72,//30
0x00ffd072,//-1
0x00ffd072,//0
0x00ffd080,//1
0x00ffd172,//2
0x00ffd180,//3
0x00ffd272,//4
0x00ffd280,//5
0x00ffd379,//6
0x00ffd46d,//7
0x00ffd479,//8
0x00ffd572,//9
0x00ffd580,//10
0x00ffd672,//11
0x00ffd680,//12
0x00ffd772,//13
0x00ffd780,//14
0x00ffd86c,//15
0x00ffd879,//16
0x00ffd96c,//17
0x00ffd979,//18
0x00ffd988,//19
0x00ffda6c,//20
0x00ffda79,//21
0x00ffdb6c,//22
0x00ffdb79,//23
0x00ffdc6c,//24
0x00ffdc79,//25
0x00ffdd6c,//26
0x00ffdd79,//27
0x00ffde6c,//28
0x00ffde79,//29
0x00ffdf6c,//30
0x00ffd06c,//-1
0x00ffd06c,//0
0x00ffd079,//1
0x00ffd16c,//2
0x00ffd179,//3
0x00ffd26c,//4
0x00ffd279,//5
0x00ffd372,//6
0x00ffd467,//7
0x00ffd472,//8
0x00ffd56c,//9
0x00ffd579,//10
0x00ffd66c,//11
0x00ffd679,//12
0x00ffd76c,//13
0x00ffd779,//14
//high
0x00ffc880,//11
0x00ffc972,//12
0x00ffc980,//13
0x00ffca72,//14
0x00ffca80,//15
0x00ffcb72,//16
0x00ffcb80,//17
0x00ffcc72,//18
0x00ffcc80,//19
0x00ffcc90,//20
0x00ffcd72,//21
0x00ffcd80,//22
0x00ffce72,//23
0x00ffce80,//24
0x00ffcf72,//25
0x00ffcf80,//26
0x00ffc080,//-5
0x00ffc172,//-4
0x00ffc180,//-3
0x00ffc272,//-2
0x00ffc280,//-1
0x00ffc372,//0
0x00ffc380,//1
0x00ffc472,//2
0x00ffc480,//3
0x00ffc572,//4
0x00ffc580,//5
0x00ffc672,//6
0x00ffc680,//7
0x00ffc772,//8
0x00ffc780,//9
0x00ffc872,//10
0x00ffc879,//11
0x00ffc96c,//12
0x00ffc979,//13
0x00ffca6c,//14
0x00ffca79,//15
0x00ffcb6c,//16
0x00ffcb79,//17
0x00ffcc6c,//18
0x00ffcc79,//19
0x00ffcc88,//20
0x00ffcd6c,//21
0x00ffcd79,//22
0x00ffce6c,//23
0x00ffce79,//24
0x00ffcf6c,//25
0x00ffcf79,//26
0x00ffc079,//-5
0x00ffc16c,//-4
0x00ffc179,//-3
0x00ffc26c,//-2
0x00ffc279,//-1
0x00ffc36c,//0
0x00ffc379,//1
0x00ffc46c,//2
0x00ffc479,//3
0x00ffc56c,//4
0x00ffc579,//5
0x00ffc66c,//6
0x00ffc679,//7
0x00ffc76c,//8
0x00ffc779,//9
0x00ffc86c,//10
//low
0x00ffc880,//11
0x00ffc972,//12
0x00ffc980,//13
0x00ffca72,//14
0x00ffca80,//15
0x00ffcb72,//16
0x00ffcb80,//17
0x00ffcc72,//18
0x00ffcc80,//19
0x00ffcc90,//20
0x00ffcd72,//21
0x00ffcd80,//22
0x00ffce72,//23
0x00ffce80,//24
0x00ffcf72,//25
0x00ffcf80,//26
0x00ffc080,//-5
0x00ffc172,//-4
0x00ffc180,//-3
0x00ffc272,//-2
0x00ffc280,//-1
0x00ffc372,//0
0x00ffc380,//1
0x00ffc472,//2
0x00ffc480,//3
0x00ffc572,//4
0x00ffc580,//5
0x00ffc672,//6
0x00ffc680,//7
0x00ffc772,//8
0x00ffc780,//9
0x00ffc872,//10
0x00ffc879,//11
0x00ffc96c,//12
0x00ffc979,//13
0x00ffca6c,//14
0x00ffca79,//15
0x00ffcb6c,//16
0x00ffcb79,//17
0x00ffcc6c,//18
0x00ffcc79,//19
0x00ffcc88,//20
0x00ffcd6c,//21
0x00ffcd79,//22
0x00ffce6c,//23
0x00ffce79,//24
0x00ffcf6c,//25
0x00ffcf79,//26
0x00ffc079,//-5
0x00ffc16c,//-4
0x00ffc179,//-3
0x00ffc26c,//-2
0x00ffc279,//-1
0x00ffc36c,//0
0x00ffc379,//1
0x00ffc46c,//2
0x00ffc479,//3
0x00ffc56c,//4
0x00ffc579,//5
0x00ffc66c,//6
0x00ffc679,//7
0x00ffc76c,//8
0x00ffc779,//9
0x00ffc86c,//10
};
#endif
@@ -2205,6 +2204,141 @@ uint32_t wifi_txgain_table_24g_1_8800dcdw_femkct[32] = {
};
#endif
#ifdef CONFIG_5M10M
u32 wifi_rxgain_table_24g_dcdw_5m[64] = {
0x82f282d1,//index 0
0x9591a200,
0x80808419,
0x000000f0,
0x42f282d1,//index 1
0x95923400,
0x80808419,
0x000000f0,
0x22f282d1,//index 2
0x9592c600,
0x80808419,
0x000000f0,
0x02f282d1,//index 3
0x9591a200,
0x80808419,
0x000000f0,
0x06f282d1,//index 4
0x9591a200,
0x80808419,
0x000000f0,
0x0ef282d1,//index 5
0x9591a200,
0x80808419,
0x000000f0,
0x0ef282d3,//index 6
0x95923400,
0x80808419,
0x000000f0,
0x0ef282d7,//index 7
0x9595a200,
0x80808419,
0x000000f0,
0x02f282d2,//index 8
0x95951000,
0x80808419,
0x000000f0,
0x02f282f4,//index 9
0x95951000,
0x80808419,
0x000000f0,
0x02f282e6,//index 10
0x9595a200,
0x80808419,
0x000000f0,
0x02f282e6,//index 11
0x9599a200,
0x80808419,
0x000000f0,
0x02f282e6,//index 12
0x959da200,
0x80808419,
0x000000f0,
0x02f282e6,//index 13
0x959f5800,
0x80808419,
0x000000f0,
0x06f282e6,//index 14
0x959f5800,
0x80808419,
0x000000f0,
0x0ef282e6,//index 15
0x959f5800,
0x80808419,
0x000000f0
};
u32 wifi_rxgain_table_24g_dcdw_10m[64] = {
0x82f282d1,//index 0
0x9591a320,
0x80808419,
0x000000f0,
0x42f282d1,//index 1
0x95923520,
0x80808419,
0x000000f0,
0x22f282d1,//index 2
0x9592c720,
0x80808419,
0x000000f0,
0x02f282d1,//index 3
0x9591a320,
0x80808419,
0x000000f0,
0x06f282d1,//index 4
0x9591a320,
0x80808419,
0x000000f0,
0x0ef282d1,//index 5
0x9591a320,
0x80808419,
0x000000f0,
0x0ef282d3,//index 6
0x95923520,
0x80808419,
0x000000f0,
0x0ef282d7,//index 7
0x9595a320,
0x80808419,
0x000000f0,
0x02f282d2,//index 8
0x95951120,
0x80808419,
0x000000f0,
0x02f282f4,//index 9
0x95951120,
0x80808419,
0x000000f0,
0x02f282e6,//index 10
0x9595a320,
0x80808419,
0x000000f0,
0x02f282e6,//index 11
0x9599a320,
0x80808419,
0x000000f0,
0x02f282e6,//index 12
0x959da320,
0x80808419,
0x000000f0,
0x02f282e6,//index 13
0x959f5920,
0x80808419,
0x000000f0,
0x06f282e6,//index 14
0x959f5920,
0x80808419,
0x000000f0,
0x0ef282e6,//index 15
0x959f5920,
0x80808419,
0x000000f0
};
#endif
u32 wifi_rxgain_table_24g_20m_8800dcdw[64] = {
0x82f282d1,//index 0
0x9591a324,
@@ -2923,7 +3057,13 @@ int aicwf_set_rf_config_8800dc(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_c
if ((ret = rwnx_send_rf_config_req(rwnx_hw, 32, 0, (u8_l *)wifi_rxgain_table_24g_40m_8800dcdw, 256)))
return -1;
#ifdef CONFIG_5M10M
if ((ret = rwnx_send_rf_config_req(rwnx_hw, 16, 0, (u8_l *)wifi_rxgain_table_24g_dcdw_5m, 256)))
return -1;
if ((ret = rwnx_send_rf_config_req(rwnx_hw, 48, 0, (u8_l *)wifi_rxgain_table_24g_dcdw_10m, 256)))
return -1;
#endif
if ((ret = rwnx_send_rf_calib_req(rwnx_hw, cfm))) {
return -1;
}
@@ -3038,88 +3178,61 @@ int aicwf_misc_ram_valid_check_8800dc(struct rwnx_hw *rwnx_hw, int *valid_out)
uint32_t misc_ram_addr;
uint32_t ram_base_addr, ram_word_cnt;
uint32_t bit_mask[4];
uint32_t dpd_info_read_addr = 0xfe004;
uint32_t boot_argc_read_addr = 0x1220f0;
uint32_t flash_size_mem_addr = 0x40038030;
uint8_t flash_size = 0;
int i;
if (valid_out) {
*valid_out = 0;
}
AICWFDBG(LOGINFO, "issue71: checking legacy V3 DPD result\n");
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, boot_argc_read_addr, &cfm);
if (ret) {
AICWFDBG(LOGERROR, "boot argc [0x%x] rd fail: %d\n", boot_argc_read_addr, ret);
return ret;
if (testmode == FW_RFTEST_MODE) {
uint32_t vect1 = 0;
uint32_t vect2 = 0;
cfg_base = RAM_LMAC_FW_ADDR + 0x0004;
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base, &cfm);
if (ret) {
AICWFDBG(LOGERROR, "cfg_base:%x vcet1 rd fail: %d\n", cfg_base, ret);
return ret;
}
vect1 = cfm.memdata;
if ((vect1 & 0xFFFF0000) != (RAM_LMAC_FW_ADDR & 0xFFFF0000)) {
AICWFDBG(LOGERROR, "vect1 invalid: %x\n", vect1);
return ret;
}
cfg_base = RAM_LMAC_FW_ADDR + 0x0008;
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base, &cfm);
if (ret) {
AICWFDBG(LOGERROR, "cfg_base:%x vcet2 rd fail: %d\n", cfg_base, ret);
return ret;
}
vect2 = cfm.memdata;
if ((vect2 & 0xFFFF0000) != (RAM_LMAC_FW_ADDR & 0xFFFF0000)) {
AICWFDBG(LOGERROR, "vect2 invalid: %x\n", vect2);
return ret;
}
cfg_base = RAM_LMAC_FW_ADDR + 0x0164;
}
AICWFDBG(LOGINFO, "issue71: boot argc=0x%x\n", cfm.memdata);
if (cfm.memdata & 0x10) {
if (valid_out) {
*valid_out = 1;
}
AICWFDBG(LOGINFO, "issue71: boot arguments mark DPD result valid\n");
// init misc ram
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x14, &cfm);
if (ret) {
AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret);
return ret;
}
if (chip_mcu_id) {
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, flash_size_mem_addr, &cfm);
misc_ram_addr = cfm.memdata;
AICWFDBG(LOGERROR, "misc_ram_addr=%x\n", misc_ram_addr);
// bit_mask
ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask);
ram_word_cnt = (MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved)) / 4;
for (i = 0; i < ram_word_cnt; i++) {
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, ram_base_addr + i * 4, &cfm);
if (ret) {
AICWFDBG(LOGERROR, "flash size[0x%x] rd fail: %d\n", flash_size_mem_addr, ret);
AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret);
return ret;
}
flash_size = cfm.memdata & 0xff;
if (flash_size == 0x16) {
dpd_info_read_addr += 0x4300000;
} else if (flash_size == 0x15) {
dpd_info_read_addr += 0x4100000;
} else if (flash_size == 0x18) {
dpd_info_read_addr += 0x4700000;
} else {
dpd_info_read_addr += 0x4100000;
}
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, dpd_info_read_addr, &cfm);
if (ret) {
AICWFDBG(LOGERROR, "dpd info [0x%x] rd fail: %d\n", dpd_info_read_addr, ret);
return ret;
}
AICWFDBG(LOGINFO,
"issue71: flash size=0x%x, DPD info [0x%x]=0x%x\n",
flash_size, dpd_info_read_addr, cfm.memdata);
if (cfm.memdata & (1<<7)) {
if (valid_out) {
*valid_out = 1;
}
AICWFDBG(LOGINFO, "issue71: legacy V3 flash DPD result is valid\n");
}
} else {
if (testmode == FW_RFTEST_MODE) {
cfg_base = RAM_LMAC_FW_ADDR + 0x0164;
}
// init misc ram
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x14, &cfm);
if (ret) {
AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret);
return ret;
}
misc_ram_addr = cfm.memdata;
AICWFDBG(LOGERROR, "misc_ram_addr=%x\n", misc_ram_addr);
// bit_mask
ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask);
ram_word_cnt = (MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved)) / 4;
for (i = 0; i < ram_word_cnt; i++) {
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, ram_base_addr + i * 4, &cfm);
if (ret) {
AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret);
return ret;
}
bit_mask[i] = cfm.memdata;
}
AICWFDBG(LOGTRACE, "bit_mask:%x,%x,%x,%x\n",bit_mask[0],bit_mask[1],bit_mask[2],bit_mask[3]);
if ((bit_mask[0] == 0) && ((bit_mask[1] & 0xFFF00000) == 0x80000000) &&
(bit_mask[2] == 0) && ((bit_mask[3] & 0xFFFFFF00) == 0x00000000)) {
if (valid_out) {
*valid_out = 1;
}
bit_mask[i] = cfm.memdata;
}
AICWFDBG(LOGTRACE, "bit_mask:%x,%x,%x,%x\n",bit_mask[0],bit_mask[1],bit_mask[2],bit_mask[3]);
if ((bit_mask[0] == 0) && ((bit_mask[1] & 0xFFF00000) == 0x80000000) &&
(bit_mask[2] == 0) && ((bit_mask[3] & 0xFFFFFF00) == 0x00000000)) {
if (valid_out) {
*valid_out = 1;
}
}
return ret;
@@ -3517,19 +3630,7 @@ int rwnx_plat_userconfig_load_8800dc(struct rwnx_hw *rwnx_hw){
int rwnx_plat_userconfig_load_8800dw(struct rwnx_hw *rwnx_hw){
int size;
u32 *dst=NULL;
u16 pid = le16_to_cpu(rwnx_hw->usbdev->udev->descriptor.idProduct);
char *filename = FW_USERCONFIG_NAME_8800DW;
if (pid == USB_PRODUCT_ID_TENDA
|| pid == USB_PRODUCT_ID_AIC8800FC_CUS3
|| pid == USB_PRODUCT_ID_AIC8800FC_CUS5
|| pid == USB_PRODUCT_ID_AIC8800FC_CUS6) {
filename = FW_USERCONFIG_NAME_8800DW_W311;
} else if (pid == USB_PRODUCT_ID_TENDA_U2
|| pid == USB_PRODUCT_ID_AIC8800FC_CUS1
|| pid == USB_PRODUCT_ID_AIC8800FC_CUS2
|| pid == USB_PRODUCT_ID_AIC8800FC_CUS4) {
filename = FW_USERCONFIG_NAME_8800DW_U2;
}
AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename);
@@ -3583,7 +3684,7 @@ int rwnx_plat_powerlimit_load_8800dcdw(struct rwnx_hw *rwnx_hw, uint16_t chip_id
/* Copy the file on the Embedded side */
AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size);
rwnx_plat_powerlimit_parsing((char *)dst, size, country_code);
rwnx_plat_powerlimit_parsing((char *)dst, size);
rwnx_release_firmware_common(&dst);
@@ -3638,7 +3739,6 @@ void system_config_8800dc(struct rwnx_hw *rwnx_hw){
array3_tbl_t p_syscfg_msk_tbl;
int ret, cnt;
const u32 mem_addr = 0x40500000;
const u32 cache_mem_addr = 0x40100020;
struct dbg_mem_read_cfm rd_mem_addr_cfm;
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, mem_addr, &rd_mem_addr_cfm);
@@ -3652,21 +3752,6 @@ void system_config_8800dc(struct rwnx_hw *rwnx_hw){
chip_mcu_id = 1;
}
if (chip_mcu_id) {
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cache_mem_addr, &rd_mem_addr_cfm);
if (ret) {
AICWFDBG(LOGERROR, "%x rd fail: %d\n", mem_addr, ret);
return;
}
rd_mem_addr_cfm.memdata |= 0x01;
ret = rwnx_send_dbg_mem_write_req(rwnx_hw, cache_mem_addr, rd_mem_addr_cfm.memdata);
if (ret) {
AICWFDBG(LOGERROR, "%x write fail: %d\n", cache_mem_addr, ret);
return;
}
}
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, 0x00000020, &rd_mem_addr_cfm);
if (ret) {
AICWFDBG(LOGERROR, "[0x00000020] rd fail: %d\n", ret);
@@ -3674,10 +3759,7 @@ void system_config_8800dc(struct rwnx_hw *rwnx_hw){
}
chip_sub_id = (u8)(rd_mem_addr_cfm.memdata);
//printk("%x=%x\n", rd_mem_addr_cfm.memaddr, rd_mem_addr_cfm.memdata);
AICWFDBG(LOGINFO, "chip_id=%x, chip_mcu_id=%x, chip_sub_id=%x\n",
chip_id, chip_mcu_id, chip_sub_id);
AICWFDBG(LOGINFO,
"issue71: using complete pre-SDK-V5/V3 DC/DW firmware and loader profile\n");
AICWFDBG(LOGINFO, "chip_id=%x, chip_sub_id=%x\n", chip_id, chip_sub_id);
//Crystal provided by CPU (start)
+68 -318
View File
@@ -4420,29 +4420,13 @@ cfg80211_chandef_identical(const struct cfg80211_chan_def *chandef1,
}
#endif
#define RWNX_CFG80211_OP_TYPE(_member) \
typeof(((struct cfg80211_ops *)0)->_member)
#define RWNX_CFG80211_OP_MATCH(_member, _type) \
__builtin_types_compatible_p(RWNX_CFG80211_OP_TYPE(_member), _type)
#define RWNX_CFG80211_OP_ASSERT(_member, _callback) \
typedef char rwnx_cfg80211_##_member##_signature_must_match[ \
__builtin_types_compatible_p(RWNX_CFG80211_OP_TYPE(_member), \
typeof(&(_callback))) ? 1 : -1]
typedef int (*rwnx_set_monitor_channel_legacy_t)(
struct wiphy *wiphy, struct cfg80211_chan_def *chandef);
typedef int (*rwnx_set_monitor_channel_dev_t)(
struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef);
typedef char rwnx_set_monitor_channel_signature_must_be_supported[
(RWNX_CFG80211_OP_MATCH(set_monitor_channel,
rwnx_set_monitor_channel_legacy_t) ||
RWNX_CFG80211_OP_MATCH(set_monitor_channel,
rwnx_set_monitor_channel_dev_t)) ? 1 : -1];
static int rwnx_cfg80211_set_monitor_channel_common(
struct wiphy *wiphy, struct cfg80211_chan_def *chandef)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0))
static int rwnx_cfg80211_set_monitor_channel(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef)
#else
static int rwnx_cfg80211_set_monitor_channel(struct wiphy *wiphy,
struct cfg80211_chan_def *chandef)
#endif
{
struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
struct rwnx_vif *rwnx_vif;
@@ -4495,40 +4479,19 @@ static int rwnx_cfg80211_set_monitor_channel_common(
return 0;
}
static int rwnx_cfg80211_set_monitor_channel_legacy(
struct wiphy *wiphy, struct cfg80211_chan_def *chandef)
{
return rwnx_cfg80211_set_monitor_channel_common(wiphy, chandef);
}
static int rwnx_cfg80211_set_monitor_channel_dev(
struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
(void)dev;
return rwnx_cfg80211_set_monitor_channel_common(wiphy, chandef);
}
#define RWNX_CFG80211_SET_MONITOR_CHANNEL_CB \
__builtin_choose_expr( \
RWNX_CFG80211_OP_MATCH(set_monitor_channel, \
rwnx_set_monitor_channel_dev_t), \
rwnx_cfg80211_set_monitor_channel_dev, \
rwnx_cfg80211_set_monitor_channel_legacy)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0))
int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
(void)dev;
return rwnx_cfg80211_set_monitor_channel_common(wiphy, chandef);
return rwnx_cfg80211_set_monitor_channel(wiphy, dev, chandef);
}
#else
int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy,
struct cfg80211_chan_def *chandef)
{
return rwnx_cfg80211_set_monitor_channel_common(wiphy, chandef);
return rwnx_cfg80211_set_monitor_channel(wiphy, chandef);
}
#endif
@@ -4590,45 +4553,15 @@ void rwnx_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
* have changed. The actual parameter values are available in
* struct wiphy. If returning an error, no value should be changed.
*/
typedef int (*rwnx_set_wiphy_params_legacy_t)(struct wiphy *wiphy,
u32 changed);
typedef int (*rwnx_set_wiphy_params_radio_t)(struct wiphy *wiphy,
int radio_idx, u32 changed);
typedef char rwnx_set_wiphy_params_signature_must_be_supported[
(RWNX_CFG80211_OP_MATCH(set_wiphy_params,
rwnx_set_wiphy_params_legacy_t) ||
RWNX_CFG80211_OP_MATCH(set_wiphy_params,
rwnx_set_wiphy_params_radio_t)) ? 1 : -1];
static int rwnx_cfg80211_set_wiphy_params_common(struct wiphy *wiphy,
u32 changed)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
static int rwnx_cfg80211_set_wiphy_params(struct wiphy *wiphy, int radio_idx, u32 changed)
#else
static int rwnx_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
#endif
{
(void)wiphy;
(void)changed;
return 0;
}
static int rwnx_cfg80211_set_wiphy_params_legacy(struct wiphy *wiphy,
u32 changed)
{
return rwnx_cfg80211_set_wiphy_params_common(wiphy, changed);
}
static int rwnx_cfg80211_set_wiphy_params_radio(struct wiphy *wiphy,
int radio_idx, u32 changed)
{
(void)radio_idx;
return rwnx_cfg80211_set_wiphy_params_common(wiphy, changed);
}
#define RWNX_CFG80211_SET_WIPHY_PARAMS_CB \
__builtin_choose_expr( \
RWNX_CFG80211_OP_MATCH(set_wiphy_params, \
rwnx_set_wiphy_params_radio_t), \
rwnx_cfg80211_set_wiphy_params_radio, \
rwnx_cfg80211_set_wiphy_params_legacy)
/**
* @set_tx_power: set the transmit power according to the parameters,
@@ -4637,25 +4570,18 @@ static int rwnx_cfg80211_set_wiphy_params_radio(struct wiphy *wiphy,
* always be %NULL unless the driver supports per-vif TX power
* (as advertised by the nl80211 feature flag.)
*/
typedef int (*rwnx_set_tx_power_no_wdev_t)(
struct wiphy *wiphy, enum nl80211_tx_power_setting type, int mbm);
typedef int (*rwnx_set_tx_power_wdev_t)(
struct wiphy *wiphy, struct wireless_dev *wdev,
enum nl80211_tx_power_setting type, int mbm);
typedef int (*rwnx_set_tx_power_radio_t)(
struct wiphy *wiphy, struct wireless_dev *wdev, int radio_idx,
enum nl80211_tx_power_setting type, int mbm);
typedef char rwnx_set_tx_power_signature_must_be_supported[
(RWNX_CFG80211_OP_MATCH(set_tx_power, rwnx_set_tx_power_no_wdev_t) ||
RWNX_CFG80211_OP_MATCH(set_tx_power, rwnx_set_tx_power_wdev_t) ||
RWNX_CFG80211_OP_MATCH(set_tx_power,
rwnx_set_tx_power_radio_t)) ? 1 : -1];
static int rwnx_cfg80211_set_tx_power_common(
struct wiphy *wiphy, struct wireless_dev *wdev,
enum nl80211_tx_power_setting type, int mbm)
static int rwnx_cfg80211_set_tx_power(struct wiphy *wiphy,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
struct wireless_dev *wdev,
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
int radio_idx,
#endif
enum nl80211_tx_power_setting type, int mbm)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
struct wireless_dev *wdev = NULL;
#endif
struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
struct rwnx_vif *vif;
s8 pwr;
@@ -4681,112 +4607,31 @@ static int rwnx_cfg80211_set_tx_power_common(
return res;
}
static int rwnx_cfg80211_set_tx_power_no_wdev(
struct wiphy *wiphy, enum nl80211_tx_power_setting type, int mbm)
{
return rwnx_cfg80211_set_tx_power_common(wiphy, NULL, type, mbm);
}
static int rwnx_cfg80211_set_tx_power_wdev(
struct wiphy *wiphy, struct wireless_dev *wdev,
enum nl80211_tx_power_setting type, int mbm)
{
return rwnx_cfg80211_set_tx_power_common(wiphy, wdev, type, mbm);
}
static int rwnx_cfg80211_set_tx_power_radio(
struct wiphy *wiphy, struct wireless_dev *wdev, int radio_idx,
enum nl80211_tx_power_setting type, int mbm)
{
(void)radio_idx;
return rwnx_cfg80211_set_tx_power_common(wiphy, wdev, type, mbm);
}
#define RWNX_CFG80211_SET_TX_POWER_CB \
__builtin_choose_expr( \
RWNX_CFG80211_OP_MATCH(set_tx_power, rwnx_set_tx_power_radio_t), \
rwnx_cfg80211_set_tx_power_radio, \
__builtin_choose_expr( \
RWNX_CFG80211_OP_MATCH(set_tx_power, rwnx_set_tx_power_wdev_t), \
rwnx_cfg80211_set_tx_power_wdev, \
rwnx_cfg80211_set_tx_power_no_wdev))
typedef int (*rwnx_get_tx_power_no_wdev_t)(struct wiphy *wiphy, int *dbm);
typedef int (*rwnx_get_tx_power_wdev_t)(struct wiphy *wiphy,
struct wireless_dev *wdev, int *dbm);
typedef int (*rwnx_get_tx_power_link_t)(struct wiphy *wiphy,
struct wireless_dev *wdev,
unsigned int link_id, int *dbm);
typedef int (*rwnx_get_tx_power_radio_link_t)(
struct wiphy *wiphy, struct wireless_dev *wdev, int radio_idx,
unsigned int link_id, int *dbm);
typedef char rwnx_get_tx_power_signature_must_be_supported[
(RWNX_CFG80211_OP_MATCH(get_tx_power, rwnx_get_tx_power_no_wdev_t) ||
RWNX_CFG80211_OP_MATCH(get_tx_power, rwnx_get_tx_power_wdev_t) ||
RWNX_CFG80211_OP_MATCH(get_tx_power, rwnx_get_tx_power_link_t) ||
RWNX_CFG80211_OP_MATCH(get_tx_power,
rwnx_get_tx_power_radio_link_t)) ? 1 : -1];
static int rwnx_cfg80211_get_tx_power_common(struct wiphy *wiphy,
struct wireless_dev *wdev,
int *dbm)
static int rwnx_cfg80211_get_tx_power(struct wiphy *wiphy,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
struct wireless_dev *wdev,
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
int radio_idx,
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 14, 0)
unsigned int link_id,
#endif
int *mbm)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
struct wireless_dev *wdev = NULL;
#endif
//struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
//struct rwnx_vif *vif;
s8 pwr = 0;
int res = 0;
(void)wiphy;
(void)wdev;
if (!dbm)
return -EINVAL;
*mbm = get_txpwr_max(pwr);
*dbm = get_txpwr_max(pwr);
return 0;
return res;
}
static int rwnx_cfg80211_get_tx_power_no_wdev(struct wiphy *wiphy, int *dbm)
{
return rwnx_cfg80211_get_tx_power_common(wiphy, NULL, dbm);
}
static int rwnx_cfg80211_get_tx_power_wdev(struct wiphy *wiphy,
struct wireless_dev *wdev,
int *dbm)
{
return rwnx_cfg80211_get_tx_power_common(wiphy, wdev, dbm);
}
static int rwnx_cfg80211_get_tx_power_link(struct wiphy *wiphy,
struct wireless_dev *wdev,
unsigned int link_id, int *dbm)
{
(void)link_id;
return rwnx_cfg80211_get_tx_power_common(wiphy, wdev, dbm);
}
static int rwnx_cfg80211_get_tx_power_radio_link(
struct wiphy *wiphy, struct wireless_dev *wdev, int radio_idx,
unsigned int link_id, int *dbm)
{
(void)radio_idx;
(void)link_id;
return rwnx_cfg80211_get_tx_power_common(wiphy, wdev, dbm);
}
#define RWNX_CFG80211_GET_TX_POWER_CB \
__builtin_choose_expr( \
RWNX_CFG80211_OP_MATCH(get_tx_power, \
rwnx_get_tx_power_radio_link_t), \
rwnx_cfg80211_get_tx_power_radio_link, \
__builtin_choose_expr( \
RWNX_CFG80211_OP_MATCH(get_tx_power, \
rwnx_get_tx_power_link_t), \
rwnx_cfg80211_get_tx_power_link, \
__builtin_choose_expr( \
RWNX_CFG80211_OP_MATCH(get_tx_power, \
rwnx_get_tx_power_wdev_t), \
rwnx_cfg80211_get_tx_power_wdev, \
rwnx_cfg80211_get_tx_power_no_wdev)))
/**
* @set_power_mgmt: set the power save to one of those two modes:
* Power-save off
@@ -5154,7 +4999,11 @@ static int rwnx_cfg80211_get_channel(struct wiphy *wiphy,
if (rwnx_vif->vif_index == rwnx_hw->monitor_vif)
{
//retrieve channel from firmware
rwnx_cfg80211_set_monitor_channel_common(wiphy, NULL);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0))
rwnx_cfg80211_set_monitor_channel(wiphy, wdev->netdev, NULL);
#else
rwnx_cfg80211_set_monitor_channel(wiphy, NULL);
#endif
}
//Check if channel context is valid
@@ -5341,28 +5190,17 @@ send_frame:
/**
* @start_radar_detection: Start radar detection in the driver.
*/
typedef int (*rwnx_start_radar_detection_legacy_t)(
struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef);
typedef int (*rwnx_start_radar_detection_cac_t)(
struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef, u32 cac_time_ms);
typedef int (*rwnx_start_radar_detection_link_t)(
struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef, u32 cac_time_ms, int link_id);
typedef char rwnx_start_radar_detection_signature_must_be_supported[
(RWNX_CFG80211_OP_MATCH(start_radar_detection,
rwnx_start_radar_detection_legacy_t) ||
RWNX_CFG80211_OP_MATCH(start_radar_detection,
rwnx_start_radar_detection_cac_t) ||
RWNX_CFG80211_OP_MATCH(start_radar_detection,
rwnx_start_radar_detection_link_t)) ? 1 : -1];
static int rwnx_cfg80211_start_radar_detection_common(
struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef, u32 cac_time_ms,
bool start_cac_timer)
static
int rwnx_cfg80211_start_radar_detection(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_chan_def *chandef
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
, u32 cac_time_ms
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0))
, int link_id
#endif
)
{
struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
struct rwnx_vif *rwnx_vif = netdev_priv(dev);
@@ -5370,8 +5208,9 @@ static int rwnx_cfg80211_start_radar_detection_common(
printk("%s\n", __func__);
if (start_cac_timer)
rwnx_radar_start_cac(&rwnx_hw->radar, cac_time_ms, rwnx_vif);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
rwnx_radar_start_cac(&rwnx_hw->radar, cac_time_ms, rwnx_vif);
#endif
rwnx_send_apm_start_cac_req(rwnx_hw, rwnx_vif, chandef, &cfm);
if (cfm.status == CO_OK) {
@@ -5389,42 +5228,6 @@ static int rwnx_cfg80211_start_radar_detection_common(
return 0;
}
static int rwnx_cfg80211_start_radar_detection_legacy(
struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
return rwnx_cfg80211_start_radar_detection_common(
wiphy, dev, chandef, 0, false);
}
static int rwnx_cfg80211_start_radar_detection_cac(
struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef, u32 cac_time_ms)
{
return rwnx_cfg80211_start_radar_detection_common(
wiphy, dev, chandef, cac_time_ms, true);
}
static int rwnx_cfg80211_start_radar_detection_link(
struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef, u32 cac_time_ms, int link_id)
{
(void)link_id;
return rwnx_cfg80211_start_radar_detection_common(
wiphy, dev, chandef, cac_time_ms, true);
}
#define RWNX_CFG80211_START_RADAR_DETECTION_CB \
__builtin_choose_expr( \
RWNX_CFG80211_OP_MATCH(start_radar_detection, \
rwnx_start_radar_detection_link_t), \
rwnx_cfg80211_start_radar_detection_link, \
__builtin_choose_expr( \
RWNX_CFG80211_OP_MATCH(start_radar_detection, \
rwnx_start_radar_detection_cac_t), \
rwnx_cfg80211_start_radar_detection_cac, \
rwnx_cfg80211_start_radar_detection_legacy))
/**
* @update_ft_ies: Provide updated Fast BSS Transition information to the
* driver. If the SME is in the driver/firmware, this information can be
@@ -6717,59 +6520,6 @@ static int rwnx_cfg80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev)
return 0;
}
/*
* Keep every direct cfg80211_ops assignment as a hard compile-time check.
* OpenWrt can backport cfg80211 APIs without changing LINUX_VERSION_CODE, and
* an incompatible callback must remain a build failure even when warnings are
* relaxed by an external package.
*/
RWNX_CFG80211_OP_ASSERT(add_virtual_intf, rwnx_cfg80211_add_iface);
RWNX_CFG80211_OP_ASSERT(del_virtual_intf, rwnx_cfg80211_del_iface);
RWNX_CFG80211_OP_ASSERT(change_virtual_intf, rwnx_cfg80211_change_iface);
RWNX_CFG80211_OP_ASSERT(start_p2p_device, rwnx_cfgp2p_start_p2p_device);
RWNX_CFG80211_OP_ASSERT(stop_p2p_device, rwnx_cfgp2p_stop_p2p_device);
RWNX_CFG80211_OP_ASSERT(scan, rwnx_cfg80211_scan);
RWNX_CFG80211_OP_ASSERT(connect, rwnx_cfg80211_connect);
RWNX_CFG80211_OP_ASSERT(disconnect, rwnx_cfg80211_disconnect);
RWNX_CFG80211_OP_ASSERT(add_key, rwnx_cfg80211_add_key);
RWNX_CFG80211_OP_ASSERT(get_key, rwnx_cfg80211_get_key);
RWNX_CFG80211_OP_ASSERT(del_key, rwnx_cfg80211_del_key);
RWNX_CFG80211_OP_ASSERT(set_default_key, rwnx_cfg80211_set_default_key);
RWNX_CFG80211_OP_ASSERT(set_default_mgmt_key,
rwnx_cfg80211_set_default_mgmt_key);
RWNX_CFG80211_OP_ASSERT(add_station, rwnx_cfg80211_add_station);
RWNX_CFG80211_OP_ASSERT(del_station, rwnx_cfg80211_del_station_compat);
RWNX_CFG80211_OP_ASSERT(change_station, rwnx_cfg80211_change_station);
RWNX_CFG80211_OP_ASSERT(mgmt_tx, rwnx_cfg80211_mgmt_tx);
RWNX_CFG80211_OP_ASSERT(start_ap, rwnx_cfg80211_start_ap);
RWNX_CFG80211_OP_ASSERT(change_beacon, rwnx_cfg80211_change_beacon);
RWNX_CFG80211_OP_ASSERT(stop_ap, rwnx_cfg80211_stop_ap);
RWNX_CFG80211_OP_ASSERT(probe_client, rwnx_cfg80211_probe_client);
RWNX_CFG80211_OP_ASSERT(set_txq_params, rwnx_cfg80211_set_txq_params);
RWNX_CFG80211_OP_ASSERT(set_power_mgmt, rwnx_cfg80211_set_power_mgmt);
RWNX_CFG80211_OP_ASSERT(get_station, rwnx_cfg80211_get_station);
RWNX_CFG80211_OP_ASSERT(remain_on_channel,
rwnx_cfg80211_remain_on_channel);
RWNX_CFG80211_OP_ASSERT(cancel_remain_on_channel,
rwnx_cfg80211_cancel_remain_on_channel);
RWNX_CFG80211_OP_ASSERT(dump_survey, rwnx_cfg80211_dump_survey);
RWNX_CFG80211_OP_ASSERT(get_channel, rwnx_cfg80211_get_channel);
RWNX_CFG80211_OP_ASSERT(update_ft_ies, rwnx_cfg80211_update_ft_ies);
RWNX_CFG80211_OP_ASSERT(set_cqm_rssi_config,
rwnx_cfg80211_set_cqm_rssi_config);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
RWNX_CFG80211_OP_ASSERT(channel_switch, rwnx_cfg80211_channel_switch);
#endif
RWNX_CFG80211_OP_ASSERT(change_bss, rwnx_cfg80211_change_bss);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || \
defined(CONFIG_WPA3_FOR_OLD_KERNEL)
RWNX_CFG80211_OP_ASSERT(external_auth, rwnx_cfg80211_external_auth);
#endif
#ifdef CONFIG_SCHED_SCAN
RWNX_CFG80211_OP_ASSERT(sched_scan_start, rwnx_cfg80211_sched_scan_start);
RWNX_CFG80211_OP_ASSERT(sched_scan_stop, rwnx_cfg80211_sched_scan_stop);
#endif
static struct cfg80211_ops rwnx_cfg80211_ops = {
.add_virtual_intf = rwnx_cfg80211_add_iface,
.del_virtual_intf = rwnx_cfg80211_del_iface,
@@ -6791,20 +6541,20 @@ static struct cfg80211_ops rwnx_cfg80211_ops = {
.start_ap = rwnx_cfg80211_start_ap,
.change_beacon = rwnx_cfg80211_change_beacon,
.stop_ap = rwnx_cfg80211_stop_ap,
.set_monitor_channel = RWNX_CFG80211_SET_MONITOR_CHANNEL_CB,
.set_monitor_channel = rwnx_cfg80211_set_monitor_channel,
.probe_client = rwnx_cfg80211_probe_client,
// .mgmt_frame_register = rwnx_cfg80211_mgmt_frame_register,
.set_wiphy_params = RWNX_CFG80211_SET_WIPHY_PARAMS_CB,
.set_wiphy_params = rwnx_cfg80211_set_wiphy_params,
.set_txq_params = rwnx_cfg80211_set_txq_params,
.set_tx_power = RWNX_CFG80211_SET_TX_POWER_CB,
.get_tx_power = RWNX_CFG80211_GET_TX_POWER_CB,
.set_tx_power = rwnx_cfg80211_set_tx_power,
.get_tx_power = rwnx_cfg80211_get_tx_power,
.set_power_mgmt = rwnx_cfg80211_set_power_mgmt,
.get_station = rwnx_cfg80211_get_station,
.remain_on_channel = rwnx_cfg80211_remain_on_channel,
.cancel_remain_on_channel = rwnx_cfg80211_cancel_remain_on_channel,
.dump_survey = rwnx_cfg80211_dump_survey,
.get_channel = rwnx_cfg80211_get_channel,
.start_radar_detection = RWNX_CFG80211_START_RADAR_DETECTION_CB,
.start_radar_detection = rwnx_cfg80211_start_radar_detection,
.update_ft_ies = rwnx_cfg80211_update_ft_ies,
.set_cqm_rssi_config = rwnx_cfg80211_set_cqm_rssi_config,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+18 -51
View File
@@ -22,52 +22,6 @@
#include "rwnx_events.h"
#include "rwnx_compat.h"
#ifdef CONFIG_RWNX_FULLMAC
/* OpenWrt can backport cfg80211 helpers without changing LINUX_VERSION_CODE. */
typedef void (*rwnx_cfg80211_cac_event_no_chandef_t)(
struct net_device *netdev, enum nl80211_radar_event event, gfp_t gfp);
typedef void (*rwnx_cfg80211_cac_event_chandef_t)(
struct net_device *netdev, const struct cfg80211_chan_def *chandef,
enum nl80211_radar_event event, gfp_t gfp);
typedef void (*rwnx_cfg80211_cac_event_link_t)(
struct net_device *netdev, const struct cfg80211_chan_def *chandef,
enum nl80211_radar_event event, gfp_t gfp, unsigned int link_id);
#define RWNX_CFG80211_CAC_EVENT_MATCH(_type) \
__builtin_types_compatible_p(typeof(&cfg80211_cac_event), _type)
typedef char rwnx_cfg80211_cac_event_signature_must_be_supported[
(RWNX_CFG80211_CAC_EVENT_MATCH(
rwnx_cfg80211_cac_event_no_chandef_t) ||
RWNX_CFG80211_CAC_EVENT_MATCH(rwnx_cfg80211_cac_event_chandef_t) ||
RWNX_CFG80211_CAC_EVENT_MATCH(rwnx_cfg80211_cac_event_link_t)) ? 1 : -1];
static void rwnx_cfg80211_cac_event_compat(
struct net_device *netdev, const struct cfg80211_chan_def *chandef,
enum nl80211_radar_event event, gfp_t gfp)
{
union {
typeof(&cfg80211_cac_event) actual;
rwnx_cfg80211_cac_event_no_chandef_t no_chandef;
rwnx_cfg80211_cac_event_chandef_t chandef;
rwnx_cfg80211_cac_event_link_t link;
} helper = { .actual = &cfg80211_cac_event };
if (RWNX_CFG80211_CAC_EVENT_MATCH(
rwnx_cfg80211_cac_event_no_chandef_t)) {
helper.no_chandef(netdev, event, gfp);
return;
}
if (RWNX_CFG80211_CAC_EVENT_MATCH(rwnx_cfg80211_cac_event_link_t)) {
helper.link(netdev, chandef, event, gfp, 0);
return;
}
helper.chandef(netdev, chandef, event, gfp);
}
#endif
/*
* tolerated deviation of radar time stamp in usecs on both sides
* TODO: this might need to be HW-dependent
@@ -1517,8 +1471,15 @@ static void rwnx_radar_cac_work(struct work_struct *ws)
}
ctxt = &rwnx_hw->chanctx_table[radar->cac_vif->ch_index];
rwnx_cfg80211_cac_event_compat(radar->cac_vif->ndev, &ctxt->chan_def,
NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
cfg80211_cac_event(radar->cac_vif->ndev,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
&ctxt->chan_def,
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
NL80211_RADAR_CAC_FINISHED, GFP_KERNEL, 0);
#else
NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
#endif
rwnx_send_apm_stop_cac_req(rwnx_hw, radar->cac_vif);
rwnx_chanctx_unlink(radar->cac_vif);
@@ -1652,9 +1613,15 @@ void rwnx_radar_cancel_cac(struct rwnx_radar *radar)
struct rwnx_chanctx *ctxt;
ctxt = &rwnx_hw->chanctx_table[radar->cac_vif->ch_index];
rwnx_send_apm_stop_cac_req(rwnx_hw, radar->cac_vif);
rwnx_cfg80211_cac_event_compat(radar->cac_vif->ndev,
&ctxt->chan_def,
NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
cfg80211_cac_event(radar->cac_vif->ndev,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
&ctxt->chan_def,
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
NL80211_RADAR_CAC_FINISHED, GFP_KERNEL, 0);
#else
NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
#endif
rwnx_chanctx_unlink(radar->cac_vif);
}
+12 -58
View File
@@ -34,60 +34,6 @@
#define IEEE80211_MAX_CHAINS 4
#endif
/* OpenWrt can backport these helpers without changing LINUX_VERSION_CODE. */
typedef bool (*rwnx_cfg80211_rx_frame_legacy_t)(struct net_device *dev,
const u8 *addr, gfp_t gfp);
typedef bool (*rwnx_cfg80211_rx_frame_link_t)(struct net_device *dev,
const u8 *addr, int link_id,
gfp_t gfp);
#define RWNX_CFG80211_HELPER_MATCH(_helper, _type) \
__builtin_types_compatible_p(typeof(&(_helper)), _type)
typedef char rwnx_cfg80211_rx_spurious_frame_signature_must_be_supported[
(RWNX_CFG80211_HELPER_MATCH(cfg80211_rx_spurious_frame,
rwnx_cfg80211_rx_frame_legacy_t) ||
RWNX_CFG80211_HELPER_MATCH(cfg80211_rx_spurious_frame,
rwnx_cfg80211_rx_frame_link_t)) ? 1 : -1];
typedef char rwnx_cfg80211_rx_unexpected_4addr_frame_signature_must_be_supported[
(RWNX_CFG80211_HELPER_MATCH(cfg80211_rx_unexpected_4addr_frame,
rwnx_cfg80211_rx_frame_legacy_t) ||
RWNX_CFG80211_HELPER_MATCH(cfg80211_rx_unexpected_4addr_frame,
rwnx_cfg80211_rx_frame_link_t)) ? 1 : -1];
static bool rwnx_cfg80211_rx_spurious_frame_compat(struct net_device *dev,
const u8 *addr, gfp_t gfp)
{
union {
typeof(&cfg80211_rx_spurious_frame) actual;
rwnx_cfg80211_rx_frame_legacy_t legacy;
rwnx_cfg80211_rx_frame_link_t link;
} helper = { .actual = &cfg80211_rx_spurious_frame };
if (RWNX_CFG80211_HELPER_MATCH(cfg80211_rx_spurious_frame,
rwnx_cfg80211_rx_frame_link_t))
return helper.link(dev, addr, -1, gfp);
return helper.legacy(dev, addr, gfp);
}
static bool rwnx_cfg80211_rx_unexpected_4addr_frame_compat(
struct net_device *dev, const u8 *addr, gfp_t gfp)
{
union {
typeof(&cfg80211_rx_unexpected_4addr_frame) actual;
rwnx_cfg80211_rx_frame_legacy_t legacy;
rwnx_cfg80211_rx_frame_link_t link;
} helper = { .actual = &cfg80211_rx_unexpected_4addr_frame };
if (RWNX_CFG80211_HELPER_MATCH(cfg80211_rx_unexpected_4addr_frame,
rwnx_cfg80211_rx_frame_link_t))
return helper.link(dev, addr, -1, gfp);
return helper.legacy(dev, addr, gfp);
}
u8 dhcped = 0;
u16 tx_legrates_lut_rate[] = {
@@ -2448,8 +2394,11 @@ check_len_update:
hdr = (struct ieee80211_hdr *)(skb->data + msdu_offset);
rwnx_vif = rwnx_rx_get_vif(rwnx_hw, hw_rxhdr->flags_vif_idx);
if (rwnx_vif) {
rwnx_cfg80211_rx_spurious_frame_compat(rwnx_vif->ndev,
hdr->addr2, GFP_ATOMIC);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
cfg80211_rx_spurious_frame(rwnx_vif->ndev, hdr->addr2, -1, GFP_ATOMIC);
#else
cfg80211_rx_spurious_frame(rwnx_vif->ndev, hdr->addr2, GFP_ATOMIC);
#endif
}
goto end;
}
@@ -2792,8 +2741,13 @@ check_len_update:
if (hw_rxhdr->flags_is_4addr && !rwnx_vif->use_4addr) {
printk("aicwf: 4addr flag error\n");
rwnx_cfg80211_rx_unexpected_4addr_frame_compat(
rwnx_vif->ndev, sta->mac_addr, GFP_ATOMIC);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
cfg80211_rx_unexpected_4addr_frame(rwnx_vif->ndev,
sta->mac_addr, -1, GFP_ATOMIC);
#else
cfg80211_rx_unexpected_4addr_frame(rwnx_vif->ndev,
sta->mac_addr, GFP_ATOMIC);
#endif
}
}
+111 -13
View File
@@ -39,14 +39,36 @@ typedef struct {
#define AIC_PATCH_OFST(mem) ((size_t) &((aic_patch_t *)0)->mem)
#define AIC_PATCH_ADDR(mem) ((u32) (aic_patch_str_base + AIC_PATCH_OFST(mem)))
/*
* Issue #58 legacy-loader test.
*
* Keep this table aligned with the SDK V3 D80 firmware imported from Radxa
* commit 254d47e6a131dbed5ba32131972f4719f3e1c7fe. Newer loader patches use
* different RX aggregation settings and a user_ext_flags field that is not
* part of this firmware generation.
*/
#define USER_PWROFST_COVER_CALIB_FLAG (0x01U << 0)
#define USER_CHAN_MAX_TXPWR_EN_FLAG (0x01U << 1)
#define USER_TX_USE_ANA_F_FLAG (0x01U << 2)
#define USER_APM_PRBRSP_OFFLOAD_DISABLE_FLAG (0x01U << 3)
#define USER_HE_MU_EDCA_UPDATE_DISABLE_FLAG (0x01U << 4)
#define USER_LOFT_CALIB_DISABLE_FLAG (0x01U << 6)
#define USER_CAPA_CALIB_DISABLE_FLAG (0x01U << 7)
#define USER_PWR_CALIB_DISABLE_FLAG (0x01U << 8)
#define USER_IPA_CALIB_DISABLE_FLAG (0x01U << 13)
#define USER_EXT_FLAGS_DEFAULT_D80 (USER_PWROFST_COVER_CALIB_FLAG)
#define CFG_USER_PWROFST_COVER_CALIB_EN (1)
#if (defined(CONFIG_POWER_LIMIT))
#define CFG_USER_CHAN_MAX_TXPWR_EN (1)
#else
#define CFG_USER_CHAN_MAX_TXPWR_EN (0)
#endif
#define CFG_USER_TX_USE_ANA_F_EN (0)
#if (defined(CONFIG_PRBREQ_REPORT))
#define CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE (1)
#else
#define CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE (0)
#endif
#define CFG_USER_HE_MU_EDCA_UPDATE_DISABLE (0)
#define CFG_USER_LOFT_CALIB_DISABLE_DISABLE (0)
#define CFG_USER_CAPA_CALIB_DISABLE_DISABLE (0)
#define CFG_USER_PWR_CALIB_DISABLE_DISABLE (0)
#define CFG_USER_IPA_CALIB_DISABLE_DISABLE (0)
u32 patch_tbl_d80[][2] =
{
#ifdef USE_5G
@@ -54,7 +76,54 @@ u32 patch_tbl_d80[][2] =
#else
{0x00b4, 0xf3010000},
#endif
{0x0170, 0x00000002},//rx aggr counter
#ifdef CONFIG_PLATFORM_HI
{0x0170, 0x00010001},//rx aggr counter
#else
{0x0170, 0x0001000A},//rx aggr counter
#endif
{0x0188,
(USER_EXT_FLAGS_DEFAULT_D80 |
#if CFG_USER_CHAN_MAX_TXPWR_EN
USER_CHAN_MAX_TXPWR_EN_FLAG |
#endif
#if CFG_USER_TX_USE_ANA_F_EN
USER_TX_USE_ANA_F_FLAG |
#endif
#if CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE
USER_APM_PRBRSP_OFFLOAD_DISABLE_FLAG |
#endif
#if CFG_USER_HE_MU_EDCA_UPDATE_DISABLE
USER_HE_MU_EDCA_UPDATE_DISABLE_FLAG |
#endif
#if CFG_USER_LOFT_CALIB_DISABLE_DISABLE
USER_LOFT_CALIB_DISABLE_FLAG |
#endif
#if CFG_USER_CAPA_CALIB_DISABLE_DISABLE
USER_CAPA_CALIB_DISABLE_FLAG |
#endif
#if CFG_USER_PWR_CALIB_DISABLE_DISABLE
USER_PWR_CALIB_DISABLE_FLAG |
#endif
#if CFG_USER_IPA_CALIB_DISABLE_DISABLE
USER_IPA_CALIB_DISABLE_FLAG |
#endif
0) & ~(
#if !CFG_USER_PWROFST_COVER_CALIB_EN
USER_PWROFST_COVER_CALIB_FLAG |
#endif
0)
}, // user_ext_flags
#ifdef CONFIG_RADAR_OR_IR_DETECT
{0x0019c,0x00000900},
#endif
#ifdef CONFIG_WOWLAN
{0x019c,0x01000000},
#ifdef ANDROID_PLATFORM
{0x01A0, 0x01000001},
#endif
#endif
};
//adap test
@@ -75,11 +144,16 @@ u32 syscfg_tbl_8800d80[][2] = {
extern int adap_test;
#define NEW_PATCH_BUFFER_MAP 1
int aicwf_patch_config_8800d80(struct aic_usb_dev *usb_dev)
{
u32 rd_patch_addr;
u32 aic_patch_addr;
u32 config_base, aic_patch_str_base;
#if (NEW_PATCH_BUFFER_MAP)
u32 patch_buff_addr, patch_buff_base, rd_version_addr, rd_version_val;
#endif
uint32_t start_addr = 0x001D7000;
u32 patch_addr = start_addr;
u32 patch_cnt = sizeof(patch_tbl_d80) / 4 / 2;
@@ -116,6 +190,32 @@ int aicwf_patch_config_8800d80(struct aic_usb_dev *usb_dev)
AICWFDBG(LOGERROR, "%x=%x\n", rd_patch_addr_cfm.memaddr, rd_patch_addr_cfm.memdata);
aic_patch_str_base = rd_patch_addr_cfm.memdata;
#if (NEW_PATCH_BUFFER_MAP)
if (chip_id == CHIP_REV_U01) {
rd_version_addr = RAM_FMAC_FW_ADDR_8800D80 + 0x01C;
} else {
rd_version_addr = RAM_FMAC_FW_ADDR_8800D80_U02 + 0x01C;
}
if ((ret = rwnx_send_dbg_mem_read_req(usb_dev, rd_version_addr, &rd_patch_addr_cfm))) {
AICWFDBG(LOGERROR, "version val[0x%x] rd fail: %d\n", rd_version_addr, ret);
return ret;
}
rd_version_val = rd_patch_addr_cfm.memdata;
AICWFDBG(LOGINFO, "rd_version_val=%08X\n", rd_version_val);
usb_dev->fw_version_uint = rd_version_val;
if (rd_version_val > 0x06090100) {
patch_buff_addr = rd_patch_addr + 12;
ret = rwnx_send_dbg_mem_read_req(usb_dev, patch_buff_addr, &rd_patch_addr_cfm);
if (ret) {
AICWFDBG(LOGERROR, "patch buf rd fail\n");
return ret;
}
AICWFDBG(LOGINFO, "%x=%x\n", rd_patch_addr_cfm.memaddr, rd_patch_addr_cfm.memdata);
patch_buff_base = rd_patch_addr_cfm.memdata;
patch_addr = start_addr = patch_buff_base;
}
#endif
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, AIC_PATCH_ADDR(magic_num), AIC_PATCH_MAGIG_NUM))) {
AICWFDBG(LOGERROR, "maigic_num[0x%x] write fail: %d\n", AIC_PATCH_ADDR(magic_num), ret);
return ret;
@@ -246,11 +346,10 @@ int system_config_8800d80(struct aic_usb_dev *usb_dev){
}
chip_id = (u8)(rd_mem_addr_cfm.memdata >> 16);
printk("chip_id=%x, chip_mcu_id = %d\n", chip_id, chip_mcu_id);
printk("AIC8800D80 legacy: using Radxa SDK V3 loader profile\n");
if (chip_mcu_id == 1) {
if (chip_mcu_id) {
ret = rwnx_send_dbg_mem_read_req(usb_dev, cache_mem_addr, &rd_mem_addr_cfm);
if (ret) {
printk("%x rd fail: %d\n", cache_mem_addr, ret);
printk("%x rd fail: %d\n", mem_addr, ret);
return ret;
}
rd_mem_addr_cfm.memdata |= 0x01;
@@ -259,7 +358,6 @@ int system_config_8800d80(struct aic_usb_dev *usb_dev){
printk("%x write fail: %d\n", cache_mem_addr, ret);
return ret;
}
printk("AIC8800D80 MCU1: enabled Bluetooth cache fix\n");
}
#if 1
syscfg_num = sizeof(syscfg_tbl_8800d80) / sizeof(u32) / 2;
-18
View File
@@ -1,18 +0,0 @@
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
@@ -1,229 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/atomic.h>
#include <linux/kernel.h>
#include <linux/kprobes.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/ptrace.h>
#include <linux/usb.h>
#define AIC_USB_VENDOR_ID 0x368b
#define AIC_USB_PRODUCT_ID 0x8d81
#define USB_BT_SUBCLASS 0x01
#define USB_BT_PROTOCOL 0x01
static atomic64_t injection_count = ATOMIC64_INIT(0);
static const char *hook_name = "none";
static int injections_get(char *buffer, const struct kernel_param *kp)
{
(void)kp;
return scnprintf(buffer, PAGE_SIZE, "%lld\n",
(long long)atomic64_read(&injection_count));
}
static const struct kernel_param_ops injections_ops = {
.get = injections_get,
};
module_param_cb(injections, &injections_ops, NULL, 0444);
MODULE_PARM_DESC(injections, "Number of AIC ACL bulk OUT URBs modified");
static int hook_get(char *buffer, const struct kernel_param *kp)
{
(void)kp;
return scnprintf(buffer, PAGE_SIZE, "%s\n", hook_name);
}
static const struct kernel_param_ops hook_ops = {
.get = hook_get,
};
module_param_cb(hook, &hook_ops, NULL, 0444);
MODULE_PARM_DESC(hook, "Active injection hook");
#if IS_ENABLED(CONFIG_KPROBES)
enum aic_zlp_hook {
AIC_ZLP_HOOK_NONE,
AIC_ZLP_HOOK_BTUSB_RETURN,
AIC_ZLP_HOOK_USB_SUBMIT,
};
static enum aic_zlp_hook active_hook;
static bool is_aic_bulk_out(const struct urb *urb)
{
const struct usb_device *udev;
if (!urb)
return false;
udev = urb->dev;
if (!udev)
return false;
if (le16_to_cpu(udev->descriptor.idVendor) != AIC_USB_VENDOR_ID ||
le16_to_cpu(udev->descriptor.idProduct) != AIC_USB_PRODUCT_ID)
return false;
return usb_pipetype(urb->pipe) == PIPE_BULK &&
usb_pipeout(urb->pipe);
}
static bool is_bluetooth_acl_endpoint(const struct urb *urb)
{
const struct usb_endpoint_descriptor *ep;
struct usb_host_interface *alt;
struct usb_interface *intf;
unsigned int endpoint;
int i;
if (!is_aic_bulk_out(urb))
return false;
intf = usb_ifnum_to_if(urb->dev, 0);
if (!intf)
return false;
alt = READ_ONCE(intf->cur_altsetting);
if (!alt ||
alt->desc.bInterfaceClass != USB_CLASS_WIRELESS_CONTROLLER ||
alt->desc.bInterfaceSubClass != USB_BT_SUBCLASS ||
alt->desc.bInterfaceProtocol != USB_BT_PROTOCOL)
return false;
endpoint = usb_pipeendpoint(urb->pipe);
for (i = 0; i < alt->desc.bNumEndpoints; i++) {
ep = &alt->endpoint[i].desc;
if (usb_endpoint_is_bulk_out(ep) &&
usb_endpoint_num(ep) == endpoint)
return true;
}
return false;
}
static void enable_zlp(struct urb *urb)
{
long long count;
if (urb->transfer_flags & URB_ZERO_PACKET)
return;
urb->transfer_flags |= URB_ZERO_PACKET;
count = atomic64_inc_return(&injection_count);
if (count == 1)
pr_info("enabled ZLP on the first 368b:8d81 ACL bulk OUT URB\n");
}
static int alloc_bulk_urb_ret_handler(struct kretprobe_instance *ri,
struct pt_regs *regs)
{
struct urb *urb;
(void)ri;
urb = (struct urb *)regs_return_value(regs);
if (!is_aic_bulk_out(urb))
return 0;
enable_zlp(urb);
return 0;
}
static struct kretprobe alloc_bulk_urb_probe = {
.kp.symbol_name = "btusb:alloc_bulk_urb",
.handler = alloc_bulk_urb_ret_handler,
};
static int usb_submit_urb_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct urb *urb;
(void)p;
urb = (struct urb *)regs_get_kernel_argument(regs, 0);
if (is_bluetooth_acl_endpoint(urb))
enable_zlp(urb);
return 0;
}
static struct kprobe usb_submit_urb_probe = {
.symbol_name = "usb_submit_urb",
.pre_handler = usb_submit_urb_pre_handler,
};
static int __init aic_zlp_quirk_init(void)
{
int ret;
ret = register_kretprobe(&alloc_bulk_urb_probe);
if (!ret) {
active_hook = AIC_ZLP_HOOK_BTUSB_RETURN;
hook_name = "btusb:alloc_bulk_urb";
pr_info("attached to system btusb for USB device 368b:8d81\n");
return 0;
}
pr_warn("btusb return hook unavailable (%d), trying USB submit fallback\n",
ret);
ret = register_kprobe(&usb_submit_urb_probe);
if (ret) {
pr_err("cannot attach to usb_submit_urb: %d\n", ret);
return ret;
}
active_hook = AIC_ZLP_HOOK_USB_SUBMIT;
hook_name = "usb_submit_urb";
pr_info("attached USB submit fallback for device 368b:8d81 interface 0\n");
return 0;
}
static void __exit aic_zlp_quirk_exit(void)
{
unsigned long missed = 0;
if (active_hook == AIC_ZLP_HOOK_BTUSB_RETURN) {
unregister_kretprobe(&alloc_bulk_urb_probe);
missed = alloc_bulk_urb_probe.nmissed;
} else if (active_hook == AIC_ZLP_HOOK_USB_SUBMIT) {
unregister_kprobe(&usb_submit_urb_probe);
missed = usb_submit_urb_probe.nmissed;
}
pr_info("detached %s after %lld injections (%lu missed hits)\n",
hook_name, (long long)atomic64_read(&injection_count), missed);
}
#else
static int __init aic_zlp_quirk_init(void)
{
pr_err("CONFIG_KPROBES is disabled in this kernel\n");
return -EOPNOTSUPP;
}
static void __exit aic_zlp_quirk_exit(void)
{
}
#endif
module_init(aic_zlp_quirk_init);
module_exit(aic_zlp_quirk_exit);
MODULE_AUTHOR("Shen Mintao <cx330.shen@autocore.ai>");
MODULE_DESCRIPTION("AIC 8800D80 standard btusb ACL bulk TX ZLP quirk");
MODULE_LICENSE("GPL");
MODULE_VERSION("1.0");
MODULE_SOFTDEP("pre: btusb");
MODULE_ALIAS("usb:v368Bp8D81d*dc*dsc*dp*ic*isc*ip*in*");
+117
View File
@@ -0,0 +1,117 @@
# AIC POWERLIMIT 2025/0623/1700
# Max tx power reference: Linux wireless regulatory database for CRDA
# https://git.kernel.org/pub/scm/linux/kernel/git/sforshee/wireless-regdb.git/tree/db.txt
# If loss_value in aic_userconfig.txt is enabled, the power value in this document will be subtracted from loss_value in actual judgment
# Table 1:
## 2.4G, 20M,#6#
## START
## SRRC FCC ETSI JP KCC UNSET
CH01 16 14 14 16 16 15
CH02 16 14 14 16 16 16
CH03 16 14 14 16 16 16
CH04 16 14 14 16 16 16
CH05 16 14 14 16 16 16
CH06 16 14 14 16 16 16
CH07 16 14 14 16 16 16
CH08 16 14 14 16 16 16
CH09 16 14 14 16 16 16
CH10 16 14 14 16 16 16
CH11 16 14 14 16 16 16
CH12 15 14 14 16 16 12
CH13 13 14 14 16 16 12
CH14 NA NA NA 16 NA 12
## END
# Table 2:
## 2.4G, 40M,#6#
## START
## SRRC FCC ETSI JP KCC UNSET
CH01 NA NA NA NA NA NA
CH02 NA NA NA NA NA NA
CH03 16 13 14 16 16 16
CH04 16 13 14 16 16 16
CH05 16 13 14 16 16 16
CH06 16 13 14 16 16 16
CH07 16 13 14 16 16 16
CH08 16 13 14 16 16 16
CH09 16 11 14 16 16 16
CH10 16 11 14 16 16 16
CH11 16 11 14 16 16 16
CH12 NA NA NA NA NA NA
CH13 NA NA NA NA NA NA
CH14 NA NA NA NA NA NA
## END
# Table 3:
## 5G, 20M,#6#
## START
## SRRC FCC ETSI JP KCC UNSET
# 5G Band 1
CH36 15 16 16 16 16 15
CH40 15 16 16 16 16 15
CH44 15 16 16 16 16 15
CH48 15 16 16 16 16 15
# 5G Band 2
CH52 15 16 16 16 16 15
CH56 15 16 16 16 16 15
CH60 15 16 16 16 16 15
CH64 15 16 16 16 16 15
# 5G Band 3
CH100 NA 16 16 16 16 15
CH104 NA 16 16 16 16 15
CH108 NA 16 16 16 16 15
CH112 NA 16 16 16 16 15
CH116 NA 16 16 16 16 15
CH120 NA 16 16 16 16 15
CH124 NA 16 16 16 16 15
CH128 NA 16 16 16 16 15
CH132 NA 16 16 16 16 15
CH136 NA 16 16 16 16 15
CH140 NA 16 16 16 16 15
CH144 NA NA 16 16 16 15
# 5G Band 4
CH149 20 16 8 NA 20 11
CH153 20 16 8 NA 20 11
CH157 20 16 8 NA 20 11
CH161 20 16 8 NA 20 11
CH165 20 16 8 NA 20 11
## END
# Table 4:
## 5G, 40M,#6#
## START
## SRRC FCC ETSI JP KCC UNSET
# 5G Band 1
CH38 15 16 16 16 20 15
CH46 15 16 16 16 20 15
# 5G Band 2
CH54 15 16 16 16 20 15
CH62 15 16 16 16 20 15
# 5G Band 3
CH102 NA 16 16 16 20 15
CH110 NA 16 16 16 20 15
CH118 NA 16 16 16 20 15
CH126 NA 16 16 16 20 15
CH134 NA 16 16 16 20 15
CH142 NA 16 NA 16 20 15
# 5G Band 4
CH151 16 15 8 NA 18 11
CH159 17 16 8 NA 17 11
## END
# Table 5:
## 5G, 80M,#6#
## START
## SRRC FCC ETSI JP KCC UNSET
# 5G Band 1
CH42 15 16 16 16 20 15
# 5G Band 2
CH58 15 16 16 16 20 15
# 5G Band 3
CH106 NA 16 16 16 20 15
CH122 NA 16 16 16 20 15
CH138 NA 16 NA NA 20 15
# 5G Band 4
CH155 15 14 8 NA 16 11
## END
+16 -2
View File
@@ -67,9 +67,23 @@ lvl_11ax_mcs9_5g=13
lvl_11ax_mcs10_5g=12
lvl_11ax_mcs11_5g=12
# txpwr_lvl_adj
lvl_adj_enable=0
lvl_adj_2g4_chan_1_4=0
lvl_adj_2g4_chan_5_9=0
lvl_adj_2g4_chan_10_13=0
lvl_adj_5g_chan_42=0
lvl_adj_5g_chan_58=0
lvl_adj_5g_chan_106=0
lvl_adj_5g_chan_122=0
lvl_adj_5g_chan_138=0
lvl_adj_5g_chan_155=0
# txpwr_loss
loss_enable=0
loss_value=2
loss_enable_2g4=0
loss_value_2g4=2
loss_enable_5g=0
loss_value_5g=5
# txpwr_ofst
ofst_enable=0
@@ -0,0 +1,124 @@
# AIC USERCONFIG 2022/0803/1707
# txpwr_lvl
enable=1
lvl_11b_11ag_1m_2g4=20
lvl_11b_11ag_2m_2g4=20
lvl_11b_11ag_5m5_2g4=20
lvl_11b_11ag_11m_2g4=20
lvl_11b_11ag_6m_2g4=20
lvl_11b_11ag_9m_2g4=20
lvl_11b_11ag_12m_2g4=20
lvl_11b_11ag_18m_2g4=20
lvl_11b_11ag_24m_2g4=20
lvl_11b_11ag_36m_2g4=19
lvl_11b_11ag_48m_2g4=18
lvl_11b_11ag_54m_2g4=17
lvl_11n_11ac_mcs0_2g4=20
lvl_11n_11ac_mcs1_2g4=20
lvl_11n_11ac_mcs2_2g4=20
lvl_11n_11ac_mcs3_2g4=20
lvl_11n_11ac_mcs4_2g4=20
lvl_11n_11ac_mcs5_2g4=19
lvl_11n_11ac_mcs6_2g4=18
lvl_11n_11ac_mcs7_2g4=17
lvl_11n_11ac_mcs8_2g4=17
lvl_11n_11ac_mcs9_2g4=16
lvl_11ax_mcs0_2g4=20
lvl_11ax_mcs1_2g4=20
lvl_11ax_mcs2_2g4=20
lvl_11ax_mcs3_2g4=20
lvl_11ax_mcs4_2g4=20
lvl_11ax_mcs5_2g4=19
lvl_11ax_mcs6_2g4=18
lvl_11ax_mcs7_2g4=17
lvl_11ax_mcs8_2g4=17
lvl_11ax_mcs9_2g4=16
lvl_11ax_mcs10_2g4=15
lvl_11ax_mcs11_2g4=15
lvl_11a_6m_5g=19
lvl_11a_9m_5g=19
lvl_11a_12m_5g=19
lvl_11a_18m_5g=18
lvl_11a_24m_5g=18
lvl_11a_36m_5g=18
lvl_11a_48m_5g=18
lvl_11a_54m_5g=18
lvl_11n_11ac_mcs0_5g=19
lvl_11n_11ac_mcs1_5g=19
lvl_11n_11ac_mcs2_5g=19
lvl_11n_11ac_mcs3_5g=18
lvl_11n_11ac_mcs4_5g=18
lvl_11n_11ac_mcs5_5g=18
lvl_11n_11ac_mcs6_5g=18
lvl_11n_11ac_mcs7_5g=17
lvl_11n_11ac_mcs8_5g=15
lvl_11n_11ac_mcs9_5g=15
lvl_11ax_mcs0_5g=19
lvl_11ax_mcs1_5g=19
lvl_11ax_mcs2_5g=19
lvl_11ax_mcs3_5g=18
lvl_11ax_mcs4_5g=18
lvl_11ax_mcs5_5g=18
lvl_11ax_mcs6_5g=18
lvl_11ax_mcs7_5g=17
lvl_11ax_mcs8_5g=15
lvl_11ax_mcs9_5g=15
lvl_11ax_mcs10_5g=13
lvl_11ax_mcs11_5g=13
# txpwr_lvl_adj
lvl_adj_enable=0
lvl_adj_2g4_chan_1_4=0
lvl_adj_2g4_chan_5_9=0
lvl_adj_2g4_chan_10_13=0
lvl_adj_5g_chan_42=0
lvl_adj_5g_chan_58=0
lvl_adj_5g_chan_106=0
lvl_adj_5g_chan_122=0
lvl_adj_5g_chan_138=0
lvl_adj_5g_chan_155=0
# txpwr_loss
loss_enable_2g4=0
loss_value_2g4=2
loss_enable_5g=0
loss_value_5g=5
# txpwr_ofst
ofst_enable=0
ofst_2g4_11b_chan_1_4=0
ofst_2g4_11b_chan_5_9=0
ofst_2g4_11b_chan_10_13=0
ofst_2g4_ofdm_highrate_chan_1_4=0
ofst_2g4_ofdm_highrate_chan_5_9=0
ofst_2g4_ofdm_highrate_chan_10_13=0
ofst_2g4_ofdm_lowrate_chan_1_4=0
ofst_2g4_ofdm_lowrate_chan_5_9=0
ofst_2g4_ofdm_lowrate_chan_10_13=0
ofst_5g_ofdm_lowrate_chan_42=0
ofst_5g_ofdm_lowrate_chan_58=0
ofst_5g_ofdm_lowrate_chan_106=0
ofst_5g_ofdm_lowrate_chan_122=0
ofst_5g_ofdm_lowrate_chan_138=0
ofst_5g_ofdm_lowrate_chan_155=0
ofst_5g_ofdm_highrate_chan_42=0
ofst_5g_ofdm_highrate_chan_58=0
ofst_5g_ofdm_highrate_chan_106=0
ofst_5g_ofdm_highrate_chan_122=0
ofst_5g_ofdm_highrate_chan_138=0
ofst_5g_ofdm_highrate_chan_155=0
ofst_5g_ofdm_midrate_chan_42=0
ofst_5g_ofdm_midrate_chan_58=0
ofst_5g_ofdm_midrate_chan_106=0
ofst_5g_ofdm_midrate_chan_122=0
ofst_5g_ofdm_midrate_chan_138=0
ofst_5g_ofdm_midrate_chan_155=0
# xtal cap
xtal_enable=0
xtal_cap=24
xtal_cap_fine=31
@@ -0,0 +1,124 @@
# AIC USERCONFIG 2022/0803/1707
# txpwr_lvl
enable=1
lvl_11b_11ag_1m_2g4=18
lvl_11b_11ag_2m_2g4=18
lvl_11b_11ag_5m5_2g4=18
lvl_11b_11ag_11m_2g4=18
lvl_11b_11ag_6m_2g4=18
lvl_11b_11ag_9m_2g4=18
lvl_11b_11ag_12m_2g4=18
lvl_11b_11ag_18m_2g4=18
lvl_11b_11ag_24m_2g4=18
lvl_11b_11ag_36m_2g4=18
lvl_11b_11ag_48m_2g4=18
lvl_11b_11ag_54m_2g4=17
lvl_11n_11ac_mcs0_2g4=20
lvl_11n_11ac_mcs1_2g4=20
lvl_11n_11ac_mcs2_2g4=20
lvl_11n_11ac_mcs3_2g4=20
lvl_11n_11ac_mcs4_2g4=20
lvl_11n_11ac_mcs5_2g4=19
lvl_11n_11ac_mcs6_2g4=18
lvl_11n_11ac_mcs7_2g4=18
lvl_11n_11ac_mcs8_2g4=17
lvl_11n_11ac_mcs9_2g4=16
lvl_11ax_mcs0_2g4=20
lvl_11ax_mcs1_2g4=20
lvl_11ax_mcs2_2g4=20
lvl_11ax_mcs3_2g4=20
lvl_11ax_mcs4_2g4=20
lvl_11ax_mcs5_2g4=19
lvl_11ax_mcs6_2g4=18
lvl_11ax_mcs7_2g4=18
lvl_11ax_mcs8_2g4=17
lvl_11ax_mcs9_2g4=17
lvl_11ax_mcs10_2g4=16
lvl_11ax_mcs11_2g4=16
lvl_11a_6m_5g=18
lvl_11a_9m_5g=18
lvl_11a_12m_5g=18
lvl_11a_18m_5g=18
lvl_11a_24m_5g=18
lvl_11a_36m_5g=18
lvl_11a_48m_5g=18
lvl_11a_54m_5g=18
lvl_11n_11ac_mcs0_5g=20
lvl_11n_11ac_mcs1_5g=19
lvl_11n_11ac_mcs2_5g=19
lvl_11n_11ac_mcs3_5g=18
lvl_11n_11ac_mcs4_5g=18
lvl_11n_11ac_mcs5_5g=18
lvl_11n_11ac_mcs6_5g=18
lvl_11n_11ac_mcs7_5g=17
lvl_11n_11ac_mcs8_5g=16
lvl_11n_11ac_mcs9_5g=16
lvl_11ax_mcs0_5g=20
lvl_11ax_mcs1_5g=19
lvl_11ax_mcs2_5g=19
lvl_11ax_mcs3_5g=18
lvl_11ax_mcs4_5g=18
lvl_11ax_mcs5_5g=18
lvl_11ax_mcs6_5g=18
lvl_11ax_mcs7_5g=17
lvl_11ax_mcs8_5g=16
lvl_11ax_mcs9_5g=16
lvl_11ax_mcs10_5g=15
lvl_11ax_mcs11_5g=15
# txpwr_lvl_adj
lvl_adj_enable=0
lvl_adj_2g4_chan_1_4=0
lvl_adj_2g4_chan_5_9=0
lvl_adj_2g4_chan_10_13=0
lvl_adj_5g_chan_42=0
lvl_adj_5g_chan_58=0
lvl_adj_5g_chan_106=0
lvl_adj_5g_chan_122=0
lvl_adj_5g_chan_138=0
lvl_adj_5g_chan_155=0
# txpwr_loss
loss_enable_2g4=0
loss_value_2g4=2
loss_enable_5g=0
loss_value_5g=5
# txpwr_ofst
ofst_enable=0
ofst_2g4_11b_chan_1_4=0
ofst_2g4_11b_chan_5_9=0
ofst_2g4_11b_chan_10_13=0
ofst_2g4_ofdm_highrate_chan_1_4=0
ofst_2g4_ofdm_highrate_chan_5_9=0
ofst_2g4_ofdm_highrate_chan_10_13=0
ofst_2g4_ofdm_lowrate_chan_1_4=0
ofst_2g4_ofdm_lowrate_chan_5_9=0
ofst_2g4_ofdm_lowrate_chan_10_13=0
ofst_5g_ofdm_lowrate_chan_42=0
ofst_5g_ofdm_lowrate_chan_58=0
ofst_5g_ofdm_lowrate_chan_106=0
ofst_5g_ofdm_lowrate_chan_122=0
ofst_5g_ofdm_lowrate_chan_138=0
ofst_5g_ofdm_lowrate_chan_155=0
ofst_5g_ofdm_highrate_chan_42=0
ofst_5g_ofdm_highrate_chan_58=0
ofst_5g_ofdm_highrate_chan_106=0
ofst_5g_ofdm_highrate_chan_122=0
ofst_5g_ofdm_highrate_chan_138=0
ofst_5g_ofdm_highrate_chan_155=0
ofst_5g_ofdm_midrate_chan_42=0
ofst_5g_ofdm_midrate_chan_58=0
ofst_5g_ofdm_midrate_chan_106=0
ofst_5g_ofdm_midrate_chan_122=0
ofst_5g_ofdm_midrate_chan_138=0
ofst_5g_ofdm_midrate_chan_155=0
# xtal cap
xtal_enable=0
xtal_cap=24
xtal_cap_fine=31
@@ -0,0 +1,124 @@
# AIC USERCONFIG 2022/0803/1707
# txpwr_lvl
enable=1
lvl_11b_11ag_1m_2g4=20
lvl_11b_11ag_2m_2g4=20
lvl_11b_11ag_5m5_2g4=20
lvl_11b_11ag_11m_2g4=20
lvl_11b_11ag_6m_2g4=20
lvl_11b_11ag_9m_2g4=20
lvl_11b_11ag_12m_2g4=20
lvl_11b_11ag_18m_2g4=20
lvl_11b_11ag_24m_2g4=20
lvl_11b_11ag_36m_2g4=19
lvl_11b_11ag_48m_2g4=18
lvl_11b_11ag_54m_2g4=17
lvl_11n_11ac_mcs0_2g4=20
lvl_11n_11ac_mcs1_2g4=20
lvl_11n_11ac_mcs2_2g4=20
lvl_11n_11ac_mcs3_2g4=20
lvl_11n_11ac_mcs4_2g4=20
lvl_11n_11ac_mcs5_2g4=19
lvl_11n_11ac_mcs6_2g4=18
lvl_11n_11ac_mcs7_2g4=17
lvl_11n_11ac_mcs8_2g4=17
lvl_11n_11ac_mcs9_2g4=16
lvl_11ax_mcs0_2g4=20
lvl_11ax_mcs1_2g4=20
lvl_11ax_mcs2_2g4=20
lvl_11ax_mcs3_2g4=20
lvl_11ax_mcs4_2g4=20
lvl_11ax_mcs5_2g4=19
lvl_11ax_mcs6_2g4=18
lvl_11ax_mcs7_2g4=17
lvl_11ax_mcs8_2g4=17
lvl_11ax_mcs9_2g4=16
lvl_11ax_mcs10_2g4=15
lvl_11ax_mcs11_2g4=15
lvl_11a_6m_5g=19
lvl_11a_9m_5g=19
lvl_11a_12m_5g=19
lvl_11a_18m_5g=18
lvl_11a_24m_5g=18
lvl_11a_36m_5g=18
lvl_11a_48m_5g=18
lvl_11a_54m_5g=18
lvl_11n_11ac_mcs0_5g=19
lvl_11n_11ac_mcs1_5g=19
lvl_11n_11ac_mcs2_5g=19
lvl_11n_11ac_mcs3_5g=18
lvl_11n_11ac_mcs4_5g=18
lvl_11n_11ac_mcs5_5g=18
lvl_11n_11ac_mcs6_5g=18
lvl_11n_11ac_mcs7_5g=17
lvl_11n_11ac_mcs8_5g=15
lvl_11n_11ac_mcs9_5g=15
lvl_11ax_mcs0_5g=19
lvl_11ax_mcs1_5g=19
lvl_11ax_mcs2_5g=19
lvl_11ax_mcs3_5g=18
lvl_11ax_mcs4_5g=18
lvl_11ax_mcs5_5g=18
lvl_11ax_mcs6_5g=18
lvl_11ax_mcs7_5g=17
lvl_11ax_mcs8_5g=15
lvl_11ax_mcs9_5g=15
lvl_11ax_mcs10_5g=14
lvl_11ax_mcs11_5g=14
# txpwr_lvl_adj
lvl_adj_enable=0
lvl_adj_2g4_chan_1_4=0
lvl_adj_2g4_chan_5_9=0
lvl_adj_2g4_chan_10_13=0
lvl_adj_5g_chan_42=0
lvl_adj_5g_chan_58=0
lvl_adj_5g_chan_106=0
lvl_adj_5g_chan_122=0
lvl_adj_5g_chan_138=0
lvl_adj_5g_chan_155=0
# txpwr_loss
loss_enable_2g4=0
loss_value_2g4=2
loss_enable_5g=0
loss_value_5g=5
# txpwr_ofst
ofst_enable=0
ofst_2g4_11b_chan_1_4=0
ofst_2g4_11b_chan_5_9=0
ofst_2g4_11b_chan_10_13=0
ofst_2g4_ofdm_highrate_chan_1_4=0
ofst_2g4_ofdm_highrate_chan_5_9=0
ofst_2g4_ofdm_highrate_chan_10_13=0
ofst_2g4_ofdm_lowrate_chan_1_4=0
ofst_2g4_ofdm_lowrate_chan_5_9=0
ofst_2g4_ofdm_lowrate_chan_10_13=0
ofst_5g_ofdm_lowrate_chan_42=0
ofst_5g_ofdm_lowrate_chan_58=0
ofst_5g_ofdm_lowrate_chan_106=0
ofst_5g_ofdm_lowrate_chan_122=0
ofst_5g_ofdm_lowrate_chan_138=0
ofst_5g_ofdm_lowrate_chan_155=0
ofst_5g_ofdm_highrate_chan_42=0
ofst_5g_ofdm_highrate_chan_58=0
ofst_5g_ofdm_highrate_chan_106=0
ofst_5g_ofdm_highrate_chan_122=0
ofst_5g_ofdm_highrate_chan_138=0
ofst_5g_ofdm_highrate_chan_155=0
ofst_5g_ofdm_midrate_chan_42=0
ofst_5g_ofdm_midrate_chan_58=0
ofst_5g_ofdm_midrate_chan_106=0
ofst_5g_ofdm_midrate_chan_122=0
ofst_5g_ofdm_midrate_chan_138=0
ofst_5g_ofdm_midrate_chan_155=0
# xtal cap
xtal_enable=0
xtal_cap=24
xtal_cap_fine=31
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+83 -83
View File
@@ -1,117 +1,117 @@
# AIC POWERLIMIT 2024/1108/1900
# AIC POWERLIMIT 2025/0623/1700
# Max tx power reference: Linux wireless regulatory database for CRDA
# https://git.kernel.org/pub/scm/linux/kernel/git/sforshee/wireless-regdb.git/tree/db.txt
# If loss_value in aic_userconfig_8800d80.txt is enabled, the power value in this document will be subtracted from loss_value in actual judgment
# If loss_value in aic_userconfig.txt is enabled, the power value in this document will be subtracted from loss_value in actual judgment
# Table 1:
## 2.4G, 20M,#5#
## 2.4G, 20M,#6#
## START
## SRRC FCC ETSI JP UNSET
CH01 15 15 15 15 15
CH02 16 16 16 16 16
CH03 16 16 16 16 16
CH04 16 16 16 16 16
CH05 16 16 16 16 16
CH06 16 16 16 16 16
CH07 16 16 16 16 16
CH08 16 16 16 16 16
CH09 16 16 16 16 16
CH10 16 16 16 16 16
CH11 16 16 16 16 16
CH12 12 12 12 12 12
CH13 12 12 12 12 12
CH14 NA NA NA 12 12
## SRRC FCC ETSI JP KCC UNSET
CH01 16 14 14 16 16 15
CH02 16 14 14 16 16 16
CH03 16 14 14 16 16 16
CH04 16 14 14 16 16 16
CH05 16 14 14 16 16 16
CH06 16 14 14 16 16 16
CH07 16 14 14 16 16 16
CH08 16 14 14 16 16 16
CH09 16 14 14 16 16 16
CH10 16 14 14 16 16 16
CH11 16 14 14 16 16 16
CH12 15 14 14 16 16 12
CH13 13 14 14 16 16 12
CH14 NA NA NA 16 NA 12
## END
# Table 2:
## 2.4G, 40M,#5#
## 2.4G, 40M,#6#
## START
## SRRC FCC ETSI JP UNSET
CH01 NA NA NA NA NA
CH02 NA NA NA NA NA
CH03 16 16 16 16 16
CH04 16 16 16 16 16
CH05 16 16 16 16 16
CH06 16 16 16 16 16
CH07 16 16 16 16 16
CH08 16 16 16 16 16
CH09 16 16 16 16 16
CH10 16 16 16 16 16
CH11 16 16 16 16 16
CH12 NA NA NA NA NA
CH13 NA NA NA NA NA
CH14 NA NA NA NA NA
## SRRC FCC ETSI JP KCC UNSET
CH01 NA NA NA NA NA NA
CH02 NA NA NA NA NA NA
CH03 16 13 14 16 16 16
CH04 16 13 14 16 16 16
CH05 16 13 14 16 16 16
CH06 16 13 14 16 16 16
CH07 16 13 14 16 16 16
CH08 16 13 14 16 16 16
CH09 16 11 14 16 16 16
CH10 16 11 14 16 16 16
CH11 16 11 14 16 16 16
CH12 NA NA NA NA NA NA
CH13 NA NA NA NA NA NA
CH14 NA NA NA NA NA NA
## END
# Table 3:
## 5G, 20M,#5#
## 5G, 20M,#6#
## START
## SRRC FCC ETSI JP UNSET
## SRRC FCC ETSI JP KCC UNSET
# 5G Band 1
CH36 15 16 16 16 15
CH40 15 16 16 16 15
CH44 15 16 16 16 15
CH48 15 16 16 16 15
CH36 15 16 16 16 16 15
CH40 15 16 16 16 16 15
CH44 15 16 16 16 16 15
CH48 15 16 16 16 16 15
# 5G Band 2
CH52 15 16 16 16 15
CH56 15 16 16 16 15
CH60 15 16 16 16 15
CH64 15 16 16 16 15
CH52 15 16 16 16 16 15
CH56 15 16 16 16 16 15
CH60 15 16 16 16 16 15
CH64 15 16 16 16 16 15
# 5G Band 3
CH100 NA 16 16 16 15
CH104 NA 16 16 16 15
CH108 NA 16 16 16 15
CH112 NA 16 16 16 15
CH116 NA 16 16 16 15
CH120 NA 16 16 16 15
CH124 NA 16 16 16 15
CH128 NA 16 16 16 15
CH132 NA 16 16 16 15
CH136 NA 16 16 16 15
CH140 NA 16 16 16 15
CH144 NA NA 16 16 15
CH100 NA 16 16 16 16 15
CH104 NA 16 16 16 16 15
CH108 NA 16 16 16 16 15
CH112 NA 16 16 16 16 15
CH116 NA 16 16 16 16 15
CH120 NA 16 16 16 16 15
CH124 NA 16 16 16 16 15
CH128 NA 16 16 16 16 15
CH132 NA 16 16 16 16 15
CH136 NA 16 16 16 16 15
CH140 NA 16 16 16 16 15
CH144 NA NA 16 16 16 15
# 5G Band 4
CH149 16 16 11 NA 11
CH153 16 16 11 NA 11
CH157 16 16 11 NA 11
CH161 16 16 11 NA 11
CH165 16 16 11 NA 11
CH149 20 16 8 NA 20 11
CH153 20 16 8 NA 20 11
CH157 20 16 8 NA 20 11
CH161 20 16 8 NA 20 11
CH165 20 16 8 NA 20 11
## END
# Table 4:
## 5G, 40M,#5#
## 5G, 40M,#6#
## START
## SRRC FCC ETSI JP UNSET
## SRRC FCC ETSI JP KCC UNSET
# 5G Band 1
CH38 15 16 16 16 15
CH46 15 16 16 16 15
CH38 15 16 16 16 20 15
CH46 15 16 16 16 20 15
# 5G Band 2
CH54 15 16 16 16 15
CH62 15 16 16 16 15
CH54 15 16 16 16 20 15
CH62 15 16 16 16 20 15
# 5G Band 3
CH102 NA 16 16 16 15
CH110 NA 16 16 16 15
CH118 NA 16 16 16 15
CH126 NA 16 16 16 15
CH134 NA 16 16 16 15
CH142 NA 16 NA 16 15
CH102 NA 16 16 16 20 15
CH110 NA 16 16 16 20 15
CH118 NA 16 16 16 20 15
CH126 NA 16 16 16 20 15
CH134 NA 16 16 16 20 15
CH142 NA 16 NA 16 20 15
# 5G Band 4
CH151 16 16 11 NA 11
CH159 16 16 11 NA 11
CH151 16 15 8 NA 18 11
CH159 17 16 8 NA 17 11
## END
# Table 5:
## 5G, 80M,#5#
## 5G, 80M,#6#
## START
## SRRC FCC ETSI JP UNSET
## SRRC FCC ETSI JP KCC UNSET
# 5G Band 1
CH42 15 16 16 16 15
CH42 15 16 16 16 20 15
# 5G Band 2
CH58 15 16 16 16 15
CH58 15 16 16 16 20 15
# 5G Band 3
CH106 NA 16 16 16 15
CH122 NA 16 16 16 15
CH138 NA 16 NA NA 15
CH106 NA 16 16 16 20 15
CH122 NA 16 16 16 20 15
CH138 NA 16 NA NA 20 15
# 5G Band 4
CH155 16 16 11 NA 11
CH155 15 14 8 NA 16 11
## END
+83 -83
View File
@@ -1,117 +1,117 @@
# AIC POWERLIMIT 2024/1108/1900
# AIC POWERLIMIT 2025/0623/1700
# Max tx power reference: Linux wireless regulatory database for CRDA
# https://git.kernel.org/pub/scm/linux/kernel/git/sforshee/wireless-regdb.git/tree/db.txt
# If loss_value in aic_userconfig_8800d80.txt is enabled, the power value in this document will be subtracted from loss_value in actual judgment
# If loss_value in aic_userconfig.txt is enabled, the power value in this document will be subtracted from loss_value in actual judgment
# Table 1:
## 2.4G, 20M,#5#
## 2.4G, 20M,#6#
## START
## SRRC FCC ETSI JP UNSET
CH01 15 15 15 15 15
CH02 16 16 16 16 16
CH03 16 16 16 16 16
CH04 16 16 16 16 16
CH05 16 16 16 16 16
CH06 16 16 16 16 16
CH07 16 16 16 16 16
CH08 16 16 16 16 16
CH09 16 16 16 16 16
CH10 16 16 16 16 16
CH11 16 16 16 16 16
CH12 12 12 12 12 12
CH13 12 12 12 12 12
CH14 NA NA NA 12 12
## SRRC FCC ETSI JP KCC UNSET
CH01 16 14 14 16 16 15
CH02 16 14 14 16 16 16
CH03 16 14 14 16 16 16
CH04 16 14 14 16 16 16
CH05 16 14 14 16 16 16
CH06 16 14 14 16 16 16
CH07 16 14 14 16 16 16
CH08 16 14 14 16 16 16
CH09 16 14 14 16 16 16
CH10 16 14 14 16 16 16
CH11 16 14 14 16 16 16
CH12 15 14 14 16 16 12
CH13 13 14 14 16 16 12
CH14 NA NA NA 16 NA 12
## END
# Table 2:
## 2.4G, 40M,#5#
## 2.4G, 40M,#6#
## START
## SRRC FCC ETSI JP UNSET
CH01 NA NA NA NA NA
CH02 NA NA NA NA NA
CH03 16 16 16 16 16
CH04 16 16 16 16 16
CH05 16 16 16 16 16
CH06 16 16 16 16 16
CH07 16 16 16 16 16
CH08 16 16 16 16 16
CH09 16 16 16 16 16
CH10 16 16 16 16 16
CH11 16 16 16 16 16
CH12 NA NA NA NA NA
CH13 NA NA NA NA NA
CH14 NA NA NA NA NA
## SRRC FCC ETSI JP KCC UNSET
CH01 NA NA NA NA NA NA
CH02 NA NA NA NA NA NA
CH03 16 13 14 16 16 16
CH04 16 13 14 16 16 16
CH05 16 13 14 16 16 16
CH06 16 13 14 16 16 16
CH07 16 13 14 16 16 16
CH08 16 13 14 16 16 16
CH09 16 11 14 16 16 16
CH10 16 11 14 16 16 16
CH11 16 11 14 16 16 16
CH12 NA NA NA NA NA NA
CH13 NA NA NA NA NA NA
CH14 NA NA NA NA NA NA
## END
# Table 3:
## 5G, 20M,#5#
## 5G, 20M,#6#
## START
## SRRC FCC ETSI JP UNSET
## SRRC FCC ETSI JP KCC UNSET
# 5G Band 1
CH36 15 16 16 16 15
CH40 15 16 16 16 15
CH44 15 16 16 16 15
CH48 15 16 16 16 15
CH36 15 16 16 16 16 15
CH40 15 16 16 16 16 15
CH44 15 16 16 16 16 15
CH48 15 16 16 16 16 15
# 5G Band 2
CH52 15 16 16 16 15
CH56 15 16 16 16 15
CH60 15 16 16 16 15
CH64 15 16 16 16 15
CH52 15 16 16 16 16 15
CH56 15 16 16 16 16 15
CH60 15 16 16 16 16 15
CH64 15 16 16 16 16 15
# 5G Band 3
CH100 NA 16 16 16 15
CH104 NA 16 16 16 15
CH108 NA 16 16 16 15
CH112 NA 16 16 16 15
CH116 NA 16 16 16 15
CH120 NA 16 16 16 15
CH124 NA 16 16 16 15
CH128 NA 16 16 16 15
CH132 NA 16 16 16 15
CH136 NA 16 16 16 15
CH140 NA 16 16 16 15
CH144 NA NA 16 16 15
CH100 NA 16 16 16 16 15
CH104 NA 16 16 16 16 15
CH108 NA 16 16 16 16 15
CH112 NA 16 16 16 16 15
CH116 NA 16 16 16 16 15
CH120 NA 16 16 16 16 15
CH124 NA 16 16 16 16 15
CH128 NA 16 16 16 16 15
CH132 NA 16 16 16 16 15
CH136 NA 16 16 16 16 15
CH140 NA 16 16 16 16 15
CH144 NA NA 16 16 16 15
# 5G Band 4
CH149 16 16 11 NA 11
CH153 16 16 11 NA 11
CH157 16 16 11 NA 11
CH161 16 16 11 NA 11
CH165 16 16 11 NA 11
CH149 20 16 8 NA 20 11
CH153 20 16 8 NA 20 11
CH157 20 16 8 NA 20 11
CH161 20 16 8 NA 20 11
CH165 20 16 8 NA 20 11
## END
# Table 4:
## 5G, 40M,#5#
## 5G, 40M,#6#
## START
## SRRC FCC ETSI JP UNSET
## SRRC FCC ETSI JP KCC UNSET
# 5G Band 1
CH38 15 16 16 16 15
CH46 15 16 16 16 15
CH38 15 16 16 16 20 15
CH46 15 16 16 16 20 15
# 5G Band 2
CH54 15 16 16 16 15
CH62 15 16 16 16 15
CH54 15 16 16 16 20 15
CH62 15 16 16 16 20 15
# 5G Band 3
CH102 NA 16 16 16 15
CH110 NA 16 16 16 15
CH118 NA 16 16 16 15
CH126 NA 16 16 16 15
CH134 NA 16 16 16 15
CH142 NA 16 NA 16 15
CH102 NA 16 16 16 20 15
CH110 NA 16 16 16 20 15
CH118 NA 16 16 16 20 15
CH126 NA 16 16 16 20 15
CH134 NA 16 16 16 20 15
CH142 NA 16 NA 16 20 15
# 5G Band 4
CH151 16 16 11 NA 11
CH159 16 16 11 NA 11
CH151 16 15 8 NA 18 11
CH159 17 16 8 NA 17 11
## END
# Table 5:
## 5G, 80M,#5#
## 5G, 80M,#6#
## START
## SRRC FCC ETSI JP UNSET
## SRRC FCC ETSI JP KCC UNSET
# 5G Band 1
CH42 15 16 16 16 15
CH42 15 16 16 16 20 15
# 5G Band 2
CH58 15 16 16 16 15
CH58 15 16 16 16 20 15
# 5G Band 3
CH106 NA 16 16 16 15
CH122 NA 16 16 16 15
CH138 NA 16 NA NA 15
CH106 NA 16 16 16 20 15
CH122 NA 16 16 16 20 15
CH138 NA 16 NA NA 20 15
# 5G Band 4
CH155 16 16 11 NA 11
CH155 15 14 8 NA 16 11
## END
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+47 -94
View File
@@ -326,7 +326,6 @@ check_kernel_build_tree() {
cleanup_legacy_bluetooth_config() {
local legacy_conf="/etc/modprobe.d/aic8800-bt.conf"
local legacy_udev="/etc/udev/rules.d/90-aic8800-mode-switch.rules"
local legacy_package
local changed=false
if [ -f "$legacy_conf" ] && grep -Eq '^[[:space:]]*(softdep|alias)[^#]*aic_btusb([[:space:]]|$)' "$legacy_conf"; then
@@ -359,21 +358,6 @@ cleanup_legacy_bluetooth_config() {
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
print_success "Legacy Bluetooth configuration cleaned up."
fi
@@ -409,7 +393,12 @@ install_firmware() {
fi
done
print_success "Firmware installed for all supported chip variants."
print_success "Firmware installed for all chip variants:"
print_info " - aic8800D80 (standard)"
print_info " - aic8800D80N (N variant)"
print_info " - aic8800D80X2 (X2 variant)"
print_info " - aic8800DC/DW (DC/DW series)"
print_info " - aic8800DLN (DLN variant)"
# Install udev rules
local rules_source="${SCRIPT_DIR}/aic.rules"
@@ -426,7 +415,7 @@ install_firmware() {
print_warning "Udev rules file not found: $rules_source"
fi
# Install usb_modeswitch configuration for AIC8800D80 "Pandora" clone
# Install usb_modeswitch configuration
local modeswitch_source="${SCRIPT_DIR}/usb_modeswitch/1111_1111"
local modeswitch_dest="/etc/usb_modeswitch.d/1111:1111"
@@ -476,11 +465,6 @@ BUILT_MODULE_NAME[1]="aic_load_fw"
BUILT_MODULE_LOCATION[1]="drivers/aic8800/aic_load_fw"
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"
EOF
@@ -590,20 +574,6 @@ refresh_initramfs() {
# 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() {
print_step "Loading kernel modules..."
@@ -612,16 +582,14 @@ load_module() {
depmod -a >> "$LOG_FILE" 2>&1
if lsmod | grep -q "$MODULE_NAME"; then
print_info "Wi-Fi module already loaded. Reloading..."
print_info "WiFi module already loaded. Reloading..."
modprobe -r "$MODULE_NAME" >> "$LOG_FILE" 2>&1 || true
fi
# aic8800_fdrv depends on aic_load_fw, which initializes both Wi-Fi-only
# adapters and the Bluetooth firmware on combo adapters. If a standard HCI
# USB interface appears afterwards, the kernel USB modalias loads btusb.
# Load the WiFi module
print_info "Loading $MODULE_NAME..."
if modprobe "$MODULE_NAME" >> "$LOG_FILE" 2>&1; then
print_success "Wi-Fi module loaded successfully."
print_success "WiFi module loaded successfully."
# Verify module is loaded
print_info "Waiting for module to initialize..."
@@ -635,29 +603,24 @@ load_module() {
done
if [ "$module_loaded" = true ]; then
print_success "Wi-Fi module is active in kernel."
print_success "WiFi module is active in kernel."
else
print_warning "Wi-Fi module may not be fully initialized yet."
print_warning "WiFi module may not be fully initialized yet."
fi
else
print_warning "Wi-Fi module installed but could not be loaded immediately."
print_warning "WiFi module installed but could not be loaded immediately."
print_info "This may be due to Secure Boot or missing hardware."
print_info "Try rebooting or check: sudo dmesg | grep aic8800"
fi
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
# Load the standard Bluetooth driver (btusb)
# The aic_load_fw module uploads the Bluetooth firmware, then btusb handles the BT interface
print_info "Loading standard Bluetooth driver (btusb)..."
if modprobe btusb >> "$LOG_FILE" 2>&1; then
print_success "Bluetooth driver (btusb) loaded successfully."
else
print_warning "Could not load btusb driver automatically."
print_info "You can manually load it with: sudo modprobe btusb"
fi
}
@@ -678,33 +641,21 @@ verify_installation() {
print_warning "DKMS status unclear: $dkms_status"
fi
# Check if the Wi-Fi module is loaded
# Check if WiFi module is loaded
if lsmod | grep -q "$MODULE_NAME"; then
print_success "Wi-Fi kernel module is loaded."
print_success "WiFi kernel module is loaded."
else
print_info "Wi-Fi module not currently loaded (this is OK if no hardware is connected)."
print_info "WiFi module not currently loaded (this is OK if no hardware is connected)."
fi
if lsmod | awk '{print $1}' | grep -qx 'btusb' || compgen -G '/sys/class/bluetooth/hci*' > /dev/null; then
print_success "A Bluetooth controller or the standard btusb module is present."
# Check if Bluetooth is available via standard btusb
if lsmod | grep -q "btusb"; then
print_success "Bluetooth kernel module (btusb) is loaded."
else
print_info "No Bluetooth controller is present (normal for Wi-Fi-only adapters or when no combo adapter is connected)."
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)."
print_info "Bluetooth module (btusb) not currently loaded (this is OK if no hardware is connected)."
fi
# Show all loaded AIC modules
echo ""
print_info "Loaded AIC modules:"
lsmod | grep aic || echo " (none)"
@@ -728,13 +679,14 @@ verify_installation() {
iwconfig 2>/dev/null | grep -E "wlan|IEEE" || echo "No wireless interfaces detected (hardware may not be connected)"
fi
print_info "Checking for Bluetooth interfaces on combo adapters..."
if command -v bluetoothctl &> /dev/null; then
bluetoothctl list 2>/dev/null || echo "No Bluetooth interfaces detected (normal for Wi-Fi-only adapters)"
elif command -v hciconfig &> /dev/null; then
hciconfig 2>/dev/null || echo "No Bluetooth interfaces detected (normal for Wi-Fi-only adapters)"
# Check for Bluetooth interfaces
print_info "Checking for Bluetooth interfaces..."
if command -v hciconfig &> /dev/null; then
hciconfig 2>/dev/null || echo "No Bluetooth interfaces detected (hardware may not be connected)"
elif command -v bluetoothctl &> /dev/null; then
bluetoothctl list 2>/dev/null || echo "No Bluetooth interfaces detected (hardware may not be connected)"
else
echo "Bluetooth tools not installed (install BlueZ to manage a combo adapter)"
echo "Bluetooth tools not installed (install bluez package for Bluetooth support)"
fi
}
@@ -750,15 +702,14 @@ show_final_instructions() {
echo ""
echo -e "${CYAN}Important Information:${NC}"
echo ""
echo "✓ Wi-Fi driver and firmware loader installed via DKMS"
echo "✓ Combo adapters use the standard Linux btusb driver"
echo "✓ Device-scoped Bluetooth ACL ZLP quirk installed for 368b:8d81"
echo "✓ WiFi driver installed via DKMS"
echo "✓ Bluetooth supported via standard btusb driver (after firmware upload)"
echo "✓ Automatic rebuild enabled for kernel updates"
echo "✓ Firmware installed in /lib/firmware/"
echo ""
echo -e "${CYAN}Next Steps:${NC}"
echo ""
echo "1. Connect your AIC8800 USB Wi-Fi or Wi-Fi/Bluetooth adapter"
echo "1. Connect your AIC8800D80 USB WiFi/Bluetooth adapter"
echo ""
echo "2. Check if the adapter is detected:"
echo " ${BLUE}lsusb | grep -i aic${NC}"
@@ -767,14 +718,14 @@ show_final_instructions() {
echo ""
echo "3. View kernel messages about the driver:"
echo " ${BLUE}sudo dmesg | grep aic8800${NC}"
echo " ${BLUE}sudo dmesg | grep -iE 'bluetooth|btusb|hci'${NC}"
echo " ${BLUE}sudo dmesg | grep btusb${NC}"
echo ""
echo "4. Connect to a WiFi network:"
echo " ${BLUE}nmcli device wifi list${NC}"
echo " ${BLUE}nmcli device wifi connect \"SSID\" password \"PASSWORD\"${NC}"
echo ""
echo "5. For a combo adapter, check Bluetooth:"
echo " ${BLUE}bluetoothctl list${NC}"
echo "5. Check Bluetooth status:"
echo " ${BLUE}bluetoothctl show${NC}"
echo " ${BLUE}bluetoothctl scan on${NC}"
echo ""
echo -e "${CYAN}Troubleshooting:${NC}"
@@ -783,12 +734,14 @@ show_final_instructions() {
echo " ${BLUE}dkms status${NC}"
echo ""
echo "• Check loaded modules:"
echo " ${BLUE}lsmod | grep -E 'aic|btusb'${NC}"
echo " ${BLUE}cat /sys/module/aic_zlp_quirk/parameters/{hook,injections}${NC}"
echo " ${BLUE}lsmod | grep aic${NC}"
echo ""
echo "• Manually load the Wi-Fi module and firmware loader:"
echo "• Manually load the WiFi module:"
echo " ${BLUE}sudo modprobe aic8800_fdrv${NC}"
echo ""
echo "• Manually load the Bluetooth module:"
echo " ${BLUE}sudo modprobe btusb${NC}"
echo ""
echo "• View detailed logs:"
echo " ${BLUE}cat $LOG_FILE${NC}"
echo ""
-121
View File
@@ -1,121 +0,0 @@
# AIC8800D80 legacy MCU revision 1 support
The `legacy-mcu1` branch is the maintained compatibility profile for the older
AIC8800D80 MCU revision tracked in
[issue #58](https://github.com/shenmintao/aic8800d80/issues/58), with related
reports in issues #14, #64, and #65. It is intended only for devices that log:
```text
chip_id=7, chip_mcu_id=1
```
Affected adapters have been observed entering through `a69c:572f` or a similar
mass-storage ID, changing to `a69c:8d80` for firmware loading, and failing when
the SDK V5 FMAC upload reaches address `0x170400`.
## Root cause
The affected MCU revision cannot accept the complete SDK V5 FMAC image in its
available upload window. With an upload base of `0x120000`, the deterministic
failure at `0x170400` gives a limit of about `0x50400` (328,704) bytes.
| Firmware | Size | End address (exclusive) | Relative to `0x170400` |
| --- | ---: | ---: | ---: |
| SDK V5 FMAC on `main` | 358,072 bytes | `0x1776B8` | 29,368 bytes over |
| SDK V3 FMAC on this branch | 327,037 bytes | `0x16FD7D` | 1,667 bytes free |
Replacing only the FMAC image is not sufficient. Earlier mixed-firmware tests
could enumerate but failed to provide a usable radio. This branch therefore
uses the complete matching AIC8800D80 firmware set from Radxa SDK V3, fixed at
upstream commit
[`254d47e6a131dbed5ba32131972f4719f3e1c7fe`](https://github.com/radxa-pkg/aic8800/commit/254d47e6a131dbed5ba32131972f4719f3e1c7fe),
together with its matching FMAC patch table and fixed patch-buffer layout.
For `chip_mcu_id=1`, the loader also reads register `0x40100020`, sets bit 0,
and writes it back before firmware upload. This is the MCU1 Bluetooth cache fix
identified in [PR #35](https://github.com/shenmintao/aic8800d80/pull/35).
Bluetooth continues to use the kernel's standard `btusb` driver; this branch
does not contain or install `aic_btusb`.
Firmware and loader paths for D80N, D80X2, and other variants are unchanged.
The same branch now also carries the separately validated legacy DC/DW profile
documented in the [issue #71 support notes](../issue71-mcu1-v3-profile/README.md).
## Hardware validation
The final profile was validated on a Steren COM-8231+ reporting
`chip_id=7, chip_mcu_id=1`. Test commit
[`027a7a8`](https://github.com/shenmintao/aic8800d80/commit/027a7a8)
demonstrated all of the following:
- the 327,037-byte FMAC uploads completely without `cmd timed-out` or
`bin upload fail: 170400`;
- the adapter completes `a69c:572f -> a69c:8d80 -> a69c:8d81` enumeration;
- 2.4 GHz and 5 GHz Wi-Fi scan, association, DHCP, and traffic work;
- USB interfaces 0 and 1 bind to system `btusb`, while interface 2 binds to
`aic8800_fdrv`;
- the earlier HCI Reset timeout `Opcode 0x0c03 failed: -110` is gone;
- Bluetooth scan and a real connection both succeed.
## Install
From an existing clone:
```bash
git fetch origin
git switch legacy-mcu1
git pull --ff-only
sudo ./install.sh
sudo reboot
```
The installer replaces the installed AIC firmware. Switching Git branches
without rerunning `install.sh` does not change the active firmware.
The expected V3 FMAC can be confirmed with:
```bash
stat -c '%s bytes' /lib/firmware/aic8800D80/fmacfw_8800d80_u02.bin
sha256sum /lib/firmware/aic8800D80/fmacfw_8800d80_u02.bin
```
Expected output:
```text
327037 bytes
1ec680c2b63dcaa0e5d33c5fb6d1857d030f8145c05c385e243760388a61a0da
```
## Verify
After reboot or a physical disconnect/reconnect, check the complete device:
```bash
sudo dmesg | grep -iE 'AIC8800D80|chip_id|chip_mcu_id|fmacfw|bin upload|cmd timed-out|Bluetooth|0x0c03|error -110'
lsusb -t
iw dev
bluetoothctl list
```
The initialization log should contain:
```text
AIC8800D80 legacy: using Radxa SDK V3 loader profile
AIC8800D80 MCU1: enabled Bluetooth cache fix
```
`lsusb -t` should show Bluetooth interfaces using `btusb` and the Wi-Fi
interface using `aic8800_fdrv`. Verify traffic through the AIC network interface
rather than an onboard Wi-Fi adapter or phone/RNDIS connection.
## Return to current firmware
Newer `chip_mcu_id=0` hardware should use `main`. Reinstall after switching so
that the V5 firmware is restored under `/lib/firmware`:
```bash
git switch main
git pull --ff-only
sudo ./install.sh
sudo reboot
```
-12
View File
@@ -1,12 +0,0 @@
KVER ?= $(shell uname -r)
KDIR ?= /lib/modules/$(KVER)/build
obj-m += aic_zlp_quirk.o
.PHONY: all clean
all:
$(MAKE) -C $(KDIR) M=$(CURDIR) modules
clean:
$(MAKE) -C $(KDIR) M=$(CURDIR) clean
-109
View File
@@ -1,109 +0,0 @@
# Issue #63: standard `btusb` ACL ZLP support
The `aic_zlp_quirk` companion module supplies the Bluetooth ACL bulk TX
zero-length-packet behavior confirmed in
[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 validated failure was specific and reproducible: AAC playback through USB
device `368b:8d81` stalled after about one minute, while SBC remained stable.
Adding `URB_ZERO_PACKET` to the ACL bulk OUT URBs kept AAC connected for more
than one hour. The standalone module was then verified with the system
`btusb`, no loaded `aic_btusb`, and 2,113 observed ZLP injections.
## Architecture and scope
The module first tries to attach a kretprobe to the standard `btusb` function
that allocates 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 function. When the preferred hook
is unavailable, the module falls back to the stable `usb_submit_urb` entry
point. The fallback changes an URB only when all of these checks pass:
- USB device is exactly `368b:8d81`;
- the transfer is bulk OUT;
- the endpoint belongs to Bluetooth interface 0 (`e0/01/01`).
Both paths add only `URB_ZERO_PACKET`. Wi-Fi interfaces and unrelated USB
devices are unchanged. If neither probe can be installed or kprobes are
disabled, the module refuses to load and system `btusb` remains unchanged.
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.
## Install from the unified branch
```bash
git fetch origin
git switch test/unified-wifi-bt-zlp
git pull --ff-only
sudo ./install.sh
sudo reboot
```
The installer removes the earlier `btusb-aic-zlp/0.1` and
`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
lsusb -t
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
```
Expected results include:
```text
Bluetooth interfaces 0/1: btusb
aic_btusb: not loaded
aic_zlp_quirk: loaded
active hook: btusb:alloc_bulk_urb
```
`active hook: usb_submit_urb` is also valid when the compiler inlined the
preferred function. During Bluetooth traffic, the `injections` value must
increase.
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.
## Isolated retest helper
`aic-zlp-quirk-test.sh` remains available only for isolated issue #63 retests.
It builds the same canonical source from
`drivers/aic8800/aic_zlp_quirk/aic_zlp_quirk.c` as a separate DKMS package. A
normal installation should use the repository-level `install.sh` instead.
## Kernel requirements
- matching kernel headers;
- `CONFIG_KPROBES=y` and kretprobe support;
- standard `btusb` plus either its `alloc_bulk_urb` symbol or the USB core
`usb_submit_urb` symbol;
- a valid module signature when Secure Boot policy requires one.
The preferred function has the same signature in Linux 5.15, 6.1, 6.6, 6.12,
6.18, and 7.1.3, although compilers may inline it. DKMS builds one module for
each installed kernel from the single canonical source file.
@@ -1,239 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
PACKAGE_NAME="aic-zlp-quirk"
PACKAGE_VERSION="0.1"
MODULE_NAME="aic_zlp_quirk"
KERNEL_RELEASE="${KERNEL_RELEASE:-$(uname -r)}"
KERNEL_BUILD_DIR="/lib/modules/${KERNEL_RELEASE}/build"
SOURCE_DIR="/usr/src/${PACKAGE_NAME}-${PACKAGE_VERSION}"
MODULES_LOAD_FILE="/etc/modules-load.d/${PACKAGE_NAME}.conf"
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() {
printf '[aic-zlp-quirk-test] %s\n' "$*"
}
die() {
printf '[aic-zlp-quirk-test] ERROR: %s\n' "$*" >&2
exit 1
}
require_root() {
[ "$(id -u)" -eq 0 ] || die "run this command as root"
}
require_command() {
command -v "$1" >/dev/null 2>&1 || die "required command not found: $1"
}
stop_bluetooth() {
if command -v systemctl >/dev/null 2>&1; then
systemctl stop bluetooth.service 2>/dev/null || true
fi
}
start_bluetooth() {
if command -v systemctl >/dev/null 2>&1; then
systemctl start bluetooth.service 2>/dev/null || true
fi
}
module_loaded() {
[ -d "/sys/module/$1" ]
}
legacy_btusb_loaded() {
module_loaded aic_btusb
}
patched_btusb_installed() {
dkms status -m btusb-aic-zlp -v 0.1 2>/dev/null | grep -q .
}
copy_sources() {
install -d "${SOURCE_DIR}"
install -m 0644 "${QUIRK_SOURCE}" "${SOURCE_DIR}/"
install -m 0644 "${SCRIPT_DIR}/Makefile" "${SOURCE_DIR}/"
install -m 0644 "${SCRIPT_DIR}/dkms.conf" "${SOURCE_DIR}/"
}
rollback_install() {
log "rolling back the ZLP companion module"
rm -f -- "${MODULES_LOAD_FILE}"
modprobe -r "${MODULE_NAME}" >/dev/null 2>&1 || true
dkms remove -m "${PACKAGE_NAME}" -v "${PACKAGE_VERSION}" --all >/dev/null 2>&1 || true
rm -rf -- "${SOURCE_DIR}"
depmod -a "${KERNEL_RELEASE}" >/dev/null 2>&1 || true
start_bluetooth
}
verify_standard_btusb() {
if legacy_btusb_loaded; then
die "obsolete aic_btusb is loaded; run 'sudo modprobe -r aic_btusb' and remove its old autoload configuration first"
fi
if patched_btusb_installed; then
die "the patched btusb test package is still installed; remove it before testing the companion module"
fi
modprobe btusb || die "could not load the system btusb module"
}
install_module() {
require_root
require_command dkms
require_command make
require_command modprobe
require_command depmod
[ -r "${KERNEL_BUILD_DIR}/Makefile" ] || \
die "kernel build tree not found: ${KERNEL_BUILD_DIR}"
if command -v lsusb >/dev/null 2>&1 && ! lsusb -d 368b:8d81 >/dev/null 2>&1; then
die "this test is restricted to USB device 368b:8d81, which is not connected"
fi
verify_standard_btusb
if module_loaded "${MODULE_NAME}"; then
log "unloading the earlier companion module"
if ! modprobe -r "${MODULE_NAME}"; then
die "could not unload the earlier ${MODULE_NAME} module"
fi
fi
trap rollback_install ERR
if dkms status -m "${PACKAGE_NAME}" -v "${PACKAGE_VERSION}" 2>/dev/null | grep -q .; then
log "removing an earlier companion-module build"
dkms remove -m "${PACKAGE_NAME}" -v "${PACKAGE_VERSION}" --all
fi
rm -rf -- "${SOURCE_DIR}"
copy_sources
log "building the ZLP companion module for ${KERNEL_RELEASE}"
dkms add -m "${PACKAGE_NAME}" -v "${PACKAGE_VERSION}"
dkms build -m "${PACKAGE_NAME}" -v "${PACKAGE_VERSION}" -k "${KERNEL_RELEASE}"
dkms install -m "${PACKAGE_NAME}" -v "${PACKAGE_VERSION}" \
-k "${KERNEL_RELEASE}" --force
depmod -a "${KERNEL_RELEASE}"
printf '%s\n' "${MODULE_NAME}" > "${MODULES_LOAD_FILE}"
stop_bluetooth
if ! modprobe "${MODULE_NAME}"; then
trap - ERR
rollback_install
die "the companion module could not attach; the system btusb was left unchanged"
fi
start_bluetooth
trap - ERR
log "loaded module: $(modinfo -n "${MODULE_NAME}")"
log "system btusb remains active; test AAC playback for at least one hour"
}
remove_module() {
require_root
require_command dkms
require_command modprobe
require_command depmod
stop_bluetooth
rm -f -- "${MODULES_LOAD_FILE}"
if module_loaded "${MODULE_NAME}" && ! modprobe -r "${MODULE_NAME}"; then
start_bluetooth
die "could not unload ${MODULE_NAME}; no files were removed"
fi
if dkms status -m "${PACKAGE_NAME}" -v "${PACKAGE_VERSION}" 2>/dev/null | grep -q .; then
if ! dkms remove -m "${PACKAGE_NAME}" -v "${PACKAGE_VERSION}" --all; then
start_bluetooth
die "DKMS removal failed; source files were left in place"
fi
fi
rm -rf -- "${SOURCE_DIR}"
depmod -a "${KERNEL_RELEASE}"
start_bluetooth
log "removed the companion module; the distribution btusb was never replaced"
}
show_aic_binding() {
local device
local driver
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
driver="not bound"
if [ -L "${device}:1.0/driver" ]; then
driver="$(basename "$(readlink -f "${device}:1.0/driver")")"
fi
printf 'AIC BT driver: %s\n' "${driver}"
return
done
printf 'AIC BT driver: device not found\n'
}
show_status() {
local loaded="no"
local injections="unavailable"
local hook="unavailable"
local integrated_dkms_status
local standalone_dkms_status
if module_loaded "${MODULE_NAME}"; then
loaded="yes"
if [ -r "/sys/module/${MODULE_NAME}/parameters/injections" ]; then
injections="$(cat "/sys/module/${MODULE_NAME}/parameters/injections")"
fi
if [ -r "/sys/module/${MODULE_NAME}/parameters/hook" ]; then
hook="$(cat "/sys/module/${MODULE_NAME}/parameters/hook")"
fi
fi
standalone_dkms_status="$(dkms status -m "${PACKAGE_NAME}" -v "${PACKAGE_VERSION}" 2>/dev/null || true)"
if [ -z "${standalone_dkms_status}" ]; then
standalone_dkms_status="not installed"
fi
integrated_dkms_status="$(dkms status -m aic8800 -v 1.0.0 2>/dev/null || true)"
if [ -z "${integrated_dkms_status}" ]; then
integrated_dkms_status="not installed"
fi
printf 'kernel: %s\n' "${KERNEL_RELEASE}"
printf 'btusb module: %s\n' "$(modinfo -n btusb 2>/dev/null || printf 'not found')"
printf 'quirk module: %s\n' "$(modinfo -n "${MODULE_NAME}" 2>/dev/null || printf 'not found')"
printf 'quirk loaded: %s\n' "${loaded}"
printf 'active hook: %s\n' "${hook}"
printf 'ZLP injections:%s\n' " ${injections}"
printf 'legacy aic_btusb: %s\n' "$(legacy_btusb_loaded && printf 'loaded' || printf 'not loaded')"
printf 'integrated DKMS: %s\n' "${integrated_dkms_status}"
printf 'standalone DKMS: %s\n' "${standalone_dkms_status}"
show_aic_binding
}
case "${1:-}" in
install)
install_module
;;
remove)
remove_module
;;
status)
show_status
;;
*)
printf 'Usage: %s {install|remove|status}\n' "$0" >&2
exit 2
;;
esac
-10
View File
@@ -1,10 +0,0 @@
PACKAGE_NAME="aic-zlp-quirk"
PACKAGE_VERSION="0.1"
MAKE[0]="make KVER=${kernelver}"
CLEAN="make KVER=${kernelver} clean"
BUILT_MODULE_NAME[0]="aic_zlp_quirk"
DEST_MODULE_LOCATION[0]="/updates/dkms"
AUTOINSTALL="yes"
-77
View File
@@ -1,77 +0,0 @@
# AIC8800DC/DW legacy MCU revision 1 support
The `legacy-mcu1` branch is the maintained compatibility profile for older
AIC8800DC/DW devices tracked in
[issue #71](https://github.com/shenmintao/aic8800d80/issues/71). It follows the
same method as the successful issue #58 D80 profile: use a complete, matched
legacy firmware and loader rather than mixing firmware generations.
The branch keeps the current USB transport, cfg80211 integration, device IDs,
DKMS installer, and modern-kernel compatibility. For AIC8800DC/DW it restores
the complete firmware directory and matching loader from immediately before
SDK V5 commit `d66e5cb`. That loader includes the MCU1 cache fix and flash DPD
validation used by the reporter's previously working driver.
The first issue #71 test proved that the DPD result stored in flash was valid,
but the V5 main application still timed out at `DBG_START_APP_REQ`. Test commit
[`dbfbfa0`](https://github.com/shenmintao/aic8800d80/commit/dbfbfa0) restored the
complete profile matching the reporter's known-good firmware hashes, after
which the reporter confirmed that the TX1U Nano worked.
## Install
```bash
git fetch origin
git switch legacy-mcu1
git pull --ff-only
sudo ./install.sh
sudo poweroff
```
After shutdown, unplug the TX1U Nano or remove host power for at least 10
seconds before reconnecting and booting.
## Verify
```bash
git rev-parse --short HEAD
md5sum /lib/firmware/aic8800DC/fmacfw_patch_8800dc_u02.bin
md5sum /lib/firmware/aic8800DC/fmacfw_patch_tbl_8800dc_u02.bin
lsusb
lsusb -t
iw dev
sudo journalctl -k -b --no-pager | tee issue71-v3-profile.log
sudo journalctl -k -b --no-pager | grep -iE 'issue71|chip_id|chip_mcu_id|chip_sub_id|DPD|calib|patch.*tbl|start app|firmware version|interface|wlan|timed-out|err_lmac'
```
Expected firmware values and log markers include:
```text
bfd8ea1d174242e7ec823813b6c5d849 fmacfw_patch_8800dc_u02.bin
7b5fde609392c2e6c2c5874838dda718 fmacfw_patch_tbl_8800dc_u02.bin
chip_id=7, chip_mcu_id=1, chip_sub_id=1
issue71: using complete pre-SDK-V5/V3 DC/DW firmware and loader profile
issue71: legacy V3 flash DPD result is valid
misc ram valid, skip calib process
FMACFW_PATCH_TBL_8800DC_U02_DESCRIBE_BASE = 187c00
Start app: 00150000, 5
Firmware Version: ...
New interface create wlan0
```
There should be no command timeout, `err_lmac_reqs`, or failed USB probe after
the main application starts.
Confirm scanning, association, DHCP, gateway and Internet reachability, real
traffic, and clean initialization after a USB unplug/replug cycle.
## Roll back
```bash
git switch main
git pull --ff-only
sudo ./install.sh
sudo poweroff
```
Cold-power-cycle the adapter again before booting the rollback result.
-87
View File
@@ -1,87 +0,0 @@
# Unified Wi-Fi, Bluetooth, and ZLP branch test
This branch tests replacing the separate `main` and `bluetooth` branches with
one driver and installer. The Wi-Fi driver and firmware were already identical
on both branches. This test unifies their installer, migration, diagnostics,
packaging, and documentation, and adds the device-scoped ZLP fix from issue
#63 as a third DKMS module.
The expected architecture is:
- `aic_load_fw` initializes every supported adapter and uploads firmware.
- `aic8800_fdrv` handles Wi-Fi.
- A combo adapter exposes a Bluetooth HCI USB interface after initialization;
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`.
- 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
unblock Bluetooth through rfkill.
## Install
```bash
git fetch origin
git switch test/unified-wifi-bt-zlp
git pull --ff-only
sudo ./install.sh
sudo reboot
```
## Test a Wi-Fi-only adapter
Confirm that:
1. The Wi-Fi interface is created.
2. Scanning, association, DHCP, and real traffic work.
3. No `aic_btusb` module is loaded.
4. The absence of `btusb` or an HCI controller is treated as normal.
## Test a Wi-Fi/Bluetooth combo adapter
Confirm that:
1. Wi-Fi scanning, association, DHCP, and real traffic work.
2. `aic_load_fw` uploads the firmware before the HCI interface is used.
3. The Bluetooth USB interface is bound to the standard `btusb` driver.
4. `bluetoothctl` can power on, scan, pair, and exchange real traffic.
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
```bash
git rev-parse --short HEAD
lsusb
lsusb -t
lsmod | grep -E 'aic|btusb|bluetooth'
iw dev
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 journalctl -k -b --no-pager | tee unified-wifi-bt-kernel.log
```
Please attach both logs and identify whether the tested adapter is Wi-Fi-only
or a combo device.
## Roll back during testing
```bash
git switch main
git pull --ff-only
sudo ./install.sh
sudo reboot
```