Skip to content

feat: Razer Kraken V4 Pro — haptic sensitivity + battery charging state (issue #11)#20

Open
Zenardi wants to merge 5 commits intomainfrom
feat/issue-11-kraken-haptics
Open

feat: Razer Kraken V4 Pro — haptic sensitivity + battery charging state (issue #11)#20
Zenardi wants to merge 5 commits intomainfrom
feat/issue-11-kraken-haptics

Conversation

@Zenardi
Copy link
Copy Markdown
Owner

@Zenardi Zenardi commented Mar 30, 2026

Summary

Implements haptic intensity control and correct battery state reporting for the Razer Kraken V4 Pro (PID 0x0568).

Changes

Haptic Intensity (Interface 4)

  • D-Bus method SetHapticIntensity dispatches a 64-byte HID Output Report to Interface 4 (wIdx=4, wVal=0x0202)
  • The sensitivity byte in the report controls how strongly the haptic motor amplifies audio into vibration
  • Architecture: the haptic motor converts game audio (played via ALSA on Interface 2) to tactile feedback automatically — our daemon controls the amplification level only

Why Interface 2 Is Never Touched

Interface 2 on PID 0x0568 is bInterfaceSubClass=2 Audio Streaming, managed by the kernel ALSA driver. Claiming it via libusb detaches ALSA and silences the headset. The audio burst approach was reverted. Protocol documentation (Wireshark-verified) is preserved with #[allow(dead_code)] for future reference.

Battery Charging State

  • USB-connected headset always implies charging — changed from Discharging(pct)Charging(pct)
  • The UI correctly shows the pulsing green ring + ⚡ badge
  • 96% is the accurate hardware reading (USB-powered headset maintains near-full charge)

UI

  • HapticsTab.tsx: updated description to clarify haptics respond to in-game audio playback

Testing

  • 57 Rust unit tests pass (including 4 TDD tests for Wireshark-verified audio packet builders)
  • 24 UI tests pass
  • cargo clippy --all-targets --all-features -- -D warnings: clean
  • Trivy: 0 HIGH/CRITICAL vulnerabilities

Closes #11

Zenardi and others added 5 commits March 30, 2026 15:22
…ld_haptic_report

Wireshark analysis of haptics_synapse.pcapng revealed 5 exact byte-level bugs
causing the 64-byte HID SET_REPORT to be malformed — firmware silently discarded
every haptic command.

Bugs fixed (all Wireshark-verified against packet #329):
- buf[26]: 0x3A → 0x39 (wrong fixed value)
- buf[33]=0x06 → buf[34]=0x06 (off-by-one on field marker)
- buf[38]=0x07 → buf[39]=0x07 (off-by-one on field marker)
- buf[39]=0x09 → buf[40]=0x09 (off-by-one on fixed byte)
- buf[40]=0x09 → buf[41]=0x20 (off-by-one + wrong value 0x09→0x20)

Intensity mapping: replaced broken linear formula with Wireshark-verified
discrete lookup table matching Synapse's exact output:
  Off  (0):   haptic_a=0,  haptic_b=0
  Low  (33):  haptic_a=26, haptic_b=62
  Med  (66):  haptic_a=40, haptic_b=68
  High (100): haptic_a=78, haptic_b=81

Tests: updated 3 existing haptic tests + added test_haptic_report_v4_pro_low_intensity.
All 79 Rust tests pass. 24 UI tests pass. Clippy clean.

Closes #11

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Haptics fix:
- Add build_haptic_audio_packet() and build_haptic_audio_end_frame()
  to razer_protocol.rs (Wireshark-verified pkt 27 / pkt 39 structure)
- Add send_haptic_audio_burst() in usb_backend.rs: sends 5 frames of
  Interface-2 audio (cmd_class=0x03, cmd_id=0x0b, wVal=0x0300, wIdx=2)
  alongside the Interface-4 sensitivity command. The motor converts the
  audio signal to vibration; the Interface-4 command alone is silent.
- Update set_haptic_intensity() in device_manager.rs to call the burst
  for non-zero levels after the sensitivity transfer succeeds.

Battery fix:
- Change headset battery state from Discharging to Charging in main.rs:
  USB-connected headset is always receiving power, so Charging is correct.
  96% is the accurate hardware reading (USB-topped-off battery).

TDD:
- 4 new unit tests covering audio packet header, audio data, checksum,
  sub-counter variation, and end-of-frame packet (all Wireshark-verified)
- All 83 Rust tests pass; all 24 UI tests pass; clippy clean; fmt clean

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…udio streaming

Interface 2 on PID 0x0568 is bInterfaceSubClass=2 (Audio Streaming), managed by
the kernel ALSA driver. Claiming it via libusb detaches ALSA and silences the
headset (muting regression in af01361).

Changes:
- Remove send_haptic_audio_burst() and open_razer_device_on_interface() from
  usb_backend.rs — these must never be called on audio interfaces
- device_manager.rs: Interface-4 sensitivity command only (correct behavior)
- razer_protocol.rs: keep build_haptic_audio_packet/end_frame with #[allow(dead_code)]
  as Wireshark-verified protocol documentation + TDD tests remain green
- main.rs: headset battery state = Charging(pct) for USB-connected device
- HapticsTab.tsx: clarify that haptic intensity responds to audio playback

Architecture note: the haptic motor converts audio to vibration automatically
when game audio plays through Interface 2 (ALSA). Our daemon controls the
amplification level only via Interface 4. No daemon-side audio burst needed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- usb_backend.rs: add log::debug! hex dump of 64-byte haptic payload after
  successful write_control. Run with RUST_LOG=debug to inspect exact bytes
  sent to Interface 4 without any audio or hardware changes needed.
  Log comment documents the 4-preset Wireshark lookup table for quick comparison.

- wireshark/HAPTICS_VERIFICATION.md: new doc with three verification methods:
  1. Daemon debug log (fastest — just run RUST_LOG=debug and move the slider)
  2. Linux usbmon + tshark wire capture (confirms bytes hit the USB bus)
  3. cargo test (no hardware needed — Wireshark-verified values in TDD tests)
  Includes full byte lookup table and fixed-field reference.

No functional changes to haptic or battery code.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(kraken-v4-pro): Fix haptic feedback not working for Kraken V4 PRO (PID 0x0568)

1 participant