Skip to content

v0.1.22

Choose a tag to compare

@github-actions github-actions released this 25 Oct 00:02
· 20 commits to main since this release

Six changes on the Fusion2 line — the X2A, X2H, X2 Wired, Xlite Wired, Xlite v4, X3 and the 1K dongle — found and measured by @f-o-o-g-s on a Pulsar X3, with the X2A side confirmed here.

"Forward" and "backward" sent each other's button

hid.MOUSE_ACTIONS had the two HID mouse codes the wrong way round, so a side button bound to "forward" went back, and one bound to "backward" went forward. That affected every driver that passes those codes through, not one model. Code 4 is BTN_SIDE (back) and code 5 is BTN_EXTRA (forward) — measured on an X3, then confirmed on an X2A three separate ways, including one run with each thumb button bound to a signal that could not be confused with the others.

The X2A's thumb-button labels were wrong in the same direction, all four of them: the rear button on each flank is back and the front one is forward, where the driver named each as the other. The X2H, Xlite v4, X3, Feinmann 8K and the Nordic family had the same two labels the same way round.

Profiles exported before this fix still restore what they saved. Exports now carry version: 2, and a version-1 file has the two action names swapped back when it is imported into a driver that was affected.

The firmware version

New. get_firmware_version() answered "unknown" on all seven Fusion2 drivers; it now reads the mouse's own version, shown by the CLI and in the GUI's model tooltip. Through the 1K dongle it is the mouse's firmware rather than the dongle's.

All four bytes are shown, highest first, because the two models measured keep the version in different bytes of the same four — an X3 reads 00.00.10.16 and its bcdDevice is 10.16; an X2A reads 00.08.00.00 and its bcdDevice is 8.00. Trimming to something prettier would be a guess at a layout that differs per model.

Profile switching on the Fusion2 family

get_active_profile() / set_active_profile() for the family. The GUI's profile selector and the CLI's --profile now follow and set the profile the mouse is actually using on those drivers, instead of only reading and writing a given profile's stored settings. Measured on an X3 on its cable and through the dongle.

The X3's six profiles and its DPI range

The X3 lists six profiles and switches to each of them, where the driver offered five. Its DPI goes to 32000 in steps of 10, not 26000 in steps of 100 — confirmed from the mouse rather than the spec sheet, by writing 31990, 32000, 12345, 12340 and 26010 and reading each back unchanged, on the cable and through the dongle.

A read the mouse dropped is sent again

In the first moments after a Fusion2 mouse's dongle comes out and its cable goes in, the mouse drops the command: the status byte stays 00 for a full second of polling and no answer ever arrives, while the same read sent again is answered. Polling longer never recovers it. Reads are now resent, up to six times about 0.26 s apart.

The budget belongs to the open rather than to each read, because once one read has been answered every later read in that open has answered on its first poll in every measurement either of us has — after each swap, 1000 in a row on a cabled X3, 67 on an X2A. So a mouse that answers nothing costs about 1.6 s on the first read and 0.14 s on each one after, and a 25-read GUI pass that gets nothing takes about 5 s, where resending every read would have taken about 40.

Reads only: a write is accepted at 02 and resending one the mouse did take is a different risk, not measured.

A dongle that says it has no link stops asking

With the mouse asleep, or not back on the dongle yet, the 1K dongle answers a request with 05 and the request echoed on the very first poll — and a request that got one is never answered, however long it is polled. 5606 polls of a sleeping read said so, as did 286 more over the three seconds after the mouse woke; the same read sent again was answered in 33 ms. A write held the same way was never taken either.

So the request now ends at that poll, for writes as well as reads, with a message that names no link rather than a timeout. A GUI page of two dozen reads on a sleeping mouse takes 28 ms instead of a second each — and it holds the USB lock for all of it, so the window and the tray used to queue behind a mouse that had said no in the first millisecond.


Found and measured by @f-o-o-g-s on a Pulsar X3, on its cable and behind the 1K dongle, with the X2A measurements here. Full attribution is in the README.