Skip to content

About

Attack Shark K86 Linux Software

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Attack Shark K86 – Linux configuration software

Static Badge AUR Version AUR Version

A C++ rewrite of the Windows-only Attack Shark K86 driver (https://download.attackshark.pro/ATTACKSHARK/K86/ATTACKSHARKK86.zip), based on reverse engineering of its Electron UI. The protocol is documented in docs/PROTOCOL.md.

It consists of

  • k86core – a dependency-free C++17 library (Linux hidraw),
  • k86ctl – a command line tool,
  • k86-gui – an optional GTK 3 GUI (plain GTK, no libadwaita).

Both K86 firmware families known to the original driver are supported:

Model USB id Firmware id
K86 (YC3121) 3151:4015 1168
K86 (YC3123) 3151:5002 2730

Features

  • lighting effects (mode, brightness, speed, direction/option, colour or rainbow), side light
  • per-key colours for the "custom" effect, per-key animations
  • key remapping (3 profiles) and Fn layer remapping, factory layouts, export/import; the K86's own functions (Bluetooth channels, Win lock, lighting and side light keys, …) have names
  • macros (50 slots), bound to keys with macro:N
  • LCD: upload PNG/JPEG/BMP and animated GIFs, clock sync, CPU/RAM/disk/network stats, erase
  • active profile, debounce, sleep timers, option flags, factory reset
  • raw command access

Not implemented: firmware / screen-controller upgrades, and configuration over the 2.4 GHz dongle or Bluetooth (the original routes those through its closed iot_driver.exe); connect the keyboard with the USB cable.

Build

sudo apt install build-essential cmake pkg-config libgtk-3-dev libayatana-appindicator3-dev
# Fedora: sudo dnf install gcc-c++ cmake pkgconf gtk3-devel libayatana-appindicator-gtk3-devel
# Arch:   sudo pacman -S base-devel cmake gtk3 libayatana-appindicator
cmake -S . -B build
cmake --build build -j
ctest --test-dir build        # protocol tests, C API test and the GUI self-test
sudo cmake --install build    # installs k86ctl, k86-gui, libk86 and the udev rule

GTK 3 is only needed for the GUI and libayatana-appindicator only for its tray icon; without them the GUI or the tray icon is left out. -DK86_BUILD_LIBRARY=OFF skips libk86.

Use -DK86_BUILD_GUI=OFF to build without GTK.

Permissions

Install the udev rule so your user can open the keyboard without root:

sudo cp udev/70-attackshark-k86.rules /etc/udev/rules.d/
sudo udevadm control --reload && sudo udevadm trigger

The GUI

k86-gui works like the original software. It finds the keyboard by itself (also when it is plugged in later), reads every setting from it, and shows:

  • Keys and Fn layer – a drawing of the K86. Click a key (Ctrl-click for several), then pick what it should do: another key (with Ctrl / Shift / Alt / Win for combinations), media keys, mouse buttons, a macro, lighting, side light, connection or profile functions. The change is written right away. Changed keys are outlined in blue; the Fn layer shows the factory functions in green.
  • Lighting – effects of the backlight and side light with brightness, speed, direction and colour, applied as you change them, with a preview.
  • Per-key colours – paint keys for the Custom effect (click or drag), then apply.
  • Macros – the 50 macro slots, with an event editor, recording from the keyboard and adjustable delays.
  • Screen – images and GIFs for the LCD, clock sync.
  • Settings – debounce, sleep timers, option switches, firmware versions, factory reset, and the window's own options: tray icon, keep running in the tray when the window is closed, start minimized to the tray (saved in ~/.config/k86-gui/settings.ini).

The tray icon (libayatana-appindicator) needs a tray that supports AppIndicator / StatusNotifierItem: KDE, waybar, GNOME with the AppIndicator extension, and so on. Its menu shows or hides the window and quits; middle click toggles the window. While k86-gui runs in the tray, it keeps the keyboard connected (for example to keep streaming system stats to the screen) and picks it up again when it is plugged in. Without a tray the window stays open.

The profile buttons at the top choose which profile you see and edit (★ marks the one the keyboard uses; Use on keyboard switches it).

k86-gui                      # normal use
k86-gui --minimize           # start hidden in the tray (closing the window keeps it there)
k86-gui --read-only          # read and look around, never write to the keyboard
k86-gui --dry-run=v1         # a simulated YC3121 (v2 = YC3123); writes are printed
k86-gui --self-test          # click through every page against the simulator and check the writes

Command line examples

k86ctl list
k86ctl info
k86ctl light modes
k86ctl light set wave --brightness 4 --speed 3 --option 1 --rainbow
k86ctl light set static --color ff8800
k86ctl sidelight set breath --color 00ffff
k86ctl keys                                          # key slot names
k86ctl keymap set CapsLock LCtrl --layer 0
k86ctl keymap set F12 consumer:Calculator --fn
k86ctl keymap set Pause conn:BT2                     # K86 functions have names too
k86ctl macro set 0 "+LCtrl/5 C/20 -LCtrl" && k86ctl keymap set Pause macro:0
k86ctl keymap export layer0.txt && k86ctl keymap import layer0.txt
k86ctl perkey fill 000000 && k86ctl perkey set W=ff0000 A=ff0000 S=ff0000 D=ff0000
k86ctl light set custom --option 0
k86ctl screen upload cat.gif
k86ctl screen clock
k86ctl sysinfo --interval 1
k86ctl --dry-run=v1 light set breath                 # print the reports, no hardware

Run k86ctl --help and k86ctl actions for the full syntax.

Library (libk86)

libk86.so with the header <k86/k86.h> lets other programs do what k86ctl does. It is a C API (usable from C++, and from Python, Rust, ... through their C FFI) and takes the same key names, actions and macro syntax as k86ctl. Errors are returned as -1 with a message from k86_last_error(); k86_open_simulated() gives an in-memory keyboard to test against.

#include <k86/k86.h>
#include <stdio.h>

int main(void) {
    k86_keyboard* kb = k86_open(NULL, 0);  /* first K86 found */
    if (!kb) {
        fprintf(stderr, "%s\n", k86_last_error());
        return 1;
    }
    k86_set_key(kb, 0, "CapsLock", "LCtrl");             /* k86ctl keymap set CapsLock LCtrl */
    k86_set_fn_key(kb, 0, K86_OS_WINDOWS, "F12", "consumer:Calculator");
    k86_set_macro(kb, 0, "+LCtrl/5 C/20 -LCtrl", 1);     /* k86ctl macro set 0 "..." */

    k86_light l = {0};
    l.mode = (uint8_t)k86_light_mode(kb, "static", 0);
    l.brightness = 4;
    l.color = 0x00FF00;
    if (k86_set_light(kb, &l) != 0) fprintf(stderr, "%s\n", k86_last_error());
    k86_close(kb);
    return 0;
}
cc app.c -o app $(pkg-config --cflags --libs k86)

See include/k86/k86.h for every function (lighting, side light, key maps and Fn layers, macros, per-key colours, LCD images, clock and stats, profile, debounce, sleep, options, factory reset). Only the k86_* functions are exported; the soname is libk86.so.0.

Testing and verification

tests/golden/*.txt were generated by executing the original driver's own JavaScript device classes for both K86 firmwares against a recording HID stub (tests/js/run.mjs; the vendor code is not redistributed here). k86tests checks that the C++ implementation produces byte-identical feature reports for 33 (YC3121) / 36 (YC3123) operations.

To regenerate the golden files, extract the installer (7z x "ATTACK SHARK K86 SOFT.exe", then 7z x '$PLUGINSDIR/app-32.7z') and run node tests/js/run.mjs <extracted>/resources/app/dist/js tests/golden.

Hardware

Tested on a K86 YC3121 (3151:4015, firmware id 1168, USB version 0x0114) over USB: device queries, lighting, side light, per-key colours and animation, key and Fn remapping (checked through the input reports), macros, profile, debounce, sleep timers, options, LCD images and GIFs, clock sync. The GUI's preload and every k86ctl read command were checked read-only against the keyboard. The GUI's write paths are checked by k86-gui --self-test against the protocol simulator for both firmwares: key, Fn layer, macro and profile assignment, lighting and side light, per-key colours and patterns, macro editing and recording, screen upload and clock, settings, read-only mode, confirmations, factory reset and unplugging / replugging. Factory reset and screen erase were not tried on hardware, and the YC3123 (3151:5002) is untested. See docs/PROTOCOL.md for the firmware timing this needed.

The self-test needs a display; ctest skips it without one (CI runs it under xvfb-run).

Releases

Prebuilt binaries (.tar.gz) and .deb, .rpm and pacman packages for x86_64 and aarch64 are on the releases page, each with a .sha256 file and a combined SHA256SUMS (sha256sum -c SHA256SUMS). The packages install the udev rule, so no extra permission setup is needed.

To make a release: set the version in CMakeLists.txt, add its section to CHANGELOG.md, commit, then tag and push (git tag 0.2.1 && git push origin 0.2.1) and run the Release workflow from the Actions tab. It builds the newest tag (or the one you enter), checks that it matches the CMake version, and creates or updates the GitHub release with the changelog section as its notes.

License

GPL-3.0, see LICENSE. third_party/stb/stb_image.h is by Sean Barrett and is public domain / MIT (see the end of that file). The icon in packaging/icons is the Attack Shark logo from the official driver; it is Attack Shark's trademark and not covered by the GPL.

Not affiliated with Attack Shark or RongYuan. The original driver is not included (apart from a few small helper functions in tests/js/stub_index.js); the golden test data is the output of running it.

About

Attack Shark K86 Linux Software

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages