#![allow(non_snake_case)]
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct XInputGamepad {
pub(crate) buttons: u16,
pub(crate) left_trigger: u8,
pub(crate) right_trigger: u8,
pub(crate) thumb_lx: i16,
pub(crate) thumb_ly: i16,
pub(crate) thumb_rx: i16,
pub(crate) thumb_ry: i16,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct XInputState {
pub(crate) packet_number: u32,
pub(crate) gamepad: XInputGamepad,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct XInputVibration {
pub(crate) left_motor: u16,
pub(crate) right_motor: u16,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct XInputCapabilities {
pub(crate) kind: u8,
pub(crate) sub_type: u8,
pub(crate) flags: u16,
pub(crate) gamepad: XInputGamepad,
pub(crate) vibration: XInputVibration,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct XInputCapabilitiesEx {
pub(crate) capabilities: XInputCapabilities,
pub(crate) vendor_id: u16,
pub(crate) product_id: u16,
pub(crate) product_version: u16,
pub(crate) unknown1: u16,
pub(crate) unknown2: u32,
}
#[cfg(windows)]
pub(crate) const GET_CAPABILITIES_EX_ORDINAL: usize = 108;
#[cfg(windows)]
pub(crate) type XInputGetCapabilitiesExFn =
unsafe extern "system" fn(u32, u32, u32, *mut XInputCapabilitiesEx) -> u32;
pub(crate) const XUSER_MAX_COUNT: u32 = 4;
#[cfg(windows)]
pub(crate) const ERROR_SUCCESS: u32 = 0;
pub(crate) const ERROR_DEVICE_NOT_CONNECTED: u32 = 1167;
pub(crate) const XINPUT_GAMEPAD_DPAD_UP: u16 = 0x0001;
pub(crate) const XINPUT_GAMEPAD_DPAD_DOWN: u16 = 0x0002;
pub(crate) const XINPUT_GAMEPAD_DPAD_LEFT: u16 = 0x0004;
pub(crate) const XINPUT_GAMEPAD_DPAD_RIGHT: u16 = 0x0008;
pub(crate) const XINPUT_GAMEPAD_START: u16 = 0x0010;
pub(crate) const XINPUT_GAMEPAD_BACK: u16 = 0x0020;
pub(crate) const XINPUT_GAMEPAD_LEFT_THUMB: u16 = 0x0040;
pub(crate) const XINPUT_GAMEPAD_RIGHT_THUMB: u16 = 0x0080;
pub(crate) const XINPUT_GAMEPAD_LEFT_SHOULDER: u16 = 0x0100;
pub(crate) const XINPUT_GAMEPAD_RIGHT_SHOULDER: u16 = 0x0200;
pub(crate) const XINPUT_GAMEPAD_A: u16 = 0x1000;
pub(crate) const XINPUT_GAMEPAD_B: u16 = 0x2000;
pub(crate) const XINPUT_GAMEPAD_X: u16 = 0x4000;
pub(crate) const XINPUT_GAMEPAD_Y: u16 = 0x8000;
#[cfg(windows)]
pub(crate) type XInputGetStateFn = unsafe extern "system" fn(u32, *mut XInputState) -> u32;
#[cfg(windows)]
pub(crate) type Module = *mut core::ffi::c_void;
#[cfg(windows)]
#[link(name = "kernel32")]
unsafe extern "system" {
pub(crate) fn LoadLibraryW(name: *const u16) -> Module;
pub(crate) fn GetProcAddress(module: Module, name: *const u8) -> *mut core::ffi::c_void;
pub(crate) fn FreeLibrary(module: Module) -> i32;
pub(crate) fn GetLastError() -> u32;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ffi_layout::assert_layout;
#[test]
fn the_structures_match_the_c_layout() {
assert_layout!(XInputGamepad, 12, {
buttons: 0, 2;
left_trigger: 2, 1;
right_trigger: 3, 1;
thumb_lx: 4, 2;
thumb_ly: 6, 2;
thumb_rx: 8, 2;
thumb_ry: 10, 2;
});
assert_layout!(XInputState, 16, {
packet_number: 0, 4;
gamepad: 4, 12;
});
}
#[test]
fn the_capabilities_structures_match_the_c_layout() {
assert_layout!(XInputVibration, 4, {
left_motor: 0, 2;
right_motor: 2, 2;
});
assert_layout!(XInputCapabilities, 20, {
kind: 0, 1;
sub_type: 1, 1;
flags: 2, 2;
gamepad: 4, 12;
vibration: 16, 4;
});
assert_layout!(XInputCapabilitiesEx, 32, {
capabilities: 0, 20;
vendor_id: 20, 2;
product_id: 22, 2;
product_version: 24, 2;
unknown1: 26, 2;
unknown2: 28, 4;
});
}
}