@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.
Files changed (142) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +44 -0
  3. package/README.md +266 -0
  4. package/bin/desklink-host.mjs +113 -0
  5. package/dist/bridge.d.ts +57 -0
  6. package/dist/bridge.d.ts.map +1 -0
  7. package/dist/bridge.js +208 -0
  8. package/dist/bridge.js.map +1 -0
  9. package/dist/engineProcess.d.ts +82 -0
  10. package/dist/engineProcess.d.ts.map +1 -0
  11. package/dist/engineProcess.js +243 -0
  12. package/dist/engineProcess.js.map +1 -0
  13. package/dist/index.d.ts +12 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +12 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/protocol.d.ts +169 -0
  18. package/dist/protocol.d.ts.map +1 -0
  19. package/dist/protocol.js +18 -0
  20. package/dist/protocol.js.map +1 -0
  21. package/dist/resolveEngine.d.ts +34 -0
  22. package/dist/resolveEngine.d.ts.map +1 -0
  23. package/dist/resolveEngine.js +103 -0
  24. package/dist/resolveEngine.js.map +1 -0
  25. package/docs/BOUNDARY.md +145 -0
  26. package/docs/PROTOCOL.md +363 -0
  27. package/engine/Cargo.lock +3077 -0
  28. package/engine/Cargo.toml +37 -0
  29. package/engine/build.rs +107 -0
  30. package/engine/native/inputtino_shim.cpp +11 -0
  31. package/engine/native/vpx_shim.c +184 -0
  32. package/engine/native/wrapper.h +7 -0
  33. package/engine/src/capture.rs +510 -0
  34. package/engine/src/clipboard.rs +132 -0
  35. package/engine/src/convert.rs +299 -0
  36. package/engine/src/encoder.rs +204 -0
  37. package/engine/src/input.rs +355 -0
  38. package/engine/src/keymap.rs +338 -0
  39. package/engine/src/main.rs +614 -0
  40. package/engine/src/peer.rs +775 -0
  41. package/engine/src/portal.rs +115 -0
  42. package/engine/src/protocol.rs +331 -0
  43. package/engine/src/session.rs +2159 -0
  44. package/engine/src/x11.rs +244 -0
  45. package/engine/vendor/inputtino/.clang-format +166 -0
  46. package/engine/vendor/inputtino/.clang-tidy +30 -0
  47. package/engine/vendor/inputtino/.dockerignore +11 -0
  48. package/engine/vendor/inputtino/.github/workflows/mirror-repo.yml +14 -0
  49. package/engine/vendor/inputtino/.github/workflows/python-lint-format-test-typecheck.yml +124 -0
  50. package/engine/vendor/inputtino/.github/workflows/python-test-install.yaml +49 -0
  51. package/engine/vendor/inputtino/.github/workflows/rust.yml +40 -0
  52. package/engine/vendor/inputtino/CMakeLists.txt +187 -0
  53. package/engine/vendor/inputtino/LICENSE +21 -0
  54. package/engine/vendor/inputtino/README.md +110 -0
  55. package/engine/vendor/inputtino/bindings/python/.devcontainer/Dockerfile +23 -0
  56. package/engine/vendor/inputtino/bindings/python/.devcontainer/devcontainer.json +28 -0
  57. package/engine/vendor/inputtino/bindings/python/.python-version +1 -0
  58. package/engine/vendor/inputtino/bindings/python/CMakeLists.txt +23 -0
  59. package/engine/vendor/inputtino/bindings/python/CPPLINT.cfg +2 -0
  60. package/engine/vendor/inputtino/bindings/python/Makefile +49 -0
  61. package/engine/vendor/inputtino/bindings/python/README.md +215 -0
  62. package/engine/vendor/inputtino/bindings/python/pyproject.toml +178 -0
  63. package/engine/vendor/inputtino/bindings/python/src/inputtino/__init__.py +43 -0
  64. package/engine/vendor/inputtino/bindings/python/src/inputtino/_core.pyi +533 -0
  65. package/engine/vendor/inputtino/bindings/python/src/inputtino/base.py +63 -0
  66. package/engine/vendor/inputtino/bindings/python/src/inputtino/joypad.py +248 -0
  67. package/engine/vendor/inputtino/bindings/python/src/inputtino/keyboard.py +256 -0
  68. package/engine/vendor/inputtino/bindings/python/src/inputtino/mouse.py +106 -0
  69. package/engine/vendor/inputtino/bindings/python/src/inputtino/pentablet.py +73 -0
  70. package/engine/vendor/inputtino/bindings/python/src/inputtino/py.typed +0 -0
  71. package/engine/vendor/inputtino/bindings/python/src/inputtino/touchscreen.py +61 -0
  72. package/engine/vendor/inputtino/bindings/python/src/inputtino/trackpad.py +74 -0
  73. package/engine/vendor/inputtino/bindings/python/src/main.cpp +217 -0
  74. package/engine/vendor/inputtino/bindings/python/tests/__init__.py +0 -0
  75. package/engine/vendor/inputtino/bindings/python/tests/helpers.py +3 -0
  76. package/engine/vendor/inputtino/bindings/python/tests/test_base.py +60 -0
  77. package/engine/vendor/inputtino/bindings/python/tests/test_inputtino.py +5 -0
  78. package/engine/vendor/inputtino/bindings/python/tests/test_joypad.py +332 -0
  79. package/engine/vendor/inputtino/bindings/python/tests/test_keyboard.py +164 -0
  80. package/engine/vendor/inputtino/bindings/python/tests/test_mouse.py +185 -0
  81. package/engine/vendor/inputtino/bindings/python/tests/test_pentablet.py +198 -0
  82. package/engine/vendor/inputtino/bindings/python/tests/test_touchscreen.py +144 -0
  83. package/engine/vendor/inputtino/bindings/python/tests/test_trackpad.py +146 -0
  84. package/engine/vendor/inputtino/bindings/python/uv.lock +390 -0
  85. package/engine/vendor/inputtino/bindings/rust/Cargo.toml +6 -0
  86. package/engine/vendor/inputtino/bindings/rust/inputtino/.dockerignore +1 -0
  87. package/engine/vendor/inputtino/bindings/rust/inputtino/Cargo.toml +18 -0
  88. package/engine/vendor/inputtino/bindings/rust/inputtino/examples/keyboard.rs +33 -0
  89. package/engine/vendor/inputtino/bindings/rust/inputtino/examples/mouse.rs +17 -0
  90. package/engine/vendor/inputtino/bindings/rust/inputtino/src/common.rs +116 -0
  91. package/engine/vendor/inputtino/bindings/rust/inputtino/src/error.rs +17 -0
  92. package/engine/vendor/inputtino/bindings/rust/inputtino/src/joypad.rs +74 -0
  93. package/engine/vendor/inputtino/bindings/rust/inputtino/src/joypad_nintendo.rs +135 -0
  94. package/engine/vendor/inputtino/bindings/rust/inputtino/src/joypad_ps5.rs +280 -0
  95. package/engine/vendor/inputtino/bindings/rust/inputtino/src/joypad_xbox.rs +134 -0
  96. package/engine/vendor/inputtino/bindings/rust/inputtino/src/keyboard.rs +76 -0
  97. package/engine/vendor/inputtino/bindings/rust/inputtino/src/lib.rs +32 -0
  98. package/engine/vendor/inputtino/bindings/rust/inputtino/src/mouse.rs +178 -0
  99. package/engine/vendor/inputtino/bindings/rust/inputtino/tests/common.rs +38 -0
  100. package/engine/vendor/inputtino/bindings/rust/inputtino/tests/joypads.rs +150 -0
  101. package/engine/vendor/inputtino/bindings/rust/inputtino/tests/keyboard.rs +73 -0
  102. package/engine/vendor/inputtino/bindings/rust/inputtino/tests/mouse.rs +139 -0
  103. package/engine/vendor/inputtino/bindings/rust/inputtino-sys/.dockerignore +1 -0
  104. package/engine/vendor/inputtino/bindings/rust/inputtino-sys/Cargo.toml +12 -0
  105. package/engine/vendor/inputtino/bindings/rust/inputtino-sys/build.rs +48 -0
  106. package/engine/vendor/inputtino/bindings/rust/inputtino-sys/src/lib.rs +5 -0
  107. package/engine/vendor/inputtino/bindings/rust/inputtino-sys/wrapper.h +1 -0
  108. package/engine/vendor/inputtino/cmake/utils.cmake +9 -0
  109. package/engine/vendor/inputtino/docker/Dockerfile +70 -0
  110. package/engine/vendor/inputtino/include/inputtino/input.h +324 -0
  111. package/engine/vendor/inputtino/include/inputtino/input.hpp +466 -0
  112. package/engine/vendor/inputtino/include/inputtino/result.hpp +37 -0
  113. package/engine/vendor/inputtino/share/pkgconfig/libinputtino.pc.in +17 -0
  114. package/engine/vendor/inputtino/src/c-bindings/helpers.hpp +19 -0
  115. package/engine/vendor/inputtino/src/c-bindings/joypad_ps5.cpp +115 -0
  116. package/engine/vendor/inputtino/src/c-bindings/joypad_switch.cpp +63 -0
  117. package/engine/vendor/inputtino/src/c-bindings/joypad_xone.cpp +62 -0
  118. package/engine/vendor/inputtino/src/c-bindings/keyboard.cpp +42 -0
  119. package/engine/vendor/inputtino/src/c-bindings/mouse.cpp +67 -0
  120. package/engine/vendor/inputtino/src/c-bindings/pen_tablet.cpp +50 -0
  121. package/engine/vendor/inputtino/src/c-bindings/touchscreen.cpp +43 -0
  122. package/engine/vendor/inputtino/src/c-bindings/trackpad.cpp +49 -0
  123. package/engine/vendor/inputtino/src/uhid/README.adoc +63 -0
  124. package/engine/vendor/inputtino/src/uhid/include/crc32.hpp +38 -0
  125. package/engine/vendor/inputtino/src/uhid/include/uhid/protected_types.hpp +36 -0
  126. package/engine/vendor/inputtino/src/uhid/include/uhid/ps5.hpp +550 -0
  127. package/engine/vendor/inputtino/src/uhid/include/uhid/uhid.hpp +168 -0
  128. package/engine/vendor/inputtino/src/uhid/joypad_ps5.cpp +580 -0
  129. package/engine/vendor/inputtino/src/uinput/include/inputtino/keyboard.hpp +84 -0
  130. package/engine/vendor/inputtino/src/uinput/include/inputtino/protected_ps5_types.hpp +7 -0
  131. package/engine/vendor/inputtino/src/uinput/include/inputtino/protected_types.hpp +110 -0
  132. package/engine/vendor/inputtino/src/uinput/joypad_nintendo.cpp +190 -0
  133. package/engine/vendor/inputtino/src/uinput/joypad_ps.cpp +203 -0
  134. package/engine/vendor/inputtino/src/uinput/joypad_utils.hpp +246 -0
  135. package/engine/vendor/inputtino/src/uinput/joypad_xbox.cpp +190 -0
  136. package/engine/vendor/inputtino/src/uinput/keyboard.cpp +120 -0
  137. package/engine/vendor/inputtino/src/uinput/mouse.cpp +199 -0
  138. package/engine/vendor/inputtino/src/uinput/pentablet.cpp +162 -0
  139. package/engine/vendor/inputtino/src/uinput/touchscreen.cpp +140 -0
  140. package/engine/vendor/inputtino/src/uinput/trackpad.cpp +192 -0
  141. package/examples/reference-client.html +428 -0
  142. package/package.json +38 -0
@@ -0,0 +1,63 @@
1
+ #include "helpers.hpp"
2
+ #include <inputtino/input.h>
3
+
4
+ InputtinoSwitchJoypad *inputtino_joypad_switch_create(const InputtinoDeviceDefinition *device,
5
+ const InputtinoErrorHandler *eh) {
6
+ auto joypad_ = inputtino::SwitchJoypad::create({
7
+ .name = device->name ? device->name : "Inputtino virtual device",
8
+ .vendor_id = device->vendor_id,
9
+ .product_id = device->product_id,
10
+ .version = device->version,
11
+ .device_phys = device->device_phys ? device->device_phys : "00:11:22:33:44:55",
12
+ .device_uniq = device->device_uniq ? device->device_uniq : "00:11:22:33:44:55",
13
+ });
14
+ if (joypad_) {
15
+ return reinterpret_cast<InputtinoSwitchJoypad *>(new inputtino::SwitchJoypad(std::move(*joypad_)));
16
+ } else {
17
+ eh->eh(joypad_.getErrorMessage().c_str(), eh->user_data);
18
+ return nullptr;
19
+ }
20
+ }
21
+
22
+ char **inputtino_joypad_switch_get_nodes(InputtinoSwitchJoypad *joypad, int *num_nodes) {
23
+ return c_get_nodes(joypad, num_nodes);
24
+ }
25
+
26
+ void inputtino_joypad_switch_set_pressed_buttons(InputtinoSwitchJoypad *joypad, int newly_pressed) {
27
+ if (joypad) {
28
+ reinterpret_cast<inputtino::SwitchJoypad *>(joypad)->set_pressed_buttons(newly_pressed);
29
+ }
30
+ }
31
+
32
+ void inputtino_joypad_switch_set_triggers(InputtinoSwitchJoypad *joypad, short left_trigger, short right_trigger) {
33
+ if (joypad) {
34
+ reinterpret_cast<inputtino::SwitchJoypad *>(joypad)->set_triggers(left_trigger, right_trigger);
35
+ }
36
+ }
37
+
38
+ void inputtino_joypad_switch_set_stick(InputtinoSwitchJoypad *joypad,
39
+ enum INPUTTINO_JOYPAD_STICK_POSITION stick_type,
40
+ short x,
41
+ short y) {
42
+ if (joypad) {
43
+ reinterpret_cast<inputtino::SwitchJoypad *>(joypad)->set_stick(inputtino::Joypad::STICK_POSITION(stick_type),
44
+ x,
45
+ y);
46
+ }
47
+ }
48
+
49
+ void inputtino_joypad_switch_set_on_rumble(InputtinoSwitchJoypad *joypad,
50
+ InputtinoJoypadRumbleFn rumble_fn,
51
+ void *user_data) {
52
+ if (joypad) {
53
+ reinterpret_cast<inputtino::SwitchJoypad *>(joypad)->set_on_rumble(
54
+ [user_data, rumble_fn](short left, short right) { rumble_fn(left, right, user_data); });
55
+ }
56
+ }
57
+
58
+ void inputtino_joypad_switch_destroy(InputtinoSwitchJoypad *joypad) {
59
+ if (joypad) {
60
+ auto joypad_ptr = reinterpret_cast<inputtino::SwitchJoypad *>(joypad);
61
+ delete joypad_ptr;
62
+ }
63
+ }
@@ -0,0 +1,62 @@
1
+ #include "helpers.hpp"
2
+ #include <inputtino/input.h>
3
+
4
+ InputtinoXOneJoypad *inputtino_joypad_xone_create(const InputtinoDeviceDefinition *device, const InputtinoErrorHandler *eh) {
5
+ auto joypad_ = inputtino::XboxOneJoypad::create({
6
+ .name = device->name ? device->name : "Inputtino virtual device",
7
+ .vendor_id = device->vendor_id,
8
+ .product_id = device->product_id,
9
+ .version = device->version,
10
+ .device_phys = device->device_phys ? device->device_phys : "00:11:22:33:44:55",
11
+ .device_uniq = device->device_uniq ? device->device_uniq : "00:11:22:33:44:55",
12
+ });
13
+ if (joypad_) {
14
+ return reinterpret_cast<InputtinoXOneJoypad *>(new inputtino::XboxOneJoypad(std::move(*joypad_)));
15
+ } else {
16
+ eh->eh(joypad_.getErrorMessage().c_str(), eh->user_data);
17
+ return nullptr;
18
+ }
19
+ }
20
+
21
+ char **inputtino_joypad_xone_get_nodes(InputtinoXOneJoypad *joypad, int *num_nodes) {
22
+ return c_get_nodes(joypad, num_nodes);
23
+ }
24
+
25
+ void inputtino_joypad_xone_set_pressed_buttons(InputtinoXOneJoypad *joypad, int newly_pressed) {
26
+ if (joypad) {
27
+ reinterpret_cast<inputtino::XboxOneJoypad *>(joypad)->set_pressed_buttons(newly_pressed);
28
+ }
29
+ }
30
+
31
+ void inputtino_joypad_xone_set_triggers(InputtinoXOneJoypad *joypad, short left_trigger, short right_trigger) {
32
+ if (joypad) {
33
+ reinterpret_cast<inputtino::XboxOneJoypad *>(joypad)->set_triggers(left_trigger, right_trigger);
34
+ }
35
+ }
36
+
37
+ void inputtino_joypad_xone_set_stick(InputtinoXOneJoypad *joypad,
38
+ enum INPUTTINO_JOYPAD_STICK_POSITION stick_type,
39
+ short x,
40
+ short y) {
41
+ if (joypad) {
42
+ reinterpret_cast<inputtino::XboxOneJoypad *>(joypad)->set_stick(inputtino::Joypad::STICK_POSITION(stick_type),
43
+ x,
44
+ y);
45
+ }
46
+ }
47
+
48
+ void inputtino_joypad_xone_set_on_rumble(InputtinoXOneJoypad *joypad,
49
+ InputtinoJoypadRumbleFn rumble_fn,
50
+ void *user_data) {
51
+ if (joypad) {
52
+ reinterpret_cast<inputtino::XboxOneJoypad *>(joypad)->set_on_rumble(
53
+ [user_data, rumble_fn](short left, short right) { rumble_fn(left, right, user_data); });
54
+ }
55
+ }
56
+
57
+ void inputtino_joypad_xone_destroy(InputtinoXOneJoypad *joypad) {
58
+ if (joypad) {
59
+ auto joypad_ptr = reinterpret_cast<inputtino::XboxOneJoypad *>(joypad);
60
+ delete joypad_ptr;
61
+ }
62
+ }
@@ -0,0 +1,42 @@
1
+ #include "helpers.hpp"
2
+ #include <inputtino/input.h>
3
+
4
+ InputtinoKeyboard *inputtino_keyboard_create(const InputtinoDeviceDefinition *device, const InputtinoErrorHandler *eh) {
5
+ auto keyboard_ = inputtino::Keyboard::create({
6
+ .name = device->name ? device->name : "Inputtino virtual device",
7
+ .vendor_id = device->vendor_id,
8
+ .product_id = device->product_id,
9
+ .version = device->version,
10
+ .device_phys = device->device_phys ? device->device_phys : "00:11:22:33:44:55",
11
+ .device_uniq = device->device_uniq ? device->device_uniq : "00:11:22:33:44:55",
12
+ });
13
+ if (keyboard_) {
14
+ return reinterpret_cast<InputtinoKeyboard *>(new inputtino::Keyboard(std::move(*keyboard_)));
15
+ } else {
16
+ eh->eh(keyboard_.getErrorMessage().c_str(), eh->user_data);
17
+ return nullptr;
18
+ }
19
+ }
20
+
21
+ char **inputtino_keyboard_get_nodes(InputtinoKeyboard *keyboard, int *num_nodes) {
22
+ return c_get_nodes(keyboard, num_nodes);
23
+ }
24
+
25
+ void inputtino_keyboard_press(InputtinoKeyboard *keyboard, short key_code) {
26
+ if (keyboard) {
27
+ reinterpret_cast<inputtino::Keyboard *>(keyboard)->press(key_code);
28
+ }
29
+ }
30
+
31
+ void inputtino_keyboard_release(InputtinoKeyboard *keyboard, short key_code) {
32
+ if (keyboard) {
33
+ reinterpret_cast<inputtino::Keyboard *>(keyboard)->release(key_code);
34
+ }
35
+ }
36
+
37
+ void inputtino_keyboard_destroy(InputtinoKeyboard *keyboard) {
38
+ if (keyboard) {
39
+ auto ptr = reinterpret_cast<inputtino::Keyboard *>(keyboard);
40
+ delete ptr;
41
+ }
42
+ }
@@ -0,0 +1,67 @@
1
+ #include "helpers.hpp"
2
+ #include <inputtino/input.h>
3
+ #include <inputtino/input.hpp>
4
+
5
+ InputtinoMouse *inputtino_mouse_create(const InputtinoDeviceDefinition *device, const InputtinoErrorHandler *eh) {
6
+ auto mouse_ = inputtino::Mouse::create({
7
+ .name = device->name ? device->name : "Inputtino virtual device",
8
+ .vendor_id = device->vendor_id,
9
+ .product_id = device->product_id,
10
+ .version = device->version,
11
+ .device_phys = device->device_phys ? device->device_phys : "00:11:22:33:44:55",
12
+ .device_uniq = device->device_uniq ? device->device_uniq : "00:11:22:33:44:55",
13
+ });
14
+ if (mouse_) {
15
+ return reinterpret_cast<InputtinoMouse *>(new inputtino::Mouse(std::move(*mouse_)));
16
+ } else {
17
+ eh->eh(mouse_.getErrorMessage().c_str(), eh->user_data);
18
+ return nullptr;
19
+ }
20
+ }
21
+
22
+ char **inputtino_mouse_get_nodes(InputtinoMouse *mouse, int *num_nodes) {
23
+ return c_get_nodes(mouse, num_nodes);
24
+ }
25
+
26
+ void inputtino_mouse_move(InputtinoMouse *mouse, int delta_x, int delta_y) {
27
+ if (mouse) {
28
+ reinterpret_cast<inputtino::Mouse *>(mouse)->move(delta_x, delta_y);
29
+ }
30
+ }
31
+
32
+ void inputtino_mouse_move_absolute(InputtinoMouse *mouse, int x, int y, int screen_width, int screen_height) {
33
+ if (mouse) {
34
+ reinterpret_cast<inputtino::Mouse *>(mouse)->move_abs(x, y, screen_width, screen_height);
35
+ }
36
+ }
37
+
38
+ void inputtino_mouse_press_button(InputtinoMouse *mouse, enum INPUTTINO_MOUSE_BUTTON button) {
39
+ if (mouse) {
40
+ reinterpret_cast<inputtino::Mouse *>(mouse)->press(inputtino::Mouse::MOUSE_BUTTON(button));
41
+ }
42
+ }
43
+
44
+ void inputtino_mouse_release_button(InputtinoMouse *mouse, enum INPUTTINO_MOUSE_BUTTON button) {
45
+ if (mouse) {
46
+ reinterpret_cast<inputtino::Mouse *>(mouse)->release(inputtino::Mouse::MOUSE_BUTTON(button));
47
+ }
48
+ }
49
+
50
+ void inputtino_mouse_scroll_vertical(InputtinoMouse *mouse, int high_res_distance) {
51
+ if (mouse) {
52
+ reinterpret_cast<inputtino::Mouse *>(mouse)->vertical_scroll(high_res_distance);
53
+ }
54
+ }
55
+
56
+ void inputtino_mouse_scroll_horizontal(InputtinoMouse *mouse, int high_res_distance) {
57
+ if (mouse) {
58
+ reinterpret_cast<inputtino::Mouse *>(mouse)->horizontal_scroll(high_res_distance);
59
+ }
60
+ }
61
+
62
+ void inputtino_mouse_destroy(InputtinoMouse *mouse) {
63
+ if (mouse) {
64
+ inputtino::Mouse *mouse_ptr = reinterpret_cast<inputtino::Mouse *>(mouse);
65
+ delete mouse_ptr;
66
+ }
67
+ }
@@ -0,0 +1,50 @@
1
+ #include "helpers.hpp"
2
+ #include <inputtino/input.h>
3
+
4
+ InputtinoPenTablet *inputtino_pen_tablet_create(const InputtinoDeviceDefinition *device, const InputtinoErrorHandler *eh) {
5
+ auto pen_tablet_ = inputtino::PenTablet::create({
6
+ .name = device->name ? device->name : "Inputtino virtual device",
7
+ .vendor_id = device->vendor_id,
8
+ .product_id = device->product_id,
9
+ .version = device->version,
10
+ .device_phys = device->device_phys ? device->device_phys : "00:11:22:33:44:55",
11
+ .device_uniq = device->device_uniq ? device->device_uniq : "00:11:22:33:44:55",
12
+ });
13
+ if (pen_tablet_) {
14
+ return reinterpret_cast<InputtinoPenTablet *>(new inputtino::PenTablet(std::move(*pen_tablet_)));
15
+ } else {
16
+ eh->eh(pen_tablet_.getErrorMessage().c_str(), eh->user_data);
17
+ return nullptr;
18
+ }
19
+ }
20
+
21
+ char **inputtino_pen_tablet_get_nodes(InputtinoPenTablet *pen_tablet, int *num_nodes) {
22
+ return c_get_nodes(pen_tablet, num_nodes);
23
+ }
24
+
25
+ void inputtino_pen_tablet_place_tool(InputtinoPenTablet *pen_tablet,
26
+ enum INPUTTINO_PEN_TOOL_TYPE tool_type,
27
+ float x,
28
+ float y,
29
+ float pressure,
30
+ float distance,
31
+ float tilt_x,
32
+ float tilt_y) {
33
+ if (pen_tablet) {
34
+ reinterpret_cast<inputtino::PenTablet *>(pen_tablet)
35
+ ->place_tool(inputtino::PenTablet::TOOL_TYPE(tool_type), x, y, pressure, distance, tilt_x, tilt_y);
36
+ }
37
+ }
38
+
39
+ void inputtino_pen_tablet_set_button(InputtinoPenTablet *pen_tablet, enum INPUTTINO_PEN_BTN_TYPE button, bool pressed) {
40
+ if (pen_tablet) {
41
+ reinterpret_cast<inputtino::PenTablet *>(pen_tablet)->set_btn(inputtino::PenTablet::BTN_TYPE(button), pressed);
42
+ }
43
+ }
44
+
45
+ void inputtino_pen_tablet_destroy(InputtinoPenTablet *pen_tablet) {
46
+ if(pen_tablet){
47
+ inputtino::PenTablet *pen_tablet_ = reinterpret_cast<inputtino::PenTablet *>(pen_tablet);
48
+ delete pen_tablet_;
49
+ }
50
+ }
@@ -0,0 +1,43 @@
1
+ #include "helpers.hpp"
2
+ #include <inputtino/input.h>
3
+
4
+ InputtinoTouchscreen *inputtino_touchscreen_create(const InputtinoDeviceDefinition *device, const InputtinoErrorHandler *eh) {
5
+ auto touchscreen_ = inputtino::TouchScreen::create({
6
+ .name = device->name ? device->name : "Inputtino virtual device",
7
+ .vendor_id = device->vendor_id,
8
+ .product_id = device->product_id,
9
+ .version = device->version,
10
+ .device_phys = device->device_phys ? device->device_phys : "00:11:22:33:44:55",
11
+ .device_uniq = device->device_uniq ? device->device_uniq : "00:11:22:33:44:55",
12
+ });
13
+ if (touchscreen_) {
14
+ return reinterpret_cast<InputtinoTouchscreen *>(new inputtino::TouchScreen(std::move(*touchscreen_)));
15
+ } else {
16
+ eh->eh(touchscreen_.getErrorMessage().c_str(), eh->user_data);
17
+ return nullptr;
18
+ }
19
+ }
20
+
21
+ char **inputtino_touchscreen_get_nodes(InputtinoTouchscreen *touchscreen, int *num_nodes) {
22
+ return c_get_nodes(touchscreen, num_nodes);
23
+ }
24
+
25
+ void inputtino_touchscreen_place_finger(
26
+ InputtinoTouchscreen *touchscreen, int finger_nr, float x, float y, float pressure, int orientation) {
27
+ if (touchscreen) {
28
+ reinterpret_cast<inputtino::TouchScreen *>(touchscreen)->place_finger(finger_nr, x, y, pressure, orientation);
29
+ }
30
+ }
31
+
32
+ void inputtino_touchscreen_release_finger(InputtinoTouchscreen *touchscreen, int finger_nr) {
33
+ if (touchscreen) {
34
+ reinterpret_cast<inputtino::TouchScreen *>(touchscreen)->release_finger(finger_nr);
35
+ }
36
+ }
37
+
38
+ void inputtino_touchscreen_destroy(InputtinoTouchscreen *touchscreen) {
39
+ if (touchscreen) {
40
+ inputtino::TouchScreen *touch_ptr = reinterpret_cast<inputtino::TouchScreen *>(touchscreen);
41
+ delete touch_ptr;
42
+ }
43
+ }
@@ -0,0 +1,49 @@
1
+ #include "helpers.hpp"
2
+ #include <inputtino/input.h>
3
+
4
+ InputtinoTrackpad *inputtino_trackpad_create(const InputtinoDeviceDefinition *device, const InputtinoErrorHandler *eh) {
5
+ auto trackpad_ = inputtino::Trackpad::create({
6
+ .name = device->name ? device->name : "Inputtino virtual device",
7
+ .vendor_id = device->vendor_id,
8
+ .product_id = device->product_id,
9
+ .version = device->version,
10
+ .device_phys = device->device_phys ? device->device_phys : "00:11:22:33:44:55",
11
+ .device_uniq = device->device_uniq ? device->device_uniq : "00:11:22:33:44:55",
12
+ });
13
+ if (trackpad_) {
14
+ return reinterpret_cast<InputtinoTrackpad *>(new inputtino::Trackpad(std::move(*trackpad_)));
15
+ } else {
16
+ eh->eh(trackpad_.getErrorMessage().c_str(), eh->user_data);
17
+ return nullptr;
18
+ }
19
+ }
20
+
21
+ char **inputtino_trackpad_get_nodes(InputtinoTrackpad *trackpad, int *num_nodes) {
22
+ return c_get_nodes(trackpad, num_nodes);
23
+ }
24
+
25
+ void inputtino_trackpad_place_finger(
26
+ InputtinoTrackpad *trackpad, int finger_nr, float x, float y, float pressure, int orientation) {
27
+ if (trackpad) {
28
+ reinterpret_cast<inputtino::Trackpad *>(trackpad)->place_finger(finger_nr, x, y, pressure, orientation);
29
+ }
30
+ }
31
+
32
+ void inputtino_trackpad_release_finger(InputtinoTrackpad *trackpad, int finger_nr) {
33
+ if (trackpad) {
34
+ reinterpret_cast<inputtino::Trackpad *>(trackpad)->release_finger(finger_nr);
35
+ }
36
+ }
37
+
38
+ void inputtino_trackpad_set_left_btn(InputtinoTrackpad *trackpad, bool pressed) {
39
+ if (trackpad) {
40
+ reinterpret_cast<inputtino::Trackpad *>(trackpad)->set_left_btn(pressed);
41
+ }
42
+ }
43
+
44
+ void inputtino_trackpad_destroy(InputtinoTrackpad *trackpad) {
45
+ if (trackpad) {
46
+ inputtino::Trackpad *trackpad_ptr = reinterpret_cast<inputtino::Trackpad *>(trackpad);
47
+ delete trackpad_ptr;
48
+ }
49
+ }
@@ -0,0 +1,63 @@
1
+ == What's this?
2
+
3
+ Here we implement virtual devices using the low level https://dri.freedesktop.org/docs/drm/hid/uhid.html[uhid]
4
+
5
+ == Why can't we use udev?
6
+
7
+ To answer this question we need to dive deeper into how the DualSense controller works, bear with me..
8
+
9
+ The PS4 and PS5 controllers also include a Gyroscope, Accelerometer and a Touchpad.
10
+ The DualSense controller also includes a microphone and a speaker.
11
+ The open source driver `hid-playstation` exposes these features as 3 separate input devices:
12
+
13
+ ----
14
+ /dev/input/event20: Sony Interactive Entertainment Wireless Controller
15
+ /dev/input/event21: Sony Interactive Entertainment Wireless Controller Motion Sensors
16
+ /dev/input/event22: Sony Interactive Entertainment Wireless Controller Touchpad
17
+ ----
18
+
19
+ Ideally we should be able to use udev to create these devices independently, unfortunately the issue is in linking these 3 devices together.
20
+
21
+ === How SDL2 links these 3 devices into a single joypad?
22
+
23
+ First off, SDL2 assumes that every `/dev/input/event*` device might be a joypad, so it opens them all to check if they are based on some heuristics.
24
+ Normally, the motion sensor device that you create with udev will be opened by SDL2 and it will be recognized as a joypad.
25
+ To get around this you can hardcode the device name to end with one of the https://github.com/libsdl-org/SDL/blob/d4f4aa745a9d9c280d5016322a2473c9d2e077a0/src/joystick/SDL_gamepad.c#L2575-L2589[SDL_ShouldIgnoreGamepad] hardcoded strings.
26
+ This will get around the first hurdle and actually recognize the udev created motion sensor as an actual sensor.
27
+
28
+ The main issue seems to be in linking these 3 devices together: the way SDL2 does this is to match the `uniq` identifier (`EVIOCGUNIQ` https://github.com/libsdl-org/SDL/blob/4189edaeb7ce4da9ab420b98904fa22196fb3dca/src/joystick/linux/SDL_sysjoystick.c#L1508[in this method]) between what is recognised as sensor and what is recognised as joypad.
29
+ Unfortunately, there's no way to set the `uniq` for an uinput device; there's https://lore.kernel.org/linux-bluetooth/20191201145357.ybq5gfty4ulnfasq@pali/t/#u[a proposal] to add this to the Linux kernel but as of March 2024 this has still not being merged.
30
+ So what happens in practice is that SDL ends up discarding that sensor and just using the joypad instead.
31
+
32
+ == How UHID solves this?
33
+
34
+ UHID allows us to completely replicate the DualSense controller at a lower level.
35
+ The device that we'll create via UHID will be picked up by `hid-playstation` just like a USB connected DualSense controller would be, which in turn will create the `/dev/input/event` devices and downstream applications will see the 3 devices as they should be.
36
+
37
+ == What are the requirements to use UHID?
38
+
39
+ You need additional permission in order to access `/dev/uhid` (normally exposed as `root` only). +
40
+
41
+ First we'll add our user to the `input` group:
42
+
43
+ ----
44
+ sudo usermod -a -G input $USER
45
+ ----
46
+
47
+ Then we add an udev rule to allow access to `/dev/uhid`:
48
+
49
+ ----
50
+ echo 'KERNEL=="uhid", GROUP="input", MODE="0660"' | sudo tee /etc/udev/rules.d/99-uhid.rules
51
+ ----
52
+
53
+ Finally, we have to make sure that the `uhid` kernel module is loaded at boot:
54
+
55
+ ----
56
+ echo "uhid" | sudo tee /etc/modules-load.d/uhid.conf
57
+ ----
58
+
59
+ === Useful resources (?)
60
+
61
+ - https://github.com/nondebug/dualsense
62
+ - https://github.com/torvalds/linux/blob/master/drivers/hid/hid-playstation.c
63
+ - https://gitlab.freedesktop.org/libevdev/hid-tools/
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Adapted from https://gist.github.com/timepp/1f678e200d9e0f2a043a9ec6b3690635
3
+ * uses constexpr to generate a CRC32 table at compile time
4
+ */
5
+ #pragma once
6
+
7
+ #include <array>
8
+ #include <cstdint>
9
+
10
+ static constexpr auto generate_table(std::uint32_t polynomial = 0xEDB88320) {
11
+ std::array<std::uint32_t, 256> table{};
12
+ for (std::uint32_t i = 0; i < 256; i++) {
13
+ std::uint32_t c = i;
14
+ for (std::size_t j = 0; j < 8; j++) {
15
+ if (c & 1) {
16
+ c = polynomial ^ (c >> 1);
17
+ } else {
18
+ c >>= 1;
19
+ }
20
+ }
21
+ table[i] = c;
22
+ }
23
+ return table;
24
+ }
25
+
26
+ // Static lookup table generated at compile time
27
+ static constexpr auto lookup_table = generate_table();
28
+
29
+ /**
30
+ * Calculate the CRC32 of a buffer
31
+ */
32
+ static constexpr uint32_t CRC32(const unsigned char *buffer, uint32_t length, uint32_t seed = 0) {
33
+ uint32_t c = seed ^ 0xFFFFFFFF;
34
+ for (size_t i = 0; i < length; ++i) {
35
+ c = lookup_table[(c ^ buffer[i]) & 0xFF] ^ (c >> 8);
36
+ }
37
+ return c ^ 0xFFFFFFFF;
38
+ }
@@ -0,0 +1,36 @@
1
+ #pragma once
2
+ #include <functional>
3
+ #include <inputtino/input.hpp>
4
+ #include <optional>
5
+ #include <uhid/ps5.hpp>
6
+ #include <uhid/uhid.hpp>
7
+
8
+ namespace inputtino {
9
+ struct PS5JoypadState {
10
+ std::shared_ptr<uhid::Device> dev;
11
+ /**
12
+ * This will be the MAC address of the device
13
+ *
14
+ * IMPORTANT: this needs to be unique for each virtual device,
15
+ * otherwise the kernel driver will return an error:
16
+ * "Duplicate device found for MAC address XX:XX:XX:XX"
17
+ *
18
+ * We also use this information internally to unique match a device with the
19
+ * /dev/input/devXX files; see get_nodes()
20
+ */
21
+ unsigned char mac_address[6] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
22
+ uint16_t vendor_id;
23
+
24
+ uhid::dualsense_input_report current_state = {};
25
+ uint8_t last_touch_id = 0;
26
+
27
+ std::optional<std::function<void(int, int)>> on_rumble = std::nullopt;
28
+ std::optional<std::function<void(int, int, int)>> on_led = std::nullopt;
29
+ std::optional<std::function<void(const PS5Joypad::TriggerEffect &)>> on_trigger_effect = std::nullopt;
30
+ uint32_t last_left_trigger_event = 0;
31
+ uint32_t last_right_trigger_event = 0;
32
+
33
+ bool stop_repeat_thread = false;
34
+ bool is_bluetooth = true;
35
+ };
36
+ } // namespace inputtino