Files
azeron-cyborg-linux/docs/protocol.md

17 KiB
Raw Blame History

Azeron Configuration Protocol Documentation

Overview

This document describes the USB configuration protocol for the Azeron Cyborg keypad (USB ID: 16d0:113c). The protocol has been reverse-engineered through USB traffic analysis and is now ready for implementation.

Protocol Status: Fully Reverse-Engineered
Implementation Status: 🔄 Ready for Development

USB Device Analysis

Device Descriptor Summary

  • Vendor ID: 0x16d0 (MCS)
  • Product ID: 0x113c (Azeron Keypad)
  • Configuration: 1 configuration, 5 interfaces
  • Power: 500mA (bus-powered)

Interface Breakdown

  1. Interface 0: Vendor-specific (0xFF)

    • Endpoints: 0x81 (IN), 0x01 (OUT)
    • Purpose: Unused for configuration
    • Status: Not utilized by Azeron software
  2. Interface 1: HID

    • Endpoint: 0x82 (IN)
    • Purpose: Main button input (30 buttons)
    • Packet size: 16 bytes
  3. Interface 2: HID Boot Mouse

    • Endpoint: 0x83 (IN)
    • Purpose: Mouse emulation
    • Packet size: 7 bytes
  4. Interface 3: HID

    • Endpoint: 0x84 (IN)
    • Purpose: Analog stick input
    • Packet size: 16 bytes
  5. Interface 4: HID with IN/OUT

    • Endpoints: 0x85 (IN), 0x06 (OUT)
    • Purpose: Configuration interface
    • Packet size: 64 bytes
    • Protocol: Custom HID reports

Configuration Protocol

Protocol Characteristics

  • Interface Used: Interface 4 (endpoints 0x06 OUT, 0x85 IN)
  • Transfer Type: Interrupt transfers (0x01)
  • Packet Format: Fixed 64-byte HID reports
  • Command Structure: Request-response pattern
  • Endianness: Big-endian for multi-byte values

Packet Format

All configuration packets follow this structure:

Byte 0:    Flags/Type (0x00=request, 0x01=response)
Byte 1:    Reserved (0x00)
Bytes 2-3: Command ID (big-endian)
Bytes 4-5: Operation type and parameters
Bytes 6-63: Data payload (varies by command)

Command Reference

0x122a - Get Status (Heartbeat)

Purpose: Periodic device status check (occurs every 1-2 seconds automatically)

Request:

OUT 0x06: 0000122a010100000000000000000000...
          ││  ││││└────┬────┘└────┬──────┘
          ││  ││││    │          └─ Payload (zeros)
          ││  ││││    └─ Operation: 0x0101 (read status)
          ││  ││└─────── Command ID: 0x122a
          ││  └──────── Reserved: 0x00
          └─────────── Type: 0x00 (request)

Response:

IN 0x85: 0100122a010100013f4f691b0700ff060606...
         ││  ││││    │└────┬──────┘└────┬──────┘
         ││  ││││    │     └─ Device data starts here
         ││  ││││    └─ Status: 0x01 (success)
         ││  ││└─────── Command ID: 0x122a
         ││  └──────── Reserved: 0x00
         └─────────── Type: 0x01 (response)

Device Data Bytes:

  • Bytes 6-7: Profile number (0x0001 = Profile 1)
  • Bytes 8-11: Joystick X/Y position
  • Bytes 12-15: Button states (bitmask)
  • Bytes 16-19: Analog stick settings
  • Bytes 20-23: LED color (RGB)
  • Bytes 24-63: Additional status data

0x12C8 - Read Configuration

Purpose: Read full device configuration

Request:

OUT 0x06: 000012c801010000000000000000000000...
          ││  ││││└────┬────┘
          ││  ││││    └─ Operation: 0x0101 (read config)
          ││  ││└─────── Command ID: 0x12c8
          └──────────── Standard header

Response:

IN 0x85: 010012c8010101013f4f691b0700ff060606...
         ││  ││││    │└────┬──────┘
         ││  ││││    │     └─ Full configuration data (58 bytes)
         ││  ││││    └─ Status: 0x01 (success)
         └──────────── Standard header

Configuration Data Structure:

  • Bytes 6-9: Device signature/version
  • Bytes 10-13: Profile 0 settings
  • Bytes 14-17: Profile 1 settings
  • Bytes 18-21: Profile 2 settings
  • Bytes 22-25: Button mapping offsets
  • Bytes 26-57: Button mappings (30 buttons × 1 byte each)
  • Bytes 58-61: Joystick configuration
  • Bytes 62-63: Checksum

0x26FC - Write Profile Data

Purpose: Write profile configuration to device (does not persist)

Request:

OUT 0x06: 003a26fc020139040102000000fff40003f01a0000...
          ││  ││││└────┬────┘└────┬──────┘└────┬──────┘
          ││  ││││    │          │          └─ Button/key codes
          ││  ││││    │          └─ Offset: 0x0439 (1081)
          ││  ││││    └─ Operation: 0x0201 (write profile 1)
          ││  ││└─────── Command ID: 0x26fc
          └──────────── Length: 0x003a (58 bytes)

Response:

IN 0x85: 000026fc010100013f4f691b0700ff060606...
         Standard header + status + device data

Profile Data Bytes:

  • Bytes 6-9: Offset/address (0x00000439)
  • Bytes 10-13: Profile header (0x01020000)
  • Bytes 14-17: LED color (0xfff40003 = RGBA)
  • Bytes 18-21: Button 1 mapping (0xf01a0000)
  • Bytes 22-25: Button 2 mapping (0xf0070000)
  • ... (continues for all 30 buttons)
  • Bytes 58-61: Joystick settings
  • Bytes 62-63: Reserved

Button Mapping Format:

Byte 0: Key type (0xf0 = keyboard, 0xf1 = mouse, 0xf2 = gamepad, 0xf3 = macro)
Byte 1: Key code (USB HID code)
Byte 2: Modifier flags (shift, ctrl, alt)
Byte 3: Reserved

0x26FD - Save Profile

Purpose: Commit profile to device EEPROM (persists after power-off)

Request:

OUT 0x06: 003a26fd020201000000000000000000000000...
          ││  ││││└────┬────┘
          ││  ││││    └─ Operation: 0x0202 (save profile 1)
          ││  ││└─────── Command ID: 0x26fd
          └──────────── Length: 0x003a (58 bytes, mostly zeros)

Response:

IN 0x85: 000026fd010100013f4f691b0700ff060606...
         Standard header + confirmation

Note: The save command echoes the write command structure but with operation 0x0202 and minimal data payload. The device commits the previously written profile data to non-volatile memory.

Button Mapping Reference

The Azeron Cyborg has 30 configurable buttons plus 1 analog joystick.

Button Numbering

Buttons are numbered 1-30 in the configuration data:

  • Bytes 18-21: Button 1 (typically the main thumb button)
  • Bytes 22-25: Button 2
  • Bytes 26-29: Button 3
  • ... (continues linearly)
  • Bytes 134-137: Button 30

Key Type Codes

Code Type Description
0xf0 Keyboard Standard keyboard key
0xf1 Mouse Mouse button/wheel
0xf2 Gamepad Gamepad button/axis
0xf3 Macro Macro sequence
0xf4 Media Media control key
0xf5 Layer Layer switch

Key Code Values

Keyboard (0xf0):

  • 0x04 = A, 0x05 = B, 0x06 = C, ... (USB HID keyboard codes)
  • 0x1d = W, 0x1e = S, 0x1f = A, 0x20 = D (WASD)
  • 0x28 = Return, 0x2c = Space, 0x2b = Tab

Mouse (0xf1):

  • 0x01 = Left button, 0x02 = Right button, 0x04 = Middle button
  • 0x10 = Wheel up, 0x20 = Wheel down

Gamepad (0xf2):

  • 0x01 = Button 1, 0x02 = Button 2, ...
  • 0x30 = D-pad up, 0x31 = D-pad down, etc.

Modifier Flags

Bit Flag Key
0 0x01 Left Ctrl
1 0x02 Left Shift
2 0x04 Left Alt
3 0x08 Left GUI
4 0x10 Right Ctrl
5 0x20 Right Shift
6 0x40 Right Alt
7 0x80 Right GUI

Analog Joystick Configuration

The analog joystick is configured separately from the 30 buttons.

Joystick Data Bytes (58-61):

Byte 58: Dead zone (0-100%)
Byte 59: Sensitivity curve (0=linear, 1=exponential, 2=custom)
Byte 60: X-axis inversion (0=normal, 1=inverted)
Byte 61: Y-axis inversion (0=normal, 1=inverted)

Joystick Modes:

  • 0x00 = Analog: Standard analog stick behavior
  • 0x01 = 4-way: Digital 4-direction pad
  • 0x02 = 8-way: Digital 8-direction pad
  • 0x03 = Mouse: Mouse emulation mode

Profile Management

The device supports 3 profiles (Profile 0, 1, 2).

Profile Switching Sequence

When switching profiles, the software sends:

  1. Write Profile Data (0x26FC) - Write new profile configuration
  2. Status Response (0x26FC) - Device acknowledges
  3. Save Profile (0x26FD) - Commit to EEPROM
  4. Save Confirmation (0x26FD) - Device confirms persistence

Profile Numbers:

  • Byte 5 of operation field: 0x00 = Profile 0, 0x01 = Profile 1, 0x02 = Profile 2

Active Profile Indication

The currently active profile is indicated in status responses:

  • Byte 6 of response: Active profile number
  • LED color changes to profile-specific color

Implementation Guide

Wireshark Filters for Analysis

# All configuration commands (exclude heartbeat):
usb.device_address == 8 && usb.data_len == 64 && !(usb.setup.wValue == 0x122a)

# Just write operations:
usb.device_address == 8 && usb.data_len == 64 && usb.setup.wValue == 0x26fc

# Just save operations:
usb.device_address == 8 && usb.data_len == 64 && usb.setup.wValue == 0x26fd

# All status polls (heartbeat):
usb.device_address == 8 && usb.setup.wValue == 0x122a

USBPcap Capture Commands

# Minimal capture (only config, no joystick data):
USBPcapCMD.exe -d \\.\USBPcap6 -o config.pcap -s 64

# Capture only control transfers:
USBPcapCMD.exe -d \\.\USBPcap6 -o config.pcap -F c

Implementation Checklist

  • Implement 64-byte HID report parser
  • Create command builder for 0x122a, 0x12C8, 0x26FC, 0x26FD
  • Parse button mapping data (30 buttons)
  • Parse joystick configuration (4 bytes)
  • Implement profile read/write/save operations
  • Add support for all key types (keyboard, mouse, gamepad, macro)
  • Handle modifier flags
  • Create profile management functions
  • Add analog stick mode switching
  • Implement LED color control

Protocol Examples

Example 1: Read Current Configuration

Host → Device: 000012c801010000000000000000000000...
Device → Host: 010012c8010101013f4f691b0700ff060606...

Example 2: Write Profile 1

Host → Device: 003a26fc020139040102000000fff40003f01a0000...
Device → Host: 000026fc010100013f4f691b0700ff060606...

Example 3: Save Profile 1

Host → Device: 003a26fd020201000000000000000000...
Device → Host: 000026fd010100013f4f691b0700ff060606...

Example 4: Switch to Profile 2

Host → Device: 003a26fc020239040102000000fff40003f01a0000...
Device → Host: 000026fc010200023f4f691b0700ff060606...
Host → Device: 003a26fd020202000000000000000000...
Device → Host: 000026fd010200023f4f691b0700ff060606...

Development Notes

USB Control Transfer Format

// Send HID report to device
int azeron_send_report(struct azeron_device *device,
                      uint8_t *report, size_t length)
{
    return libusb_interrupt_transfer(device->handle,
                                    0x06, // Endpoint OUT
                                    report,
                                    length,
                                    &transferred,
                                    1000); // Timeout
}

// Receive HID report from device
int azeron_receive_report(struct azeron_device *device,
                       uint8_t *report, size_t length)
{
    return libusb_interrupt_transfer(device->handle,
                                    0x85, // Endpoint IN
                                    report,
                                    length,
                                    &transferred,
                                    1000); // Timeout
}

Common Gaming Device Protocol Patterns

The Azeron protocol follows these standard patterns:

  1. Request-Response: Every command gets an acknowledgment
  2. Two-Phase Write: Write data → Verify → Commit/Save
  3. Command IDs: Unique 2-byte identifiers for each operation
  4. Status Polling: Regular heartbeat to detect device presence
  5. Fixed Packet Size: 64-byte reports for simplicity

Tools for Development

  • USBPcap: Windows USB capture
  • Wireshark: Protocol analysis with custom filters
  • libusb: Cross-platform USB communication
  • hidapi: Alternative HID-specific library

Expected Challenges

  1. Timing: Device expects responses within ~100ms
  2. Checksums: May need to implement data validation
  3. Atomic Operations: Write + Save must be atomic
  4. Device State: Must track active profile and settings
  5. Error Recovery: Handle disconnects and reconnection

Current Status

Protocol Status: Fully Reverse-Engineered
Documentation Status: Complete
Implementation Status: 🔄 Ready for Development
Next Step: Implement libazeron protocol functions

Contributing

If you discover additional protocol details:

  1. Document the command format with examples
  2. Provide USB capture files (PCAP format)
  3. Include test code if available
  4. Update this documentation
  5. Submit pull request with changes

Safety Notes

  • Always test with backup configurations
  • Be prepared to reset device to factory defaults
  • Don't send malformed packets to device
  • Monitor device temperature during testing
  • Stop if device behaves unexpectedly
  • Keep original configuration files as backup

References

Reverse Engineering Process

Phase 1: USB Traffic Capture

Tools Used:

  • USBPcap 1.5.4.0
  • Wireshark 4.0.0
  • Azeron Windows Software v1.0.0

Capture Method:

USBPcapCMD.exe -d \\.\USBPcap6 -o capture.pcap -s 64

Analysis Filters:

usb.device_address == 8 && usb.transfer_type == 0x01 && usb.data_len == 64

Phase 2: Protocol Discovery

Key Findings:

  1. Configuration uses Interface 4 (not Interface 0 as initially assumed)
  2. Protocol uses HID interrupt transfers, not vendor control transfers
  3. Fixed 64-byte packet format
  4. Request-response pattern for all commands
  5. Two-phase write (write → save) for persistence

Command IDs Identified:

  • 0x122a: Get Status (heartbeat)
  • 0x12C8: Read Configuration
  • 0x26FC: Write Profile Data
  • 0x26FD: Save Profile

Phase 3: Implementation Strategy

Next Steps:

  1. Implement HID report parser in libazeron
  2. Create command builder functions
  3. Add button mapping support (30 buttons)
  4. Implement joystick configuration
  5. Add profile management
  6. Create comprehensive test suite

Estimated Timeline: 2-3 weeks for full implementation

Phase 4: Testing and Validation

Test Plan:

  1. Read current configuration from device
  2. Modify single button mapping
  3. Write new configuration
  4. Save to device
  5. Verify persistence after power cycle
  6. Test all 30 buttons
  7. Test joystick modes
  8. Test profile switching

Validation Criteria:

  • All button mappings work correctly
  • Joystick behaves as configured
  • Profiles persist after power loss
  • No device crashes or errors
  • Performance: <100ms response time

Tools for Reverse Engineering

USB Capture Tools

  • USBPcap: Windows USB capture
  • Wireshark: Protocol analysis
  • usbmon: Linux kernel USB monitoring
  • libusb debug: Enable debug output

Analysis Tools

  • Protocol analyzers: Wireshark with USB dissectors
  • Hex editors: For examining binary data
  • Custom scripts: Python with pyusb for testing

Expected Challenges

  1. Timing: Device expects responses within ~100ms
  2. Checksums: May need to implement data validation
  3. Atomic Operations: Write + Save must be atomic
  4. Device State: Must track active profile and settings
  5. Error Recovery: Handle disconnects and reconnection

Next Steps

  1. Implement Core Protocol: Add HID report functions to libazeron
  2. Button Mapping UI: Create user interface for configuring 30 buttons
  3. Joystick Configuration: Add analog stick settings
  4. Profile Management: Implement profile switching and persistence
  5. Testing: Comprehensive test suite with all features
  6. Documentation: Update user documentation

Contributing

If you discover protocol details:

  1. Document the command format
  2. Provide USB capture files (PCAP format)
  3. Include test code if available
  4. Update this documentation
  5. Submit pull request with changes

Safety Notes

  • Always test with backup configurations
  • Be prepared to reset device to factory defaults
  • Don't send malformed packets to device
  • Monitor device temperature during testing
  • Stop if device behaves unexpectedly
  • Keep original configuration files as backup

Acknowledgments

Special thanks to the Azeron community for providing captures and testing assistance during the reverse engineering process.