66// standard includes
77#include < algorithm>
88#include < array>
9+ #include < atomic>
910#include < chrono>
1011#include < cmath>
1112#include < cstddef>
1213#include < cstdint>
1314#include < cstring>
15+ #include < numbers>
1416#include < optional>
1517#include < span>
1618#include < utility>
@@ -31,6 +33,8 @@ namespace lvh::reports {
3133
3234 constexpr auto dualshock4_bt_input_report_id = std::byte {0x11 };
3335
36+ constexpr auto dualshock4_bt_input_hid_present = std::byte {0x80 };
37+
3438 constexpr auto dualshock4_bt_output_report_id = std::byte {0x11 };
3539
3640 constexpr auto dualshock4_output_hwctl_crc32 = std::byte {0x40 };
@@ -61,6 +65,10 @@ namespace lvh::reports {
6165
6266 constexpr auto dualsense_flag2_compatible_vibration = std::byte {0x04 };
6367
68+ constexpr auto dualsense_acceleration_scale = 9 .80665F * 100 .0F ;
69+
70+ constexpr auto dualsense_gyroscope_scale = 1145 .0F * std::numbers::pi_v<float > / 180 .0F ;
71+
6472 constexpr std::uint8_t switch_rumble_and_subcommand_output_report_id = 0x01 ;
6573
6674 constexpr std::uint8_t switch_rumble_only_output_report_id = 0x10 ;
@@ -613,6 +621,19 @@ namespace lvh::reports {
613621 return static_cast <std::uint16_t >((static_cast <std::uint64_t >(elapsed) * 3U ) / 16U );
614622 }
615623
624+ std::uint8_t dualsense_sequence_number () {
625+ static std::atomic_uint32_t sequence_number = 0 ;
626+ return static_cast <std::uint8_t >((sequence_number.fetch_add (1U , std::memory_order_relaxed) + 1U ) % 255U );
627+ }
628+
629+ std::uint32_t dualsense_sensor_timestamp () {
630+ const auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(
631+ std::chrono::steady_clock::now ().time_since_epoch ()
632+ )
633+ .count ();
634+ return static_cast <std::uint32_t >(static_cast <std::uint64_t >(elapsed) / 333U );
635+ }
636+
616637 std::vector<std::uint8_t > pack_dualshock4_input_report (const DeviceProfile &profile, const GamepadState &state) {
617638 const auto is_bluetooth = profile.bus_type == BusType::bluetooth;
618639 const auto payload_offset = is_bluetooth ? 3U : 1U ;
@@ -627,6 +648,9 @@ namespace lvh::reports {
627648
628649 ByteReport report (profile.input_report_size , zero_byte);
629650 report[0 ] = is_bluetooth ? dualshock4_bt_input_report_id : to_byte (profile.report_id );
651+ if (is_bluetooth) {
652+ report[1 ] = dualshock4_bt_input_hid_present;
653+ }
630654
631655 report[payload_offset + 0U ] = to_byte (normalize_u8_axis (normalized.left_stick .x ));
632656 report[payload_offset + 1U ] = to_byte (normalize_u8_axis (-normalized.left_stick .y ));
@@ -722,6 +746,7 @@ namespace lvh::reports {
722746 report[payload_offset + 3U ] = to_byte (normalize_u8_axis (-normalized.right_stick .y ));
723747 report[payload_offset + 4U ] = to_byte (normalize_trigger (normalized.left_trigger ));
724748 report[payload_offset + 5U ] = to_byte (normalize_trigger (normalized.right_trigger ));
749+ report[payload_offset + 6U ] = to_byte (dualsense_sequence_number ());
725750 report[payload_offset + 7U ] = to_byte (hat_from_buttons (normalized.buttons ));
726751
727752 if (normalized.buttons .test (GamepadButton::x)) {
@@ -773,15 +798,16 @@ namespace lvh::reports {
773798 }
774799
775800 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 ));
801+ write_i16 (report, payload_offset + 15U , scale_i16 (normalized.gyroscope ->x , dualsense_gyroscope_scale ));
802+ write_i16 (report, payload_offset + 17U , scale_i16 (normalized.gyroscope ->y , dualsense_gyroscope_scale ));
803+ write_i16 (report, payload_offset + 19U , scale_i16 (normalized.gyroscope ->z , dualsense_gyroscope_scale ));
779804 }
780805 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 ));
806+ write_i16 (report, payload_offset + 21U , scale_i16 (normalized.acceleration ->x , dualsense_acceleration_scale ));
807+ write_i16 (report, payload_offset + 23U , scale_i16 (normalized.acceleration ->y , dualsense_acceleration_scale ));
808+ write_i16 (report, payload_offset + 25U , scale_i16 (normalized.acceleration ->z , dualsense_acceleration_scale ));
784809 }
810+ write_u32 (report, payload_offset + 27U , dualsense_sensor_timestamp ());
785811
786812 write_dualsense_touch_contact (report, payload_offset + 32U , normalized.touchpad_contacts [0 ]);
787813 write_dualsense_touch_contact (report, payload_offset + 36U , normalized.touchpad_contacts [1 ]);
0 commit comments