|
6 | 6 | // standard includes |
7 | 7 | #include <algorithm> |
8 | 8 | #include <array> |
| 9 | +#include <atomic> |
9 | 10 | #include <chrono> |
10 | 11 | #include <cmath> |
11 | 12 | #include <cstddef> |
12 | 13 | #include <cstdint> |
13 | 14 | #include <cstring> |
| 15 | +#include <numbers> |
14 | 16 | #include <optional> |
15 | 17 | #include <span> |
16 | 18 | #include <utility> |
@@ -61,6 +63,10 @@ namespace lvh::reports { |
61 | 63 |
|
62 | 64 | constexpr auto dualsense_flag2_compatible_vibration = std::byte {0x04}; |
63 | 65 |
|
| 66 | + constexpr auto dualsense_acceleration_scale = 9.80665F * 100.0F; |
| 67 | + |
| 68 | + constexpr auto dualsense_gyroscope_scale = 1145.0F * std::numbers::pi_v<float> / 180.0F; |
| 69 | + |
64 | 70 | constexpr std::uint8_t switch_rumble_and_subcommand_output_report_id = 0x01; |
65 | 71 |
|
66 | 72 | constexpr std::uint8_t switch_rumble_only_output_report_id = 0x10; |
@@ -613,6 +619,19 @@ namespace lvh::reports { |
613 | 619 | return static_cast<std::uint16_t>((static_cast<std::uint64_t>(elapsed) * 3U) / 16U); |
614 | 620 | } |
615 | 621 |
|
| 622 | + std::uint8_t dualsense_sequence_number() { |
| 623 | + static std::atomic_uint32_t sequence_number = 0; |
| 624 | + return static_cast<std::uint8_t>((sequence_number.fetch_add(1U, std::memory_order_relaxed) + 1U) % 255U); |
| 625 | + } |
| 626 | + |
| 627 | + std::uint32_t dualsense_sensor_timestamp() { |
| 628 | + const auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>( |
| 629 | + std::chrono::steady_clock::now().time_since_epoch() |
| 630 | + ) |
| 631 | + .count(); |
| 632 | + return static_cast<std::uint32_t>(static_cast<std::uint64_t>(elapsed) / 333U); |
| 633 | + } |
| 634 | + |
616 | 635 | std::vector<std::uint8_t> pack_dualshock4_input_report(const DeviceProfile &profile, const GamepadState &state) { |
617 | 636 | const auto is_bluetooth = profile.bus_type == BusType::bluetooth; |
618 | 637 | const auto payload_offset = is_bluetooth ? 3U : 1U; |
@@ -722,6 +741,7 @@ namespace lvh::reports { |
722 | 741 | report[payload_offset + 3U] = to_byte(normalize_u8_axis(-normalized.right_stick.y)); |
723 | 742 | report[payload_offset + 4U] = to_byte(normalize_trigger(normalized.left_trigger)); |
724 | 743 | report[payload_offset + 5U] = to_byte(normalize_trigger(normalized.right_trigger)); |
| 744 | + report[payload_offset + 6U] = to_byte(dualsense_sequence_number()); |
725 | 745 | report[payload_offset + 7U] = to_byte(hat_from_buttons(normalized.buttons)); |
726 | 746 |
|
727 | 747 | if (normalized.buttons.test(GamepadButton::x)) { |
@@ -773,15 +793,16 @@ namespace lvh::reports { |
773 | 793 | } |
774 | 794 |
|
775 | 795 | if (normalized.gyroscope) { |
776 | | - write_i16(report, payload_offset + 15U, scale_i16(normalized.gyroscope->x, 1145.0F)); |
777 | | - write_i16(report, payload_offset + 17U, scale_i16(normalized.gyroscope->y, 1145.0F)); |
778 | | - write_i16(report, payload_offset + 19U, scale_i16(normalized.gyroscope->z, 1145.0F)); |
| 796 | + write_i16(report, payload_offset + 15U, scale_i16(normalized.gyroscope->x, dualsense_gyroscope_scale)); |
| 797 | + write_i16(report, payload_offset + 17U, scale_i16(normalized.gyroscope->y, dualsense_gyroscope_scale)); |
| 798 | + write_i16(report, payload_offset + 19U, scale_i16(normalized.gyroscope->z, dualsense_gyroscope_scale)); |
779 | 799 | } |
780 | 800 | if (normalized.acceleration) { |
781 | | - write_i16(report, payload_offset + 21U, scale_i16(normalized.acceleration->x, 100.0F)); |
782 | | - write_i16(report, payload_offset + 23U, scale_i16(normalized.acceleration->y, 100.0F)); |
783 | | - write_i16(report, payload_offset + 25U, scale_i16(normalized.acceleration->z, 100.0F)); |
| 801 | + write_i16(report, payload_offset + 21U, scale_i16(normalized.acceleration->x, dualsense_acceleration_scale)); |
| 802 | + write_i16(report, payload_offset + 23U, scale_i16(normalized.acceleration->y, dualsense_acceleration_scale)); |
| 803 | + write_i16(report, payload_offset + 25U, scale_i16(normalized.acceleration->z, dualsense_acceleration_scale)); |
784 | 804 | } |
| 805 | + write_u32(report, payload_offset + 27U, dualsense_sensor_timestamp()); |
785 | 806 |
|
786 | 807 | write_dualsense_touch_contact(report, payload_offset + 32U, normalized.touchpad_contacts[0]); |
787 | 808 | write_dualsense_touch_contact(report, payload_offset + 36U, normalized.touchpad_contacts[1]); |
|
0 commit comments