.--..--..--..--..--..--..--..--..--..--..--.
/ .. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \\n\ \ /\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ \ / /
\/ /`--'`--'`--'`--'`--'`--'`--'`--'`--'\/ /
/ /\ / /\
/ /\ \ .d8b. db d88888b .d8b. / /\ \\n\ \/ / d8' `8b 88 88' d8' `8b \ \/ /
\/ / 88ooo88 88 88ooo 88ooo88 \/ / ATXPK v1.2.0
/ /\ 88~~~88 88 88~~~ 88~~~88 / /\
/ /\ \ 88 88 88booo. 88 88 88 / /\ \\n\ \/ / YP YP Y88888P YP YP YP \ \/ /
\/ / \/ /
/ /\.--..--..--..--..--..--..--..--..--./ /\
/ /\ \.. \.. \.. \.. \.. \.. \.. \.. \.. \/\ \\n\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `' /
`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'
A simple Python utility to help understand and manage TX power readings on the Alfa ACHM (MT7610U) WiFi adapter on Linux.
atxpk helps you:
- Check current TX power and adapter state for your Alfa ACHM.
- Apply an EEPROM patch to keep the adapter at the target TX power.
- Use an
iwfallback loop when the EEPROM patch cannot be verified. - Install a systemd service so the fix applies automatically on plug-in.
- Understand why
iw devTX power readings behave the way they do.
If you've seen your Alfa show txpower 7.00 dBm and panicked, here's what we learned after testing across three platforms:
| Platform | Device | Architecture |
|---|---|---|
| Kali 3 | MacBook USB boot | x86_64 |
| Kali 2 | Raspberry Pi 4 | ARM64 |
| Kali 1 | Raspberry Pi 3B+ | ARM |
iw dev TX power is NOT a live measurement. It's a calibration value from the adapter's EEPROM, specific to each channel/frequency band. It does NOT change with regulatory domain settings.
| Channel | Band | TX Power (all platforms) |
|---|---|---|
| 1, 6 | 2.4 GHz | ~4 dBm |
| 11 | 2.4 GHz | ~5 dBm |
| 36, 149 | 5 GHz | ~17 dBm |
| 165 | 5 GHz | ~19 dBm |
7 dBm is just a placeholder. When the interface is in managed mode with no active channel set, iw dev shows 7 dBm as a default value. This is NOT your actual TX power.
To see real TX power values:
- Put interface in monitor mode
- Set a specific channel
- Check
iw devagain
sudo airmon-ng check kill
sudo ip link set wlan0 down
sudo iw dev wlan0 set type monitor
sudo ip link set wlan0 up
sudo iw dev wlan0 set channel 149
sudo iw dev wlan0 infoiw reg set may or may not apply to your adapter's PHY depending on your kernel/driver setup. But it does NOT affect the iw dev txpower reading — that comes from the adapter's own calibration table regardless of what iw reg get shows.
- Don't trust 7 dBm in managed mode — it's meaningless.
- Don't panic if reg domain shows "99" or "UNSET" — the adapter still works at its calibrated power.
- Monitor mode + locked channel = real numbers.
- Your actual transmit power is determined by the adapter firmware, not what
iwdisplays.
Clone the repository and install the systemd service:
git clone https://github.com/KiMiGuel/ALFA-TXPower-Keeper
cd ~/atxpk
sudo ./atxpk installThis will:
- Copy the keeper to
/opt/atxpk/ - Create
/usr/local/sbin/atxpk - Install the systemd service
atxpk.service - Install the udev rule
99-atxpk.rules - Start and enable the service
Check status:
sudo systemctl status atxpk
sudo journalctl -u atxpk -fRun without arguments to open the interactive menu:
sudo ./atxpkMenu options:
- Fix Now — detect the Alfa and apply the EEPROM patch/iw fallback.
- Monitor & Patch — switch to monitor mode on channel 149, then apply the fix (most reliable TX-power reading).
- Fix iw reg — set the regulatory domain to BO and verify it.
- Install Service — install the systemd service and udev rules.
- Uninstall Service — remove the systemd service and udev rules.
- Check Status — show adapter presence, phy, interface, permanent MAC, and TX power.
- Exit
# Show adapter state
sudo ./atxpk status
# Run a single patch/verify cycle
sudo ./atxpk oneshot
# Run continuously in the foreground
sudo ./atxpk daemon
# Interactive fix mode (connect USB)
sudo ./atxpk fix
# Verbose output
sudo ./atxpk -v daemon
sudo ./atxpk oneshot -v| Option | Default | Description |
|---|---|---|
| -i, --interface | auto-discover | Optional interface name for iw fallback |
| -t, --target-dbm | 20 | Target TX power in dBm |
| --interval | 3 | Daemon check interval in seconds |
| --eeprom-offset | 0x52 | EEPROM offset to patch |
| --eeprom-value | 0x1e | EEPROM value to write |
| --max-retries | 30 | Retries when waiting for adapter/phy |
sudo ./atxpk uninstallThis stops the service, removes the systemd/udev integration, and deletes
/opt/atxpk and /usr/local/sbin/atxpk.
- On startup (or when the daemon wakes), enumerate USB devices for
idVendor=0e8d,idProduct=7610. - For each
phy*in/sys/class/ieee80211/, resolve thedevicesymlink and check whether it belongs to the matched USB device. - Mount debugfs if necessary.
- Attempt to write
0x1eto offset0x52of the discovered EEPROM node. - Read back the byte. If it equals
0x1e, the patch is verified. - For interactive modes, switch the interface to monitor mode, lock channel 149, and read the real TX power.
- If the target TX power is not reached, enter the
iwfallback loop. - If the adapter disappears, reset state and wait for re-insertion.
- The debugfs EEPROM node may appear as mode
0400(read-only). The tool attempts the write directly, because many kernels still allow root to write to it viadd. - The
iw set txpowerfallback is a best-effort workaround. Themt76x0udriver binds TX power to EEPROM values, soiwmay be ignored depending on kernel version and driver state. - A complete fix requires patching the kernel driver itself; this tool is a user-space workaround.
Service fails to start:
sudo journalctl -u atxpk -n 50Adapter not detected:
- Confirm the adapter is plugged in.
- Check
lsusb | grep 0e8d:7610.
EEPROM patch fails:
- Some kernels hard-lock the debugfs EEPROM node. The tool will automatically
fall back to the
iwloop.
Wrong or missing interface name:
- The tool auto-discovers the interface from the matched
phyX. If that fails, pass-i <interface>or set it in the systemd serviceExecStartline. - If no interface is found, EEPROM patching still runs, but
iwfallback and TX power verification are skipped.
iw(wireless tools)airmon-ng(aircrack-ng suite) — for monitor-mode diagnostics- Python 3.7+
- systemd — for service/udev integration
Testing and validation done across MacBook USB boot, Raspberry Pi 4, and Raspberry Pi 3B+ running Kali Linux. Thanks to the morrownr/8812au-8821au-linux-wireless-drivers community for the diagnostic guidance.
Note: This script is for educational and diagnostic purposes. Always comply with local RF regulations.