//! 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); } }