Skip to content

Commit

Permalink
feat: added switch joypad
Browse files Browse the repository at this point in the history
  • Loading branch information
ABeltramo committed Aug 6, 2024
1 parent 7f197ff commit 866c3c2
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 1 deletion.
1 change: 1 addition & 0 deletions bindings/rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ input = "0.9.0"
rustix = { version = "0.38.18", features = ["fs"] }
approx = "0.5.1"
sdl2 = "0.37.0"
serial_test = "3.1.1"
72 changes: 72 additions & 0 deletions bindings/rust/src/joypad_switch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use std::ffi::{c_int, c_void};
use crate::c_bindings::{inputtino_joypad_switch_create, inputtino_joypad_switch_destroy, inputtino_joypad_switch_get_nodes, inputtino_joypad_switch_set_on_rumble, inputtino_joypad_switch_set_pressed_buttons, inputtino_joypad_switch_set_stick, inputtino_joypad_switch_set_triggers};
use crate::common::{InputtinoDeviceDefinition, error_handler_fn};
use crate::{get_nodes, make_device};

// re-export INPUTTINO_JOYPAD_BTN and INPUTTINO_JOYPAD_STICK_POSITION
pub use crate::c_bindings::{INPUTTINO_JOYPAD_BTN, INPUTTINO_JOYPAD_STICK_POSITION};

pub struct InputtinoSwitchJoypad {
joypad: *mut crate::c_bindings::InputtinoSwitchJoypad,
on_rumble_fn: Box<dyn FnMut(i32, i32) -> ()>,
}

impl InputtinoSwitchJoypad {
pub fn new(device: &InputtinoDeviceDefinition) -> Result<Self, String> {
unsafe {
let dev = make_device!(inputtino_joypad_switch_create, device);
match dev {
Ok(joypad) => {
Ok(InputtinoSwitchJoypad { joypad, on_rumble_fn: Box::new(|_, _| {}) })
}
Err(e) => Err(e),
}
}
}

pub fn get_nodes(&self) -> Result<Vec<String>, String> {
unsafe {
get_nodes!(inputtino_joypad_switch_get_nodes, self.joypad)
}
}

pub fn set_pressed(&self, buttons: i32) {
unsafe {
inputtino_joypad_switch_set_pressed_buttons(self.joypad, buttons);
}
}

pub fn set_triggers(&self, left_trigger: i16, right_trigger: i16) {
unsafe {
inputtino_joypad_switch_set_triggers(self.joypad, left_trigger, right_trigger);
}
}

pub fn set_stick(&self, stick_type: INPUTTINO_JOYPAD_STICK_POSITION, x: i16, y: i16) {
unsafe {
inputtino_joypad_switch_set_stick(self.joypad, stick_type, x, y);
}
}

pub fn set_on_rumble(&mut self, on_rumble_fn: impl FnMut(i32, i32) -> () + 'static) {
self.on_rumble_fn = Box::new(on_rumble_fn);
unsafe {
let state_ptr = self as *const _ as *mut c_void;
inputtino_joypad_switch_set_on_rumble(self.joypad, Some(on_rumble_c_fn), state_ptr);
}
}
}

impl Drop for InputtinoSwitchJoypad {
fn drop(&mut self) {
unsafe {
inputtino_joypad_switch_destroy(self.joypad);
}
}
}

#[allow(dead_code)]
pub unsafe extern "C" fn on_rumble_c_fn(left_motor: c_int, right_motor: c_int, user_data: *mut ::core::ffi::c_void) {
let joypad: &mut InputtinoSwitchJoypad = &mut *(user_data as *mut InputtinoSwitchJoypad);
((*joypad).on_rumble_fn)(left_motor, right_motor);
}
1 change: 0 additions & 1 deletion bindings/rust/src/joypad_xbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ impl Drop for InputtinoXOneJoypad {

#[allow(dead_code)]
pub unsafe extern "C" fn on_rumble_c_fn(left_motor: c_int, right_motor: c_int, user_data: *mut ::core::ffi::c_void) {
println!("on_rumble_c_fn {:?}-{:?}", left_motor, right_motor);
let joypad: &mut InputtinoXOneJoypad = &mut *(user_data as *mut InputtinoXOneJoypad);
((*joypad).on_rumble_fn)(left_motor, right_motor);
}
3 changes: 3 additions & 0 deletions bindings/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@ pub mod common;
pub mod mouse;
pub mod keyboard;
pub mod joypad_xbox;
pub mod joypad_switch;

// Private low level automatic c bindings
mod c_bindings;
122 changes: 122 additions & 0 deletions bindings/rust/tests/joypad_xbox.rs → bindings/rust/tests/joypads.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use serial_test::serial;
use inputtino_rs::common::InputtinoDeviceDefinition;
use inputtino_rs::joypad_switch::InputtinoSwitchJoypad;
use inputtino_rs::joypad_xbox::{InputtinoXOneJoypad, INPUTTINO_JOYPAD_BTN, INPUTTINO_JOYPAD_STICK_POSITION};

#[test]
#[serial]
fn test_xbox_joypad() {
let device = InputtinoDeviceDefinition::new("Rusty XOne controller", 0x045e, 0x02dd, 0x0100, "00:11:22:33:44", "00:11:22:33:44");
let mut joypad = InputtinoXOneJoypad::new(&device).unwrap();
Expand Down Expand Up @@ -118,3 +121,122 @@ fn test_xbox_joypad() {
std::thread::sleep(std::time::Duration::from_millis(125));
}
}

#[test]
#[serial]
fn test_switch_joypad() {
let device = InputtinoDeviceDefinition::new("Rusty Switch controller", 0x045e, 0x02dd, 0x0100, "00:11:22:33:44", "00:11:22:33:44");
let mut joypad = InputtinoSwitchJoypad::new(&device).unwrap();

let nodes = joypad.get_nodes().unwrap();
{
assert_eq!(nodes.len(), 2);
assert!(nodes[0].starts_with("/dev/input/event"));
assert!(nodes[1].starts_with("/dev/input/js"));
}

let sdl = sdl2::init().unwrap();
let joystick_subsystem = sdl.game_controller().unwrap();
let mut sdl_js = joystick_subsystem.open(0).unwrap();
let mut event_pump = sdl.event_pump().unwrap();

for event in event_pump.poll_iter() {
match event {
sdl2::event::Event::JoyDeviceAdded { which, .. } => {
assert_eq!(which, 0);
}
sdl2::event::Event::ControllerDeviceAdded { which, .. } => {
assert_eq!(which, 0);
}
_ => panic!("Unexpected event : {:?}", event),
}
}

assert_eq!(sdl_js.name(), "Xbox One Controller");
assert!(sdl_js.has_rumble());

{
joypad.set_pressed(INPUTTINO_JOYPAD_BTN::A as i32);
for event in event_pump.wait_timeout_iter(50) {
match event {
sdl2::event::Event::ControllerButtonDown { button, .. } => {
assert_eq!(button, sdl2::controller::Button::B);
}
sdl2::event::Event::JoyButtonDown { button_idx, .. } => {
assert_eq!(button_idx, sdl2::controller::Button::B as u8);
break;
}
_ => panic!("Unexpected event : {:?}", event),
}
}
}

{
joypad.set_triggers(0, 0);
for event in event_pump.wait_timeout_iter(50) {
match event {
sdl2::event::Event::ControllerAxisMotion { axis, value, .. } => {
assert_eq!(axis, sdl2::controller::Axis::TriggerLeft);
assert_eq!(value, 0);
}
sdl2::event::Event::JoyAxisMotion { axis_idx, value, .. } => {
assert_eq!(axis_idx, sdl2::controller::Axis::TriggerLeft as u8);
assert_eq!(value, 0);
break;
}
_ => panic!("Unexpected event : {:?}", event),
}
}
}

{
joypad.set_stick(INPUTTINO_JOYPAD_STICK_POSITION::LS, 0, 0);
for event in event_pump.wait_timeout_iter(50) {
match event {
sdl2::event::Event::ControllerAxisMotion { axis, value, .. } => {
assert_eq!(axis, sdl2::controller::Axis::LeftX);
assert_eq!(value, 0);
}
sdl2::event::Event::JoyAxisMotion { axis_idx, value, .. } => {
assert_eq!(axis_idx, sdl2::controller::Axis::LeftX as u8);
assert_eq!(value, 0);
break;
}
_ => panic!("Unexpected event : {:?}", event),
}
}
}

{
joypad.set_stick(INPUTTINO_JOYPAD_STICK_POSITION::RS, 0, 0);
for event in event_pump.wait_timeout_iter(50) {
match event {
sdl2::event::Event::ControllerAxisMotion { axis, value, .. } => {
assert_eq!(axis, sdl2::controller::Axis::RightX);
assert_eq!(value, 0);
}
sdl2::event::Event::JoyAxisMotion { axis_idx, value, .. } => {
assert_eq!(axis_idx, sdl2::controller::Axis::RightX as u8);
assert_eq!(value, 0);
break;
}
_ => panic!("Unexpected event : {:?}", event),
}
}
}

{
joypad.set_on_rumble(move |left, right| {
assert_eq!(left, 100);
assert_eq!(right, 200);
});
let res = sdl_js.set_rumble(100, 200, 150);
assert!(res.is_ok());
std::thread::sleep(std::time::Duration::from_millis(25));
joypad.set_on_rumble(move |left, right| {
assert_eq!(left, 0);
assert_eq!(right, 0);
});
std::thread::sleep(std::time::Duration::from_millis(125));
}
}

0 comments on commit 866c3c2

Please sign in to comment.