- Added support for Single, Long, and Double press actions in libazeron. - Mapped Cyborg surgical command IDs (0x20F6, 0x20F8, 0x204A). - Updated azeron-cli to support --long and --double mapping flags. - Updated protocol documentation with newly discovered Cyborg commands. - Added TODO.md for remaining joystick and timing tasks.
479 lines
14 KiB
Markdown
479 lines
14 KiB
Markdown
# 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 (except offsets)
|
|
|
|
### Packet Format
|
|
|
|
All configuration packets follow this structure:
|
|
|
|
```
|
|
Byte 0: Flags/Type (0x00=request, 0x01=response)
|
|
Byte 1: Reserved/Length (0x3a for config writes)
|
|
Bytes 2-3: Command ID (big-endian)
|
|
Bytes 4-5: Operation type and parameters
|
|
Bytes 6-63: Data payload (varies by command)
|
|
```
|
|
|
|
### Command Reference (Cyborg Model)
|
|
|
|
#### 0x122a - Get Status (Heartbeat)
|
|
**Purpose:** Periodic device status check.
|
|
|
|
#### 0x2000 - Set Global Settings
|
|
**Purpose:** Configure timing delays for actions.
|
|
- **Bytes 60-61 (Payload):** Long Press Delay (ms, big-endian, e.g., `01f4` = 500ms)
|
|
- **Bytes 62-63 (Payload):** Double Press Delay (ms, big-endian, e.g., `00c8` = 200ms)
|
|
|
|
#### 0x20F6 - Set Single Press
|
|
#### 0x20F8 - Set Long Press
|
|
#### 0x204A - Set Double Press
|
|
**Purpose:** Surgical update for a specific button action.
|
|
- **Byte 10 (Payload):** Button ID (0-based)
|
|
- **Byte 22 (Payload):** Key Type (0xf0 = Keyboard)
|
|
- **Byte 23 (Payload):** Key Code (HID)
|
|
|
|
#### 0x204B - Commit Button Changes
|
|
**Purpose:** Makes surgical updates (`0x20F6/F8/4A`) active.
|
|
|
|
#### 0x26EC - Bulk Write Profile
|
|
**Purpose:** Writes a complete profile block.
|
|
- **Byte 3 (Payload):** Joystick Mode (0x00 = Analog, 0x01 = WASD)
|
|
- **Byte 8 (Payload):** Stick Angle (degrees)
|
|
|
|
#### 0x26ED - Commit Bulk Write
|
|
**Purpose:** Persists bulk changes to EEPROM.
|
|
|
|
### Command Reference (Classic Model)
|
|
|
|
*Note: These commands are used by older Azeron versions and may differ from Cyborg.*
|
|
|
|
#### 0x12C8 - Read Configuration
|
|
**Purpose:** Read full device configuration.
|
|
|
|
#### 0x26FC - Write Profile Data
|
|
**Purpose:** Write profile configuration to device (does not persist).
|
|
|
|
#### 0x26FD - Save Profile
|
|
**Purpose:** Commit profile to device EEPROM.
|
|
|
|
## 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
|
|
|
|
```wireshark
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```c
|
|
// 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
|
|
|
|
- USB HID Specification: https://www.usb.org/hid
|
|
- libusb Documentation: https://libusb.info
|
|
- Azeron Cyborg Product Page: https://azeron.net
|
|
- Wireshark USB Analysis: https://wiki.wireshark.org/USB
|
|
|
|
## 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:**
|
|
```bash
|
|
USBPcapCMD.exe -d \\.\USBPcap6 -o capture.pcap -s 64
|
|
```
|
|
|
|
**Analysis Filters:**
|
|
```wireshark
|
|
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. |