210 lines
9.2 KiB
Rust
210 lines
9.2 KiB
Rust
//! Button-to-USB mapping for CMDR Joystick
|
|
//!
|
|
//! This module defines the hardware button indices (matrix layout and extras)
|
|
//! and their mapping to USB joystick button numbers and HAT directions.
|
|
//! The mapping is consumed by the button processing and USB report layers.
|
|
//!
|
|
//! Notes
|
|
//! - USB buttons are 1-based (USB_BUTTON_1..=USB_BUTTON_32)
|
|
//! - HAT is represented by four symbolic constants: up/right/down/left
|
|
//! - Some buttons enable a “long press” variant via `usb_button_long`
|
|
|
|
// HW Button index map:
|
|
// ---------------------------------------------------------------
|
|
// | 0 L| 1 U| 25 U | | 2 | | 26 U | 4 U| 3 L|
|
|
// ---------------------------------------------------------------
|
|
// | | 5 | 6 | 7 | | 12 | 11 | 10 | |
|
|
// | |
|
|
// | | 8 | | 13 | |
|
|
// | | 9 | | 14 | |
|
|
// | X1/Y1 X2/Y2 |
|
|
// | | 16 | | 21 | |
|
|
// | | 19 | 15 | 17 | | 24 | 20 | 22 | |
|
|
// | | 18 | | 23 | |
|
|
// ---------------------------------------------------------------
|
|
|
|
// ==================== BUTTON INDICES ====================
|
|
pub const BUTTON_FRONT_LEFT_LOWER: usize = 0;
|
|
pub const BUTTON_FRONT_LEFT_UPPER: usize = 1;
|
|
pub const BUTTON_FRONT_LEFT_EXTRA: usize = 25;
|
|
pub const BUTTON_FRONT_CONFIG: usize = 2;
|
|
pub const BUTTON_FRONT_RIGHT_LOWER: usize = 3;
|
|
pub const BUTTON_FRONT_RIGHT_UPPER: usize = 4;
|
|
pub const BUTTON_FRONT_RIGHT_EXTRA: usize = 26;
|
|
pub const BUTTON_TOP_LEFT_LOW: usize = 5;
|
|
pub const BUTTON_TOP_LEFT_HIGH: usize = 6;
|
|
pub const BUTTON_TOP_LEFT_MODE: usize = 7;
|
|
pub const BUTTON_TOP_LEFT_UP: usize = 8;
|
|
pub const BUTTON_TOP_LEFT_DOWN: usize = 9;
|
|
pub const BUTTON_TOP_LEFT_HAT: usize = 15;
|
|
pub const BUTTON_TOP_LEFT_HAT_UP: usize = 16;
|
|
pub const BUTTON_TOP_LEFT_HAT_RIGHT: usize = 17;
|
|
pub const BUTTON_TOP_LEFT_HAT_DOWN: usize = 18;
|
|
pub const BUTTON_TOP_LEFT_HAT_LEFT: usize = 19;
|
|
pub const BUTTON_TOP_RIGHT_LOW: usize = 10;
|
|
pub const BUTTON_TOP_RIGHT_HIGH: usize = 11;
|
|
pub const BUTTON_TOP_RIGHT_MODE: usize = 12;
|
|
pub const BUTTON_TOP_RIGHT_UP: usize = 13;
|
|
pub const BUTTON_TOP_RIGHT_DOWN: usize = 14;
|
|
pub const BUTTON_TOP_RIGHT_HAT: usize = 20;
|
|
pub const BUTTON_TOP_RIGHT_HAT_UP: usize = 21;
|
|
pub const BUTTON_TOP_RIGHT_HAT_RIGHT: usize = 22;
|
|
pub const BUTTON_TOP_RIGHT_HAT_DOWN: usize = 23;
|
|
pub const BUTTON_TOP_RIGHT_HAT_LEFT: usize = 24;
|
|
|
|
// ==================== USB BUTTON MAPPING ====================
|
|
pub const USB_BUTTON_1: usize = 1;
|
|
pub const USB_BUTTON_2: usize = 2;
|
|
pub const USB_BUTTON_3: usize = 3;
|
|
pub const USB_BUTTON_4: usize = 4;
|
|
pub const USB_BUTTON_5: usize = 5;
|
|
pub const USB_BUTTON_6: usize = 6;
|
|
pub const USB_BUTTON_7: usize = 7;
|
|
pub const USB_BUTTON_8: usize = 8;
|
|
pub const USB_BUTTON_9: usize = 9;
|
|
pub const USB_BUTTON_10: usize = 10;
|
|
pub const USB_BUTTON_11: usize = 11;
|
|
pub const USB_BUTTON_12: usize = 12;
|
|
pub const USB_BUTTON_13: usize = 13;
|
|
pub const USB_BUTTON_14: usize = 14;
|
|
pub const USB_BUTTON_15: usize = 15;
|
|
pub const USB_BUTTON_16: usize = 16;
|
|
pub const USB_BUTTON_17: usize = 17;
|
|
pub const USB_BUTTON_18: usize = 18;
|
|
pub const USB_BUTTON_19: usize = 19;
|
|
pub const USB_BUTTON_20: usize = 20;
|
|
pub const USB_BUTTON_21: usize = 21;
|
|
pub const USB_BUTTON_22: usize = 22;
|
|
pub const USB_BUTTON_23: usize = 23;
|
|
pub const USB_BUTTON_24: usize = 24;
|
|
pub const USB_BUTTON_25: usize = 25;
|
|
pub const USB_BUTTON_26: usize = 26;
|
|
pub const USB_BUTTON_27: usize = 27;
|
|
pub const USB_BUTTON_28: usize = 28;
|
|
pub const USB_BUTTON_29: usize = 29;
|
|
pub const USB_BUTTON_30: usize = 30;
|
|
pub const USB_BUTTON_31: usize = 31;
|
|
pub const USB_BUTTON_32: usize = 32;
|
|
|
|
pub const USB_HAT_UP: usize = 33;
|
|
pub const USB_HAT_RIGHT: usize = 34;
|
|
pub const USB_HAT_DOWN: usize = 35;
|
|
pub const USB_HAT_LEFT: usize = 36;
|
|
|
|
use crate::buttons::Button;
|
|
|
|
/// Configure USB button mappings for all buttons.
|
|
///
|
|
/// Populates per-button fields used by the button state machine:
|
|
/// - `usb_button`: regular (short-press) USB button assignment
|
|
/// - `usb_button_long`: long-press USB button assignment (if enabled)
|
|
/// - `enable_long_press` and `enable_long_hold`: behavior flags for timing
|
|
pub fn configure_button_mappings(buttons: &mut [Button]) {
|
|
buttons[BUTTON_FRONT_LEFT_LOWER].usb_button = USB_BUTTON_29;
|
|
buttons[BUTTON_FRONT_LEFT_UPPER].usb_button = USB_BUTTON_28;
|
|
buttons[BUTTON_FRONT_CONFIG].usb_button = USB_BUTTON_32; // Button used as global config.
|
|
buttons[BUTTON_FRONT_CONFIG].usb_button_long = USB_BUTTON_3;
|
|
buttons[BUTTON_FRONT_CONFIG].enable_long_press = true;
|
|
|
|
buttons[BUTTON_FRONT_RIGHT_LOWER].usb_button = USB_BUTTON_2;
|
|
buttons[BUTTON_FRONT_RIGHT_UPPER].usb_button = USB_BUTTON_1;
|
|
buttons[BUTTON_TOP_LEFT_LOW].usb_button = USB_BUTTON_4;
|
|
buttons[BUTTON_TOP_LEFT_LOW].usb_button_long = USB_BUTTON_5;
|
|
buttons[BUTTON_TOP_LEFT_LOW].enable_long_press = true;
|
|
buttons[BUTTON_TOP_LEFT_LOW].enable_long_hold = true;
|
|
|
|
buttons[BUTTON_TOP_LEFT_HIGH].usb_button = USB_BUTTON_6;
|
|
buttons[BUTTON_TOP_LEFT_HIGH].usb_button_long = USB_BUTTON_7;
|
|
buttons[BUTTON_TOP_LEFT_HIGH].enable_long_press = true;
|
|
|
|
buttons[BUTTON_TOP_LEFT_MODE].usb_button = 0;
|
|
buttons[BUTTON_TOP_LEFT_UP].usb_button = USB_BUTTON_12;
|
|
buttons[BUTTON_TOP_LEFT_UP].usb_button_long = USB_BUTTON_13;
|
|
buttons[BUTTON_TOP_LEFT_UP].enable_long_press = true;
|
|
|
|
buttons[BUTTON_TOP_LEFT_DOWN].usb_button = USB_BUTTON_16;
|
|
buttons[BUTTON_TOP_LEFT_DOWN].usb_button_long = USB_BUTTON_17;
|
|
buttons[BUTTON_TOP_LEFT_DOWN].enable_long_press = true;
|
|
buttons[BUTTON_TOP_LEFT_DOWN].enable_long_hold = true;
|
|
|
|
buttons[BUTTON_TOP_RIGHT_LOW].usb_button = USB_BUTTON_10;
|
|
buttons[BUTTON_TOP_RIGHT_LOW].usb_button_long = USB_BUTTON_11;
|
|
buttons[BUTTON_TOP_RIGHT_LOW].enable_long_press = true;
|
|
|
|
buttons[BUTTON_TOP_RIGHT_HIGH].usb_button = USB_BUTTON_8;
|
|
buttons[BUTTON_TOP_RIGHT_HIGH].usb_button_long = USB_BUTTON_9;
|
|
buttons[BUTTON_TOP_RIGHT_HIGH].enable_long_press = true;
|
|
|
|
buttons[BUTTON_TOP_RIGHT_MODE].usb_button = 0;
|
|
buttons[BUTTON_TOP_RIGHT_UP].usb_button = USB_BUTTON_14;
|
|
buttons[BUTTON_TOP_RIGHT_UP].usb_button_long = USB_BUTTON_15;
|
|
buttons[BUTTON_TOP_RIGHT_UP].enable_long_press = true;
|
|
|
|
buttons[BUTTON_TOP_RIGHT_DOWN].usb_button = USB_BUTTON_18;
|
|
buttons[BUTTON_TOP_RIGHT_DOWN].usb_button_long = USB_BUTTON_19;
|
|
buttons[BUTTON_TOP_RIGHT_DOWN].enable_long_press = true;
|
|
|
|
buttons[BUTTON_TOP_LEFT_HAT].usb_button = USB_BUTTON_20;
|
|
buttons[BUTTON_TOP_LEFT_HAT].usb_button_long = USB_BUTTON_21;
|
|
buttons[BUTTON_TOP_LEFT_HAT].enable_long_press = true;
|
|
|
|
buttons[BUTTON_TOP_LEFT_HAT_UP].usb_button = USB_BUTTON_22;
|
|
buttons[BUTTON_TOP_LEFT_HAT_RIGHT].usb_button = USB_BUTTON_23;
|
|
buttons[BUTTON_TOP_LEFT_HAT_DOWN].usb_button = USB_BUTTON_24;
|
|
buttons[BUTTON_TOP_LEFT_HAT_LEFT].usb_button = USB_BUTTON_25;
|
|
buttons[BUTTON_TOP_RIGHT_HAT].usb_button = USB_BUTTON_26;
|
|
buttons[BUTTON_TOP_RIGHT_HAT].usb_button_long = USB_BUTTON_27;
|
|
buttons[BUTTON_TOP_RIGHT_HAT].enable_long_press = true;
|
|
|
|
buttons[BUTTON_TOP_RIGHT_HAT_UP].usb_button = USB_HAT_UP;
|
|
buttons[BUTTON_TOP_RIGHT_HAT_RIGHT].usb_button = USB_HAT_RIGHT;
|
|
buttons[BUTTON_TOP_RIGHT_HAT_DOWN].usb_button = USB_HAT_DOWN;
|
|
buttons[BUTTON_TOP_RIGHT_HAT_LEFT].usb_button = USB_HAT_LEFT;
|
|
buttons[BUTTON_FRONT_LEFT_EXTRA].usb_button = USB_BUTTON_30;
|
|
buttons[BUTTON_FRONT_RIGHT_EXTRA].usb_button = USB_BUTTON_31;
|
|
}
|
|
|
|
#[cfg(all(test, feature = "std"))]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::buttons::{Button, TOTAL_BUTTONS};
|
|
|
|
#[test]
|
|
fn front_buttons_have_expected_mappings() {
|
|
// Front panel buttons map to the expected USB button ids.
|
|
let mut buttons = [Button::default(); TOTAL_BUTTONS];
|
|
configure_button_mappings(&mut buttons);
|
|
|
|
assert_eq!(buttons[BUTTON_FRONT_LEFT_LOWER].usb_button, USB_BUTTON_29);
|
|
assert_eq!(buttons[BUTTON_FRONT_RIGHT_UPPER].usb_button, USB_BUTTON_1);
|
|
assert_eq!(buttons[BUTTON_FRONT_CONFIG].usb_button_long, USB_BUTTON_3);
|
|
}
|
|
|
|
#[test]
|
|
fn long_press_flags_set_correctly() {
|
|
// Long-press flags are configured for buttons that need them at runtime.
|
|
let mut buttons = [Button::default(); TOTAL_BUTTONS];
|
|
configure_button_mappings(&mut buttons);
|
|
|
|
assert!(buttons[BUTTON_TOP_LEFT_LOW].enable_long_press);
|
|
assert!(buttons[BUTTON_TOP_LEFT_LOW].enable_long_hold);
|
|
assert!(buttons[BUTTON_TOP_RIGHT_LOW].enable_long_press);
|
|
assert!(!buttons[BUTTON_TOP_RIGHT_LOW].enable_long_hold);
|
|
}
|
|
|
|
#[test]
|
|
fn hat_buttons_map_to_expected_ids() {
|
|
// Hat direction buttons should map to the numerical HID hat constants.
|
|
let mut buttons = [Button::default(); TOTAL_BUTTONS];
|
|
configure_button_mappings(&mut buttons);
|
|
|
|
assert_eq!(buttons[BUTTON_TOP_RIGHT_HAT_UP].usb_button, USB_HAT_UP);
|
|
assert_eq!(
|
|
buttons[BUTTON_TOP_RIGHT_HAT_RIGHT].usb_button,
|
|
USB_HAT_RIGHT
|
|
);
|
|
assert_eq!(buttons[BUTTON_TOP_RIGHT_HAT_DOWN].usb_button, USB_HAT_DOWN);
|
|
assert_eq!(buttons[BUTTON_TOP_RIGHT_HAT_LEFT].usb_button, USB_HAT_LEFT);
|
|
}
|
|
}
|