rpcsx/rpcs3/Input/ds4_pad_handler.h
DH 62ad27d1e2 split rpcs3 and hle libraries
merge rpcs3 utilities
2025-04-08 19:46:57 +03:00

200 lines
5.1 KiB
C++

#pragma once
#include "hid_pad_handler.h"
#include <unordered_map>
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<ds4_touch_point, 2> 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<u16, 1> sensor_timestamp;
u8 sensor_temperature;
le_t<u16, 1> gyro[3];
le_t<u16, 1> 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<ds4_touch_report, 3> 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<ds4_touch_report, 4> 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<CalibData, CalibIndex::COUNT> 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<DS4Device>
{
// 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<PadDevice>& device, u64 keyCode) override;
bool get_is_right_trigger(const std::shared_ptr<PadDevice>& device, u64 keyCode) override;
bool get_is_left_stick(const std::shared_ptr<PadDevice>& device, u64 keyCode) override;
bool get_is_right_stick(const std::shared_ptr<PadDevice>& device, u64 keyCode) override;
bool get_is_touch_pad_motion(const std::shared_ptr<PadDevice>& device, u64 keyCode) override;
PadHandlerBase::connection update_connection(const std::shared_ptr<PadDevice>& device) override;
void get_extended_info(const pad_ensemble& binding) override;
void apply_pad_data(const pad_ensemble& binding) override;
std::unordered_map<u64, u16> get_button_values(const std::shared_ptr<PadDevice>& device) override;
pad_preview_values get_preview_values(const std::unordered_map<u64, u16>& data) override;
};