@desklink/host 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +44 -0
- package/README.md +266 -0
- package/bin/desklink-host.mjs +113 -0
- package/dist/bridge.d.ts +57 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/bridge.js +208 -0
- package/dist/bridge.js.map +1 -0
- package/dist/engineProcess.d.ts +82 -0
- package/dist/engineProcess.d.ts.map +1 -0
- package/dist/engineProcess.js +243 -0
- package/dist/engineProcess.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol.d.ts +169 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +18 -0
- package/dist/protocol.js.map +1 -0
- package/dist/resolveEngine.d.ts +34 -0
- package/dist/resolveEngine.d.ts.map +1 -0
- package/dist/resolveEngine.js +103 -0
- package/dist/resolveEngine.js.map +1 -0
- package/docs/BOUNDARY.md +145 -0
- package/docs/PROTOCOL.md +363 -0
- package/engine/Cargo.lock +3077 -0
- package/engine/Cargo.toml +37 -0
- package/engine/build.rs +107 -0
- package/engine/native/inputtino_shim.cpp +11 -0
- package/engine/native/vpx_shim.c +184 -0
- package/engine/native/wrapper.h +7 -0
- package/engine/src/capture.rs +510 -0
- package/engine/src/clipboard.rs +132 -0
- package/engine/src/convert.rs +299 -0
- package/engine/src/encoder.rs +204 -0
- package/engine/src/input.rs +355 -0
- package/engine/src/keymap.rs +338 -0
- package/engine/src/main.rs +614 -0
- package/engine/src/peer.rs +775 -0
- package/engine/src/portal.rs +115 -0
- package/engine/src/protocol.rs +331 -0
- package/engine/src/session.rs +2159 -0
- package/engine/src/x11.rs +244 -0
- package/engine/vendor/inputtino/.clang-format +166 -0
- package/engine/vendor/inputtino/.clang-tidy +30 -0
- package/engine/vendor/inputtino/.dockerignore +11 -0
- package/engine/vendor/inputtino/.github/workflows/mirror-repo.yml +14 -0
- package/engine/vendor/inputtino/.github/workflows/python-lint-format-test-typecheck.yml +124 -0
- package/engine/vendor/inputtino/.github/workflows/python-test-install.yaml +49 -0
- package/engine/vendor/inputtino/.github/workflows/rust.yml +40 -0
- package/engine/vendor/inputtino/CMakeLists.txt +187 -0
- package/engine/vendor/inputtino/LICENSE +21 -0
- package/engine/vendor/inputtino/README.md +110 -0
- package/engine/vendor/inputtino/bindings/python/.devcontainer/Dockerfile +23 -0
- package/engine/vendor/inputtino/bindings/python/.devcontainer/devcontainer.json +28 -0
- package/engine/vendor/inputtino/bindings/python/.python-version +1 -0
- package/engine/vendor/inputtino/bindings/python/CMakeLists.txt +23 -0
- package/engine/vendor/inputtino/bindings/python/CPPLINT.cfg +2 -0
- package/engine/vendor/inputtino/bindings/python/Makefile +49 -0
- package/engine/vendor/inputtino/bindings/python/README.md +215 -0
- package/engine/vendor/inputtino/bindings/python/pyproject.toml +178 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/__init__.py +43 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/_core.pyi +533 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/base.py +63 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/joypad.py +248 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/keyboard.py +256 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/mouse.py +106 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/pentablet.py +73 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/py.typed +0 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/touchscreen.py +61 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/trackpad.py +74 -0
- package/engine/vendor/inputtino/bindings/python/src/main.cpp +217 -0
- package/engine/vendor/inputtino/bindings/python/tests/__init__.py +0 -0
- package/engine/vendor/inputtino/bindings/python/tests/helpers.py +3 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_base.py +60 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_inputtino.py +5 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_joypad.py +332 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_keyboard.py +164 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_mouse.py +185 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_pentablet.py +198 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_touchscreen.py +144 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_trackpad.py +146 -0
- package/engine/vendor/inputtino/bindings/python/uv.lock +390 -0
- package/engine/vendor/inputtino/bindings/rust/Cargo.toml +6 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/.dockerignore +1 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/Cargo.toml +18 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/examples/keyboard.rs +33 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/examples/mouse.rs +17 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/common.rs +116 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/error.rs +17 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/joypad.rs +74 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/joypad_nintendo.rs +135 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/joypad_ps5.rs +280 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/joypad_xbox.rs +134 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/keyboard.rs +76 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/lib.rs +32 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/mouse.rs +178 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/tests/common.rs +38 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/tests/joypads.rs +150 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/tests/keyboard.rs +73 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/tests/mouse.rs +139 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino-sys/.dockerignore +1 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino-sys/Cargo.toml +12 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino-sys/build.rs +48 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino-sys/src/lib.rs +5 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino-sys/wrapper.h +1 -0
- package/engine/vendor/inputtino/cmake/utils.cmake +9 -0
- package/engine/vendor/inputtino/docker/Dockerfile +70 -0
- package/engine/vendor/inputtino/include/inputtino/input.h +324 -0
- package/engine/vendor/inputtino/include/inputtino/input.hpp +466 -0
- package/engine/vendor/inputtino/include/inputtino/result.hpp +37 -0
- package/engine/vendor/inputtino/share/pkgconfig/libinputtino.pc.in +17 -0
- package/engine/vendor/inputtino/src/c-bindings/helpers.hpp +19 -0
- package/engine/vendor/inputtino/src/c-bindings/joypad_ps5.cpp +115 -0
- package/engine/vendor/inputtino/src/c-bindings/joypad_switch.cpp +63 -0
- package/engine/vendor/inputtino/src/c-bindings/joypad_xone.cpp +62 -0
- package/engine/vendor/inputtino/src/c-bindings/keyboard.cpp +42 -0
- package/engine/vendor/inputtino/src/c-bindings/mouse.cpp +67 -0
- package/engine/vendor/inputtino/src/c-bindings/pen_tablet.cpp +50 -0
- package/engine/vendor/inputtino/src/c-bindings/touchscreen.cpp +43 -0
- package/engine/vendor/inputtino/src/c-bindings/trackpad.cpp +49 -0
- package/engine/vendor/inputtino/src/uhid/README.adoc +63 -0
- package/engine/vendor/inputtino/src/uhid/include/crc32.hpp +38 -0
- package/engine/vendor/inputtino/src/uhid/include/uhid/protected_types.hpp +36 -0
- package/engine/vendor/inputtino/src/uhid/include/uhid/ps5.hpp +550 -0
- package/engine/vendor/inputtino/src/uhid/include/uhid/uhid.hpp +168 -0
- package/engine/vendor/inputtino/src/uhid/joypad_ps5.cpp +580 -0
- package/engine/vendor/inputtino/src/uinput/include/inputtino/keyboard.hpp +84 -0
- package/engine/vendor/inputtino/src/uinput/include/inputtino/protected_ps5_types.hpp +7 -0
- package/engine/vendor/inputtino/src/uinput/include/inputtino/protected_types.hpp +110 -0
- package/engine/vendor/inputtino/src/uinput/joypad_nintendo.cpp +190 -0
- package/engine/vendor/inputtino/src/uinput/joypad_ps.cpp +203 -0
- package/engine/vendor/inputtino/src/uinput/joypad_utils.hpp +246 -0
- package/engine/vendor/inputtino/src/uinput/joypad_xbox.cpp +190 -0
- package/engine/vendor/inputtino/src/uinput/keyboard.cpp +120 -0
- package/engine/vendor/inputtino/src/uinput/mouse.cpp +199 -0
- package/engine/vendor/inputtino/src/uinput/pentablet.cpp +162 -0
- package/engine/vendor/inputtino/src/uinput/touchscreen.cpp +140 -0
- package/engine/vendor/inputtino/src/uinput/trackpad.cpp +192 -0
- package/examples/reference-client.html +428 -0
- package/package.json +38 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
use crate::{
|
|
2
|
+
sys::{InputtinoDeviceDefinition, InputtinoErrorHandler},
|
|
3
|
+
InputtinoError,
|
|
4
|
+
};
|
|
5
|
+
use std::{ffi::CString, path::PathBuf};
|
|
6
|
+
|
|
7
|
+
/// Definition of the type of device to emulate.
|
|
8
|
+
#[allow(dead_code)]
|
|
9
|
+
pub struct DeviceDefinition {
|
|
10
|
+
pub def: InputtinoDeviceDefinition,
|
|
11
|
+
// Keep those around since we are passing them as pointers
|
|
12
|
+
name: CString,
|
|
13
|
+
phys: CString,
|
|
14
|
+
uniq: CString,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
impl DeviceDefinition {
|
|
18
|
+
/// Create a new device definition for creating emulated devices.
|
|
19
|
+
///
|
|
20
|
+
/// # Arguments
|
|
21
|
+
///
|
|
22
|
+
/// * `name` - The name of the emulated device.
|
|
23
|
+
/// * `vendor_id` - ID of the vendor that created the emulated device.
|
|
24
|
+
/// * `product_id` - ID of the product.
|
|
25
|
+
/// * `version` -
|
|
26
|
+
/// * `phys` -
|
|
27
|
+
/// * `uniq` -
|
|
28
|
+
pub fn new(
|
|
29
|
+
name: &str,
|
|
30
|
+
vendor_id: u16,
|
|
31
|
+
product_id: u16,
|
|
32
|
+
version: u16,
|
|
33
|
+
phys: &str,
|
|
34
|
+
uniq: &str,
|
|
35
|
+
) -> Self {
|
|
36
|
+
let name = CString::new(name).unwrap();
|
|
37
|
+
let phys = CString::new(phys).unwrap();
|
|
38
|
+
let uniq = CString::new(uniq).unwrap();
|
|
39
|
+
let def = InputtinoDeviceDefinition {
|
|
40
|
+
name: name.as_ptr(),
|
|
41
|
+
vendor_id,
|
|
42
|
+
product_id,
|
|
43
|
+
version,
|
|
44
|
+
device_phys: phys.as_ptr(), // TODO: optional, if not present random MAC address
|
|
45
|
+
device_uniq: uniq.as_ptr(),
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
DeviceDefinition {
|
|
49
|
+
def,
|
|
50
|
+
name,
|
|
51
|
+
phys,
|
|
52
|
+
uniq,
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
pub(crate) unsafe extern "C" fn error_handler_fn(
|
|
58
|
+
error_message: *const ::core::ffi::c_char,
|
|
59
|
+
user_data: *mut ::core::ffi::c_void,
|
|
60
|
+
) {
|
|
61
|
+
let error_str = std::ffi::CStr::from_ptr(error_message);
|
|
62
|
+
let user_data = user_data as *mut CString;
|
|
63
|
+
*user_data = CString::from(error_str);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
type GetNodesFn<T> = unsafe extern "C" fn(
|
|
67
|
+
device: *mut T,
|
|
68
|
+
num_nodes: *mut ::core::ffi::c_int,
|
|
69
|
+
) -> *mut *mut ::core::ffi::c_char;
|
|
70
|
+
|
|
71
|
+
pub(crate) fn get_nodes<T>(
|
|
72
|
+
f: GetNodesFn<T>,
|
|
73
|
+
device: *mut T,
|
|
74
|
+
) -> Result<Vec<PathBuf>, InputtinoError> {
|
|
75
|
+
let mut nodes_count: core::ffi::c_int = 0;
|
|
76
|
+
let nodes = unsafe { f(device, &mut nodes_count) };
|
|
77
|
+
if nodes.is_null() {
|
|
78
|
+
return Err(InputtinoError::Generic("Failed to get nodes".to_string()));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let mut result = Vec::new();
|
|
82
|
+
for i in 0..nodes_count {
|
|
83
|
+
let node = unsafe { std::ffi::CString::from_raw(*nodes.offset(i as isize)) };
|
|
84
|
+
result.push(PathBuf::from(&node.to_string_lossy().to_string()));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
Ok(result)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
type CreateDeviceFn<T> = unsafe extern "C" fn(
|
|
91
|
+
device: *const InputtinoDeviceDefinition,
|
|
92
|
+
eh: *const InputtinoErrorHandler,
|
|
93
|
+
) -> *mut T;
|
|
94
|
+
|
|
95
|
+
pub(crate) fn make_device<T>(
|
|
96
|
+
f: CreateDeviceFn<T>,
|
|
97
|
+
definition: &DeviceDefinition,
|
|
98
|
+
) -> Result<*mut T, InputtinoError> {
|
|
99
|
+
let mut error_str = std::ffi::CString::default();
|
|
100
|
+
let error_handler = InputtinoErrorHandler {
|
|
101
|
+
eh: Some(error_handler_fn),
|
|
102
|
+
user_data: &mut error_str as *mut _ as *mut std::ffi::c_void,
|
|
103
|
+
};
|
|
104
|
+
let device = unsafe { f(&definition.def, &error_handler) };
|
|
105
|
+
if device.is_null() {
|
|
106
|
+
let error_msg = error_str.to_string_lossy();
|
|
107
|
+
Err(InputtinoError::Generic(format!(
|
|
108
|
+
"Failed to create input device: {error_msg}"
|
|
109
|
+
)))
|
|
110
|
+
} else {
|
|
111
|
+
Ok(device)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
unsafe impl Send for DeviceDefinition {}
|
|
116
|
+
unsafe impl Sync for DeviceDefinition {}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/// Simple error type that might be expanded on later.
|
|
2
|
+
#[derive(Debug, Clone)]
|
|
3
|
+
pub enum InputtinoError {
|
|
4
|
+
/// Any error type, represented by an error message.
|
|
5
|
+
Generic(String),
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// TODO: When this becomes more complex, consider using `thiserror`.
|
|
9
|
+
impl std::fmt::Display for InputtinoError {
|
|
10
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
11
|
+
match self {
|
|
12
|
+
InputtinoError::Generic(error_message) => write!(f, "{}", error_message),
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
impl std::error::Error for InputtinoError { }
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
use crate::{JoypadStickPosition, PS5Joypad, SwitchJoypad, XboxOneJoypad};
|
|
2
|
+
|
|
3
|
+
/// A generic Joypad which exposes some common functionality of the underlying joypad.
|
|
4
|
+
pub enum Joypad {
|
|
5
|
+
Switch(SwitchJoypad),
|
|
6
|
+
PS5(PS5Joypad),
|
|
7
|
+
XboxOne(XboxOneJoypad),
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
impl Joypad {
|
|
11
|
+
/// Set the state of all buttons.
|
|
12
|
+
///
|
|
13
|
+
/// Any buttons that are not set are released if they were set before.
|
|
14
|
+
///
|
|
15
|
+
/// # Examples
|
|
16
|
+
///
|
|
17
|
+
/// ```ignore
|
|
18
|
+
/// device.set_pressed(inputtino::JoypadButton::A | inputtino::JoypadButton::B);
|
|
19
|
+
/// ```
|
|
20
|
+
pub fn set_pressed(&self, buttons: i32) {
|
|
21
|
+
match self {
|
|
22
|
+
Joypad::Switch(joypad) => joypad.set_pressed(buttons),
|
|
23
|
+
Joypad::PS5(joypad) => joypad.set_pressed(buttons),
|
|
24
|
+
Joypad::XboxOne(joypad) => joypad.set_pressed(buttons),
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/// Set the state of the triggers.
|
|
29
|
+
///
|
|
30
|
+
/// # Examples
|
|
31
|
+
///
|
|
32
|
+
/// ```ignore
|
|
33
|
+
/// device.set_triggers(0, -i16::MAX);
|
|
34
|
+
/// ```
|
|
35
|
+
pub fn set_triggers(&self, left_trigger: i16, right_trigger: i16) {
|
|
36
|
+
match self {
|
|
37
|
+
Joypad::Switch(joypad) => joypad.set_triggers(left_trigger, right_trigger),
|
|
38
|
+
Joypad::PS5(joypad) => joypad.set_triggers(left_trigger, right_trigger),
|
|
39
|
+
Joypad::XboxOne(joypad) => joypad.set_triggers(left_trigger, right_trigger),
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/// Set the state of the joysticks.
|
|
44
|
+
///
|
|
45
|
+
/// # Examples
|
|
46
|
+
///
|
|
47
|
+
/// ```ignore
|
|
48
|
+
/// device.set_stick(inputtino::JoypadStickPosition::LS, 0, -i16::MAX);
|
|
49
|
+
/// ```
|
|
50
|
+
pub fn set_stick(&self, stick_type: JoypadStickPosition, x: i16, y: i16) {
|
|
51
|
+
match self {
|
|
52
|
+
Joypad::Switch(joypad) => joypad.set_stick(stick_type, x, y),
|
|
53
|
+
Joypad::PS5(joypad) => joypad.set_stick(stick_type, x, y),
|
|
54
|
+
Joypad::XboxOne(joypad) => joypad.set_stick(stick_type, x, y),
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// Sets a callback to be called when this device receives a rumble event.
|
|
59
|
+
///
|
|
60
|
+
/// # Examples
|
|
61
|
+
///
|
|
62
|
+
/// ```ignore
|
|
63
|
+
/// device.set_on_rumble(|low, high| {
|
|
64
|
+
/// println!("Received rumble event with frequencies low: {low}, high: {high}");
|
|
65
|
+
/// });
|
|
66
|
+
/// ```
|
|
67
|
+
pub fn set_on_rumble(&mut self, on_rumble_fn: impl FnMut(i32, i32) + 'static) {
|
|
68
|
+
match self {
|
|
69
|
+
Joypad::Switch(joypad) => joypad.set_on_rumble(on_rumble_fn),
|
|
70
|
+
Joypad::PS5(joypad) => joypad.set_on_rumble(on_rumble_fn),
|
|
71
|
+
Joypad::XboxOne(joypad) => joypad.set_on_rumble(on_rumble_fn),
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
use std::ffi::{c_int, c_void};
|
|
2
|
+
use std::path::PathBuf;
|
|
3
|
+
|
|
4
|
+
use crate::common::{get_nodes, make_device, DeviceDefinition};
|
|
5
|
+
use crate::sys::{
|
|
6
|
+
inputtino_joypad_switch_create, inputtino_joypad_switch_destroy,
|
|
7
|
+
inputtino_joypad_switch_get_nodes, inputtino_joypad_switch_set_on_rumble,
|
|
8
|
+
inputtino_joypad_switch_set_pressed_buttons, inputtino_joypad_switch_set_stick,
|
|
9
|
+
inputtino_joypad_switch_set_triggers,
|
|
10
|
+
};
|
|
11
|
+
use crate::{InputtinoError, JoypadStickPosition};
|
|
12
|
+
|
|
13
|
+
/// Emulated Nintendo Switch joypad.
|
|
14
|
+
pub struct SwitchJoypad {
|
|
15
|
+
joypad: *mut crate::sys::InputtinoSwitchJoypad,
|
|
16
|
+
on_rumble_fn: *mut c_void,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
impl SwitchJoypad {
|
|
20
|
+
/// Create a new emulated Nintendo Switch device with the given device definition.
|
|
21
|
+
///
|
|
22
|
+
/// # Examples
|
|
23
|
+
///
|
|
24
|
+
/// ```
|
|
25
|
+
/// let definition = inputtino::DeviceDefinition::new(
|
|
26
|
+
/// "Inputtino Switch controller",
|
|
27
|
+
/// 0x057e,
|
|
28
|
+
/// 0x2009,
|
|
29
|
+
/// 0x8111,
|
|
30
|
+
/// "00:11:22:33:44",
|
|
31
|
+
/// "00:11:22:33:44",
|
|
32
|
+
/// );
|
|
33
|
+
/// let device = inputtino::SwitchJoypad::new(&definition);
|
|
34
|
+
/// ```
|
|
35
|
+
pub fn new(device: &DeviceDefinition) -> Result<Self, InputtinoError> {
|
|
36
|
+
make_device(inputtino_joypad_switch_create, device).map(|joypad| SwitchJoypad {
|
|
37
|
+
joypad,
|
|
38
|
+
on_rumble_fn: std::ptr::null_mut(),
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/// Set the state of all buttons.
|
|
43
|
+
///
|
|
44
|
+
/// Any buttons that are not set are released if they were set before.
|
|
45
|
+
///
|
|
46
|
+
/// # Examples
|
|
47
|
+
///
|
|
48
|
+
/// ```ignore
|
|
49
|
+
/// device.set_pressed(inputtino::JoypadButton::A | inputtino::JoypadButton::B);
|
|
50
|
+
/// ```
|
|
51
|
+
pub fn set_pressed(&self, buttons: i32) {
|
|
52
|
+
unsafe {
|
|
53
|
+
inputtino_joypad_switch_set_pressed_buttons(self.joypad, buttons);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/// Set the state of the triggers.
|
|
58
|
+
///
|
|
59
|
+
/// # Examples
|
|
60
|
+
///
|
|
61
|
+
/// ```ignore
|
|
62
|
+
/// device.set_triggers(0, -i16::MAX);
|
|
63
|
+
/// ```
|
|
64
|
+
pub fn set_triggers(&self, left_trigger: i16, right_trigger: i16) {
|
|
65
|
+
unsafe {
|
|
66
|
+
inputtino_joypad_switch_set_triggers(self.joypad, left_trigger, right_trigger);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/// Set the state of the joysticks.
|
|
71
|
+
///
|
|
72
|
+
/// # Examples
|
|
73
|
+
///
|
|
74
|
+
/// ```ignore
|
|
75
|
+
/// device.set_stick(inputtino::JoypadStickPosition::LS, 0, -i16::MAX);
|
|
76
|
+
/// ```
|
|
77
|
+
pub fn set_stick(&self, stick_type: JoypadStickPosition, x: i16, y: i16) {
|
|
78
|
+
unsafe {
|
|
79
|
+
inputtino_joypad_switch_set_stick(self.joypad, stick_type, x, y);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/// Sets a callback to be called when this device receives a rumble event.
|
|
84
|
+
///
|
|
85
|
+
/// # Examples
|
|
86
|
+
///
|
|
87
|
+
/// ```ignore
|
|
88
|
+
/// device.set_on_rumble(|low, high| {
|
|
89
|
+
/// println!("Received rumble event with frequencies low: {low}, high: {high}");
|
|
90
|
+
/// });
|
|
91
|
+
/// ```
|
|
92
|
+
pub fn set_on_rumble(&mut self, on_rumble_fn: impl FnMut(i32, i32) + 'static) {
|
|
93
|
+
let on_rumble_fn = Box::new(RumbleFunction {
|
|
94
|
+
on_rumble_fn: Box::new(on_rumble_fn),
|
|
95
|
+
});
|
|
96
|
+
self.on_rumble_fn = Box::into_raw(on_rumble_fn) as *mut c_void;
|
|
97
|
+
unsafe {
|
|
98
|
+
inputtino_joypad_switch_set_on_rumble(
|
|
99
|
+
self.joypad,
|
|
100
|
+
Some(on_rumble_c_fn),
|
|
101
|
+
self.on_rumble_fn,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
pub fn get_nodes(&self) -> Result<Vec<PathBuf>, InputtinoError> {
|
|
107
|
+
get_nodes(inputtino_joypad_switch_get_nodes, self.joypad)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
impl Drop for SwitchJoypad {
|
|
112
|
+
fn drop(&mut self) {
|
|
113
|
+
unsafe {
|
|
114
|
+
inputtino_joypad_switch_destroy(self.joypad);
|
|
115
|
+
if !self.on_rumble_fn.is_null() {
|
|
116
|
+
drop(Box::from_raw(self.on_rumble_fn as *mut RumbleFunction));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
struct RumbleFunction {
|
|
123
|
+
on_rumble_fn: Box<dyn FnMut(i32, i32)>,
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
unsafe extern "C" fn on_rumble_c_fn(
|
|
127
|
+
left_motor: c_int,
|
|
128
|
+
right_motor: c_int,
|
|
129
|
+
user_data: *mut ::core::ffi::c_void,
|
|
130
|
+
) {
|
|
131
|
+
let on_rumble_fn = user_data as *mut RumbleFunction;
|
|
132
|
+
((*on_rumble_fn).on_rumble_fn)(left_motor, right_motor);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
unsafe impl Send for SwitchJoypad {}
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
use inputtino_sys::{inputtino_joypad_ps5_place_finger, inputtino_joypad_ps5_release_finger};
|
|
2
|
+
use std::ffi::{c_int, c_void};
|
|
3
|
+
use std::path::PathBuf;
|
|
4
|
+
|
|
5
|
+
use crate::common::{get_nodes, make_device, DeviceDefinition};
|
|
6
|
+
use crate::sys::{
|
|
7
|
+
inputtino_joypad_ps5_create, inputtino_joypad_ps5_destroy, inputtino_joypad_ps5_get_nodes,
|
|
8
|
+
inputtino_joypad_ps5_set_on_led, inputtino_joypad_ps5_set_on_rumble,
|
|
9
|
+
inputtino_joypad_ps5_set_pressed_buttons, inputtino_joypad_ps5_set_stick,
|
|
10
|
+
inputtino_joypad_ps5_set_triggers, inputtino_joypad_ps5_set_motion,
|
|
11
|
+
inputtino_joypad_ps5_set_battery, inputtino_joypad_ps5_set_on_trigger_effect,
|
|
12
|
+
};
|
|
13
|
+
use crate::{BatteryState, InputtinoError, JoypadMotionType, JoypadStickPosition};
|
|
14
|
+
|
|
15
|
+
/// Emulated PlayStation 5's DualSense joypad.
|
|
16
|
+
pub struct PS5Joypad {
|
|
17
|
+
joypad: *mut crate::sys::InputtinoPS5Joypad,
|
|
18
|
+
on_rumble_fn: *mut c_void,
|
|
19
|
+
on_led_fn: *mut c_void,
|
|
20
|
+
on_trigger_effect_fn: *mut c_void,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
impl PS5Joypad {
|
|
24
|
+
// TODO: Expose in C API and use the binding.
|
|
25
|
+
pub const TOUCHPAD_WIDTH: i32 = 1920;
|
|
26
|
+
pub const TOUCHPAD_HEIGHT: i32 = 1080;
|
|
27
|
+
|
|
28
|
+
/// Create a new emulated PS5 DualSense device with the given device definition.
|
|
29
|
+
///
|
|
30
|
+
/// # Examples
|
|
31
|
+
///
|
|
32
|
+
/// ```
|
|
33
|
+
/// let definition = inputtino::DeviceDefinition::new(
|
|
34
|
+
/// "Inputtino PS5 controller",
|
|
35
|
+
/// 0x054C,
|
|
36
|
+
/// 0x0CE6,
|
|
37
|
+
/// 0x8111,
|
|
38
|
+
/// "00:11:22:33:44",
|
|
39
|
+
/// "00:11:22:33:44",
|
|
40
|
+
/// );
|
|
41
|
+
/// let device = inputtino::SwitchJoypad::new(&definition);
|
|
42
|
+
/// ```
|
|
43
|
+
pub fn new(device: &DeviceDefinition) -> Result<Self, InputtinoError> {
|
|
44
|
+
make_device(inputtino_joypad_ps5_create, device).map(|joypad| PS5Joypad {
|
|
45
|
+
joypad,
|
|
46
|
+
on_rumble_fn: std::ptr::null_mut(),
|
|
47
|
+
on_led_fn: std::ptr::null_mut(),
|
|
48
|
+
on_trigger_effect_fn: std::ptr::null_mut(),
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/// Set the state of all buttons.
|
|
53
|
+
///
|
|
54
|
+
/// Any buttons that are not set are released if they were set before.
|
|
55
|
+
///
|
|
56
|
+
/// # Examples
|
|
57
|
+
///
|
|
58
|
+
/// ```ignore
|
|
59
|
+
/// device.set_pressed(inputtino::JoypadButton::A | inputtino::JoypadButton::B);
|
|
60
|
+
/// ```
|
|
61
|
+
pub fn set_pressed(&self, buttons: i32) {
|
|
62
|
+
unsafe {
|
|
63
|
+
inputtino_joypad_ps5_set_pressed_buttons(self.joypad, buttons);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/// Set the state of the triggers.
|
|
68
|
+
///
|
|
69
|
+
/// # Examples
|
|
70
|
+
///
|
|
71
|
+
/// ```ignore
|
|
72
|
+
/// device.set_triggers(0, -i16::MAX);
|
|
73
|
+
/// ```
|
|
74
|
+
pub fn set_triggers(&self, left_trigger: i16, right_trigger: i16) {
|
|
75
|
+
unsafe {
|
|
76
|
+
inputtino_joypad_ps5_set_triggers(self.joypad, left_trigger, right_trigger);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/// Set the state of the joysticks.
|
|
81
|
+
///
|
|
82
|
+
/// # Examples
|
|
83
|
+
///
|
|
84
|
+
/// ```ignore
|
|
85
|
+
/// device.set_stick(inputtino::JoypadStickPosition::LS, 0, -i16::MAX);
|
|
86
|
+
/// ```
|
|
87
|
+
pub fn set_stick(&self, stick_type: JoypadStickPosition, x: i16, y: i16) {
|
|
88
|
+
unsafe {
|
|
89
|
+
inputtino_joypad_ps5_set_stick(self.joypad, stick_type, x, y);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/// Sets a callback to be called when this device receives a rumble event.
|
|
94
|
+
///
|
|
95
|
+
/// # Examples
|
|
96
|
+
///
|
|
97
|
+
/// ```ignore
|
|
98
|
+
/// device.set_on_rumble(|low, high| {
|
|
99
|
+
/// println!("Received rumble event with frequencies low: {low}, high: {high}");
|
|
100
|
+
/// });
|
|
101
|
+
/// ```
|
|
102
|
+
pub fn set_on_rumble(&mut self, on_rumble_fn: impl FnMut(i32, i32) + 'static) {
|
|
103
|
+
let on_rumble_fn = Box::new(RumbleFunction {
|
|
104
|
+
on_rumble_fn: Box::new(on_rumble_fn),
|
|
105
|
+
});
|
|
106
|
+
self.on_rumble_fn = Box::into_raw(on_rumble_fn) as *mut c_void;
|
|
107
|
+
unsafe {
|
|
108
|
+
inputtino_joypad_ps5_set_on_rumble(
|
|
109
|
+
self.joypad,
|
|
110
|
+
Some(on_rumble_c_fn),
|
|
111
|
+
self.on_rumble_fn,
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/// Sets a callback to be called when this device receives a LED change event.
|
|
117
|
+
///
|
|
118
|
+
/// # Examples
|
|
119
|
+
///
|
|
120
|
+
/// ```ignore
|
|
121
|
+
/// device.set_on_led(|r, g, b| {
|
|
122
|
+
/// println!("Received LED event with colors R: {r}, G: {g}, B: {b}");
|
|
123
|
+
/// });
|
|
124
|
+
/// ```
|
|
125
|
+
pub fn set_on_led(&mut self, on_led_fn: impl FnMut(i32, i32, i32) + 'static) {
|
|
126
|
+
let on_led_fn = Box::new(LedFunction {
|
|
127
|
+
on_led_fn: Box::new(on_led_fn),
|
|
128
|
+
});
|
|
129
|
+
self.on_led_fn = Box::into_raw(on_led_fn) as *mut c_void;
|
|
130
|
+
unsafe {
|
|
131
|
+
inputtino_joypad_ps5_set_on_led(self.joypad, Some(on_led_c_fn), self.on_led_fn);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/// Sets a callback to be called when this device receives a trigger effect event.
|
|
136
|
+
///
|
|
137
|
+
/// # Examples
|
|
138
|
+
///
|
|
139
|
+
/// ```ignore
|
|
140
|
+
/// device.set_on_trigger_effect(|trigger_event_flags, type_left, type_right, left_effect, right_effect| {
|
|
141
|
+
/// println!(
|
|
142
|
+
/// "Received trigger effect event: trigger_event_flags: {trigger_event_flags}, type_left: {type_left}, type_right: {type_right}, \
|
|
143
|
+
/// left_effect: {:?}, right_effect: {:?}",
|
|
144
|
+
/// left_effect, right_effect
|
|
145
|
+
/// );
|
|
146
|
+
/// });
|
|
147
|
+
/// ```
|
|
148
|
+
pub fn set_on_trigger_effect(&mut self, on_trigger_effect_fn: impl FnMut(u8, u8, u8, &[u8], &[u8]) + 'static) {
|
|
149
|
+
let on_trigger_effect_fn = Box::new(TriggerEffectFunction {
|
|
150
|
+
on_trigger_effect_fn: Box::new(on_trigger_effect_fn),
|
|
151
|
+
});
|
|
152
|
+
self.on_trigger_effect_fn = Box::into_raw(on_trigger_effect_fn) as *mut c_void;
|
|
153
|
+
unsafe {
|
|
154
|
+
inputtino_joypad_ps5_set_on_trigger_effect(self.joypad, Some(on_trigger_effect_c_fn), self.on_trigger_effect_fn);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
pub fn get_nodes(&self) -> Result<Vec<PathBuf>, InputtinoError> {
|
|
159
|
+
get_nodes(inputtino_joypad_ps5_get_nodes, self.joypad)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/// Simulates placement of a finger on the touchpad.
|
|
163
|
+
///
|
|
164
|
+
/// # Examples
|
|
165
|
+
///
|
|
166
|
+
/// ```ignore
|
|
167
|
+
/// device.place_finger(0, 100, inputtino::PS5Joypad::TOUCHPAD_HEIGHT / 2);
|
|
168
|
+
/// ```
|
|
169
|
+
pub fn place_finger(&self, finger_id: u32, x: u16, y: u16) {
|
|
170
|
+
unsafe {
|
|
171
|
+
inputtino_joypad_ps5_place_finger(self.joypad, finger_id as i32, x, y);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/// Simulates releasing of a finger from the touchpad.
|
|
176
|
+
///
|
|
177
|
+
/// # Examples
|
|
178
|
+
///
|
|
179
|
+
/// ```ignore
|
|
180
|
+
/// device.release_finger(0);
|
|
181
|
+
/// ```
|
|
182
|
+
pub fn release_finger(&self, finger_id: u32) {
|
|
183
|
+
unsafe {
|
|
184
|
+
inputtino_joypad_ps5_release_finger(self.joypad, finger_id as i32);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/// Sets the state of the gyro or acceleration sensors.
|
|
189
|
+
///
|
|
190
|
+
/// # Examples
|
|
191
|
+
///
|
|
192
|
+
/// ```ignore
|
|
193
|
+
/// device.set_motion(JoypadMotionType::ACCELERATION, 0.0, 0.0, 1.0);
|
|
194
|
+
/// ```
|
|
195
|
+
pub fn set_motion(&self, motion_type: JoypadMotionType, x: f32, y: f32, z: f32) {
|
|
196
|
+
unsafe {
|
|
197
|
+
inputtino_joypad_ps5_set_motion(self.joypad, motion_type, x, y, z);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/// Sets the state of the battery.
|
|
202
|
+
///
|
|
203
|
+
/// # Examples
|
|
204
|
+
///
|
|
205
|
+
/// ```ignore
|
|
206
|
+
/// device.set_battery(BatteryState::BATTERY_DISCHARGING, 55);
|
|
207
|
+
/// ```
|
|
208
|
+
pub fn set_battery(&self, battery_state: BatteryState, level: u8) {
|
|
209
|
+
unsafe {
|
|
210
|
+
inputtino_joypad_ps5_set_battery(self.joypad, battery_state, level as u16);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
impl Drop for PS5Joypad {
|
|
216
|
+
fn drop(&mut self) {
|
|
217
|
+
unsafe {
|
|
218
|
+
inputtino_joypad_ps5_destroy(self.joypad);
|
|
219
|
+
if !self.on_rumble_fn.is_null() {
|
|
220
|
+
drop(Box::from_raw(self.on_rumble_fn as *mut RumbleFunction));
|
|
221
|
+
}
|
|
222
|
+
if !self.on_led_fn.is_null() {
|
|
223
|
+
drop(Box::from_raw(self.on_led_fn as *mut LedFunction));
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
struct RumbleFunction {
|
|
230
|
+
on_rumble_fn: Box<dyn FnMut(i32, i32)>,
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
unsafe extern "C" fn on_rumble_c_fn(
|
|
234
|
+
left_motor: c_int,
|
|
235
|
+
right_motor: c_int,
|
|
236
|
+
user_data: *mut ::core::ffi::c_void,
|
|
237
|
+
) {
|
|
238
|
+
let on_rumble_fn = user_data as *mut RumbleFunction;
|
|
239
|
+
((*on_rumble_fn).on_rumble_fn)(left_motor, right_motor);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
struct LedFunction {
|
|
243
|
+
on_led_fn: Box<dyn FnMut(i32, i32, i32)>,
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
unsafe extern "C" fn on_led_c_fn(
|
|
247
|
+
r: c_int,
|
|
248
|
+
g: c_int,
|
|
249
|
+
b: c_int,
|
|
250
|
+
user_data: *mut ::core::ffi::c_void,
|
|
251
|
+
) {
|
|
252
|
+
let on_led_fn = user_data as *mut LedFunction;
|
|
253
|
+
((*on_led_fn).on_led_fn)(r, g, b);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
struct TriggerEffectFunction {
|
|
257
|
+
on_trigger_effect_fn: Box<dyn FnMut(u8, u8, u8, &[u8], &[u8])>,
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
unsafe extern "C" fn on_trigger_effect_c_fn(
|
|
261
|
+
trigger_event_flags: u8,
|
|
262
|
+
type_left: u8,
|
|
263
|
+
type_right: u8,
|
|
264
|
+
left: *const u8,
|
|
265
|
+
right: *const u8,
|
|
266
|
+
user_data: *mut ::core::ffi::c_void,
|
|
267
|
+
) {
|
|
268
|
+
let on_trigger_effect_fn = user_data as *mut TriggerEffectFunction;
|
|
269
|
+
let left_effect = std::slice::from_raw_parts(left, 10);
|
|
270
|
+
let right_effect = std::slice::from_raw_parts(right, 10);
|
|
271
|
+
((*on_trigger_effect_fn).on_trigger_effect_fn)(
|
|
272
|
+
trigger_event_flags,
|
|
273
|
+
type_left,
|
|
274
|
+
type_right,
|
|
275
|
+
left_effect,
|
|
276
|
+
right_effect,
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
unsafe impl Send for PS5Joypad {}
|