- C 67.6%
- Makefile 25.5%
- Shell 6.9%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .github/workflows | ||
| packaging | ||
| src | ||
| dkms.conf | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
powermiao8k
Linux kernel driver that exposes the Angry Miao INFINITY 8K Mouse battery
(both the mouse cell and the dock's spare cell) as power_supply devices,
so UPower / GNOME / KDE pick them up natively — no userspace daemon, no
virtual HID, no /dev/uhid.
┌────────────────────────────────────────────────┐
│ AM INFINITY 8K │
│ HID interface 0 (mouse pointer) │
│ HID interface 1 (keyboard / consumer ctrl) │
│ HID interface 2 (battery feature report) ◄─┐ │
└──────────────────────────────────────────────┼─┘
│
feature read │ every 15 s
│
┌────────────────────────────────┴───┐
│ powermiao8k.ko │
│ │
│ /sys/class/power_supply/ │
│ powermiao8k ← main │
│ powermiao8k_spare ← dock cell│
└────────────────────────────────────┘
│
▼
UPower → KDE / GNOME widget
Supported hardware
- Angry Miao INFINITY 8K Mouse with charging dock — USB VID:PID
3151:5007
The wired-mode device (3151:402A) is intentionally not supported: that
firmware doesn't expose battery state over HID feature reports.
Features
- Two
power_supplydevices, one per physical battery cell. - KDE/GNOME show the mouse icon for the main battery and the plain battery icon for the dock cell.
- 15-second polling interval; only emits
power_supply_changed()when the value actually moves. - The dock cell is reported as
present=0when the dock isn't paired/in range, and always asstate=Chargingso the desktop doesn't flash a low-battery warning when it dips. - DKMS source package for both Fedora/RHEL (RPM) and Debian/Ubuntu (DEB) — auto-rebuilds on kernel upgrades.
- Ships a udev rule that makes UPower classify the main battery as a mouse (without breaking keyboard input on the device's other HID interface).
Install
Fedora / RHEL / openSUSE — RPM
Grab the latest RPM from the releases page and:
sudo dnf install ./powermiao8k-*.rpm
The first install triggers a one-time DKMS build (~30–90 s) and, if Secure
Boot is on, generates a self-signed MOK key under /var/lib/dkms/. If
the kernel rejects the unsigned/MOK-signed module, enroll the key once:
sudo mokutil --import /var/lib/dkms/mok.pub
sudo reboot # at the blue MOK Manager screen → Enroll MOK
Debian / Ubuntu — DEB
sudo apt install ./powermiao8k-dkms_*.deb
dkms is pulled in automatically as a dependency.
From source
Either flavor of package, plus a manual install path, are produced by the
top-level Makefile:
make rpm # → rpmbuild/RPMS/x86_64/powermiao8k-*.rpm
make deb # → debbuild/powermiao8k-dkms_*.deb
sudo make install # bare module + udev rule, no DKMS
sudo modprobe powermiao8k
Build deps for make rpm: rpm-build, systemd-rpm-macros.
Build deps for make deb: build-essential, debhelper, dpkg-dev, fakeroot.
Verify
# Module is loaded
lsmod | grep powermiao8k
# Two power_supply nodes exist
ls /sys/class/power_supply/
# powermiao8k powermiao8k_spare
# UPower sees both
upower -e | grep powermiao
upower -i /org/freedesktop/UPower/devices/battery_powermiao8k
upower -i /org/freedesktop/UPower/devices/battery_powermiao8k_spare
In KDE Plasma's battery applet you should see two entries — one with a mouse icon ("AM INFINITY Mouse") and one with a battery icon ("AM INFINITY Spare Battery").
How it works
The mouse exposes three HID interfaces. The kernel module:
-
Binds to all three interfaces of
3151:5007(so we don't crowd out the input/keyboard devices on input0/input1 — they still work viaHID_CONNECT_DEFAULT). -
Only on input2 does it actually open the transport (
hid_hw_power(FULLON)+hid_hw_open()) and run the polling workqueue. -
Every 15 s it issues the same handshake the dock firmware uses:
SET_FEATURE report 0x00, command byte 0xF7 sleep 50 ms GET_FEATURE report 0xF7 → 65 bytes; main% at byte 2, spare% at byte 10 -
Both readings are pushed into two separate
power_supplydevices. The main one is parented under the HID device so UPower's sibling walk reaches the mouse/keyboard input nodes; the spare is parented under a private virtual class so it stays a generic battery in the UI.
The shipped 99-powermiao8k.rules adds ID_INPUT_MOUSE=1 to every
input device of 3151:5007. UPower's per-input-node priority list
prefers MOUSE over KEYBOARD, so once both candidates look like mice,
the main battery is typed as a mouse without us having to strip
keyboard tags from anything (libinput / Wayland still see the
keyboard interface as a keyboard via its EVDEV capability bits).
Cutting a release
The CI workflow (.github/workflows/release.yml) builds both .deb and
.rpm on every push. Pushing a tag creates a GitHub Release with the
artifacts attached:
git tag v1.2.3
git push origin v1.2.3
The version from the tag is patched into the spec, the Makefile, and the Debian changelog/maintainer scripts before each package is built.
Troubleshooting
Battery values show -1 / "Unknown"
Either DKMS hasn't built the module (check dkms status) or the
mouse is connected wired (3151:402A); only dock mode is supported.
Run dmesg | grep powermiao8k to see the driver's own error line.
Module loaded but /sys/class/power_supply/powermiao8k is missing
The driver only registers power_supply nodes on input2 of the mouse.
Confirm: ls /sys/bus/hid/devices/0003:3151:5007.*/driver should show
the powermiao8k symlink on at least one of the entries (the input2
one).
KDE shows the wrong icon (keyboard "A" instead of mouse)
The udev rule didn't apply yet. Either:
sudo udevadm control --reload-rules
# unplug/replug the mouse, OR:
sudo modprobe -r powermiao8k && sudo modprobe powermiao8k
"Module is in use" on uninstall
UPower is reading /sys/class/power_supply/powermiao8k. The package's
%preun does a best-effort modprobe -r; if that races with UPower
you can finish the unload manually after the package is removed:
sudo modprobe -r powermiao8k
License
GPL-2.0-only — see LICENSE.
Author
TsFreddie <whatis@tsdo.in>