#pragma once #include "hid_pad_handler.h" #include namespace reports { constexpr u32 DS4_ACC_RES_PER_G = 8192; constexpr u32 DS4_GYRO_RES_PER_DEG_S = 86; // technically this could be 1024, but keeping it at 86 keeps us within 16 bits of precision constexpr u32 DS4_FEATURE_REPORT_USB_CALIBRATION_SIZE = 37; constexpr u32 DS4_FEATURE_REPORT_BLUETOOTH_CALIBRATION_SIZE = 41; // constexpr u32 DS4_FEATURE_REPORT_PAIRING_INFO_SIZE = 16; // constexpr u32 DS4_FEATURE_REPORT_0x81_SIZE = 7; constexpr u32 DS4_FEATURE_REPORT_FIRMWARE_INFO_SIZE = 49; constexpr u32 DS4_INPUT_REPORT_USB_SIZE = 64; constexpr u32 DS4_INPUT_REPORT_BLUETOOTH_SIZE = 78; constexpr u32 DS4_OUTPUT_REPORT_USB_SIZE = 32; constexpr u32 DS4_OUTPUT_REPORT_BLUETOOTH_SIZE = 78; constexpr u32 DS4_TOUCHPAD_WIDTH = 1920; constexpr u32 DS4_TOUCHPAD_HEIGHT = 942; constexpr u32 DS4_TOUCH_POINT_INACTIVE = 0x80; struct ds4_touch_point { u8 contact; u8 x_lo; u8 x_hi : 4; u8 y_lo : 4; u8 y_hi; }; static_assert(sizeof(ds4_touch_point) == 4); struct ds4_touch_report { u8 timestamp; std::array points; }; static_assert(sizeof(ds4_touch_report) == 9); struct ds4_input_report_common { u8 x; u8 y; u8 rx; u8 ry; u8 buttons[3]; u8 z; u8 rz; le_t sensor_timestamp; u8 sensor_temperature; le_t gyro[3]; le_t accel[3]; u8 reserved2[5]; u8 status[2]; u8 reserved3; }; static_assert(sizeof(ds4_input_report_common) == 32); struct ds4_input_report_usb { u8 report_id; ds4_input_report_common common; u8 num_touch_reports; std::array touch_reports; u8 reserved[3]; }; static_assert(sizeof(ds4_input_report_usb) == DS4_INPUT_REPORT_USB_SIZE); struct ds4_input_report_bt { u8 report_id; u8 reserved[2]; ds4_input_report_common common; u8 num_touch_reports; std::array touch_reports; u8 reserved2[2]; u8 crc32[4]; }; static_assert(sizeof(ds4_input_report_bt) == DS4_INPUT_REPORT_BLUETOOTH_SIZE); struct ds4_output_report_common { u8 valid_flag0; u8 valid_flag1; u8 reserved; u8 motor_right; u8 motor_left; u8 lightbar_red; u8 lightbar_green; u8 lightbar_blue; u8 lightbar_blink_on; u8 lightbar_blink_off; }; static_assert(sizeof(ds4_output_report_common) == 10); struct ds4_output_report_usb { u8 report_id; ds4_output_report_common common; u8 reserved[21]; }; static_assert(sizeof(ds4_output_report_usb) == DS4_OUTPUT_REPORT_USB_SIZE); struct ds4_output_report_bt { u8 report_id; u8 hw_control; u8 audio_control; ds4_output_report_common common; u8 reserved[61]; u8 crc32[4]; }; static_assert(sizeof(ds4_output_report_bt) == DS4_OUTPUT_REPORT_BLUETOOTH_SIZE); } // namespace reports class DS4Device : public HidDevice { public: bool bt_controller{false}; bool has_calib_data{false}; std::array calib_data{}; reports::ds4_input_report_usb report_usb{}; reports::ds4_input_report_bt report_bt{}; }; class ds4_pad_handler final : public hid_pad_handler { // These are all the possible buttons on a standard DS4 controller // The touchpad is restricted to its button for now (or forever?) enum DS4KeyCodes { None = 0, Triangle, Circle, Cross, Square, Left, Right, Up, Down, R1, // R2But, R3, L1, // L2But, L3, Share, Options, PSButton, TouchPad, Touch_L, Touch_R, Touch_U, Touch_D, L2, R2, LSXNeg, LSXPos, LSYNeg, LSYPos, RSXNeg, RSXPos, RSYNeg, RSYPos }; public: ds4_pad_handler(); ~ds4_pad_handler(); void SetPadData(const std::string& padId, u8 player_id, u8 large_motor, u8 small_motor, s32 r, s32 g, s32 b, bool player_led, bool battery_led, u32 battery_led_brightness) override; u32 get_battery_level(const std::string& padId) override; void init_config(cfg_pad* cfg) override; private: // This function gets us usuable buffer from the rawbuffer of padData bool GetCalibrationData(DS4Device* ds4Device) const; // Copies data into padData if status is NewData, otherwise buffer is untouched DataStatus get_data(DS4Device* ds4Device) override; int send_output_report(DS4Device* device) override; void check_add_device(hid_device* hidDevice, hid_enumerated_device_view path, std::wstring_view serial) override; bool get_is_left_trigger(const std::shared_ptr& device, u64 keyCode) override; bool get_is_right_trigger(const std::shared_ptr& device, u64 keyCode) override; bool get_is_left_stick(const std::shared_ptr& device, u64 keyCode) override; bool get_is_right_stick(const std::shared_ptr& device, u64 keyCode) override; bool get_is_touch_pad_motion(const std::shared_ptr& device, u64 keyCode) override; PadHandlerBase::connection update_connection(const std::shared_ptr& device) override; void get_extended_info(const pad_ensemble& binding) override; void apply_pad_data(const pad_ensemble& binding) override; std::unordered_map get_button_values(const std::shared_ptr& device) override; pad_preview_values get_preview_values(const std::unordered_map& data) override; };