Skip to content

automatethestack/razer-naga-relay-hotfix

Repository files navigation

Razer Naga Relay • macOS Hotfix for Modifier Keys

macOS hotfix for Razer Naga gaming mice - Fixes modifier keys not working with Naga's 12-button grid.

Without this hotfix, pressing Shift + Naga Button 1 outputs 1 instead of !. Naga Relay intercepts the button presses and re-emits them with the correct modifier state, so your keyboard modifiers (Shift, Cmd, Opt, Ctrl) work properly with Naga buttons.

Razer Synapse alternative | Razer Naga macOS support | Naga Trinity driver | Naga V2 HyperSpeed macOS | Gaming mouse button remapper | macOS Razer driver | Naga side buttons macOS | Naga modifiers not working fix

Quick Start

See SETUP.md for detailed setup and testing instructions.

Overview of Naga Relay

Naga Relay is a lightweight daemon that captures input from Razer Naga mice and relays whitelisted button presses as keyboard events. It uses Apple's IOHIDManager for device-specific capture, meaning it cannot see your main keyboard.

+-------------------------------------------------------------+
|              IOHIDManager (Device-Specific)                 |
+-------------------------------------------------------------+
|  Main Keyboard --> System (untouched, invisible to daemon)  |
|                                                             |
|  Naga Keyboard --> IOHIDManager --> Whitelist --> CGEvent   |
|       |                                              |      |
|       +-- SEIZED (exclusive)              Query mods-+      |
|                                                             |
|  - Cannot see main keyboard keystrokes                      |
|  - Only receives events from Naga                           |
|  - Queries modifiers on-demand (no tracking)                |
|  - Strict whitelist (12 inputs only)                        |
+-------------------------------------------------------------+

Whitelisted Inputs

Only these 12 inputs are processed. All others are silently dropped:

Naga Input Output HID Code
Button 1 1 0x1E
Button 2 2 0x1F
Button 3 3 0x20
Button 4 4 0x21
Button 5 5 0x22
Button 6 6 0x23
Button 7 7 0x24
Button 8 8 0x25
Button 9 9 0x26
Button 10 0 0x27
Button 11 . 0x37
Button 12 Backspace 0x2A

How Modifiers Work

When you press a Naga button:

  1. The daemon queries the current modifier state from the system
  2. Creates a synthetic keyboard event with your key
  3. Attaches the current modifiers (Shift, Cmd, Opt, Ctrl)
  4. Posts the combined event

Example: Hold Shift on keyboard + press Naga button 1 = System receives Shift+1 = !

Building

cd razer-naga-relay
swift build -c release

Usage

# Normal operation
.build/release/nagarelay

# With debug logging
.build/release/nagarelay --debug

# With device seizure (recommended)
sudo .build/release/nagarelay

Requirements

  • macOS 12.0+
  • Swift 6.0+ (Xcode 16+ or Swift toolchain)
  • Accessibility permission (System Preferences > Privacy & Security > Accessibility)
  • Optional: sudo for exclusive device seizure

Supported Devices

Device Connection Vendor ID Product ID
Razer Naga Trinity USB 0x1532 0x0067
Razer Naga V2 HyperSpeed USB 0x1532 0x00B4
Razer Naga V2 HyperSpeed Bluetooth 0x068E 0x00B5

Testing

Run unit tests:

swift test

Run specific suite:

swift test --filter KeyMappingTests

What's Tested

  • Whitelist enforcement (all 12 inputs)
  • HID-to-virtual keycode mappings
  • Modifier description helpers
  • Error formatting

How IOHIDManager Works

Naga Relay uses Apple's IOHIDManager API for device-specific input capture:

  1. Device Matching: Filters by Razer VendorID and Naga ProductIDs
  2. Device Seizure: Opens device with kIOHIDOptionsTypeSeizeDevice for exclusive access
  3. Callback Registration: Receives raw HID values via input value callback
  4. Whitelist Filtering: Only 12 inputs pass through; all others dropped
  5. Event Synthesis: Creates CGEvent with current modifier state and posts to system

This approach cannot see your main keyboard - it only receives events from the Naga device.

Bluetooth Notes

Bluetooth Naga devices bypass IOHIDManager seizure, causing duplicate events. Naga Relay handles this with:

  1. Deduplication: Ignores identical events within 50ms window
  2. Event Tap: Blocks original Bluetooth HID events after relaying our version
  3. Event Marking: Our relayed events are marked so the tap lets them through

Virtualization Notes

USB HID passthrough is not supported on Apple Silicon VMs:

  • Tart/UTM: Apple Virtualization.framework lacks USB passthrough
  • VMware Fusion: HID devices not reliably passed through on ARM64

Hardware integration tests must run directly on host macOS with physical Naga connected.

Files

razer-naga-relay/
+-- Package.swift              # Swift Package Manager config
+-- config.json                # Reference config (not loaded at runtime)
+-- README.md
+-- SECURITY-AUDIT.md          # Full security analysis
+-- SETUP.md                   # Setup and testing guide
+-- Sources/
|   +-- NagaKeyRelay/
|   |   +-- main.swift         # CLI entry point
|   +-- NagaKeyRelayLib/
|       +-- KeyMapping.swift   # HID to virtual keycode mappings
|       +-- NagaHIDRelay.swift # IOHIDManager relay engine
+-- Tests/NagaKeyRelayTests/
    +-- KeyMappingTests.swift  # Whitelist enforcement tests
    +-- NagaHIDRelayTests.swift # Helper function tests

Security Model

Aspect This Implementation
Main keyboard visibility Cannot see any
Attack surface Low (device-specific)
Modifier tracking On-demand query
Whitelist Mandatory (12 inputs)
Device isolation Complete

See SECURITY-AUDIT.md for a full line-by-line security analysis.

About

Razer Naga Relay • macOS Hotfix for Modifier Keys

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors