mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-06 06:51:26 +12:00
218 lines
7.2 KiB
C++
218 lines
7.2 KiB
C++
#pragma once
|
|
|
|
#include "hid_pad_handler.h"
|
|
|
|
#ifndef _MSC_VER
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
|
#endif
|
|
#include "3rdparty/fusion/fusion/Fusion/Fusion.h"
|
|
#ifndef _MSC_VER
|
|
#pragma GCC diagnostic pop
|
|
#endif
|
|
|
|
#include <unordered_map>
|
|
|
|
namespace reports
|
|
{
|
|
// NOTE: The 1st half-frame contains slightly older data than the 2nd half-frame
|
|
#pragma pack(push, 1)
|
|
struct ps_move_input_report_common
|
|
{
|
|
// ID Size Description
|
|
u8 report_id{}; // 0x00 1 HID Report ID (always 0x01)
|
|
u8 buttons_1{}; // 0x01 1 Buttons 1 (Start, Select)
|
|
u8 buttons_2{}; // 0x02 1 Buttons 2 (X, Square, Circle, Triangle)
|
|
u8 buttons_3{}; // 0x03 1+ Buttons 3 (PS, Move, T) and EXT
|
|
u8 sequence_number{}; // 0x04 1- Sequence number
|
|
u8 trigger_1{}; // 0x05 1 T button values (1st half-frame)
|
|
u8 trigger_2{}; // 0x06 1 T button values (2nd half-frame)
|
|
u32 magic{}; // 0x07 4 always 0x7F7F7F7F
|
|
u8 timestamp_upper{}; // 0x0B 1 Timestamp (upper byte)
|
|
u8 battery_level{}; // 0x0C 1 Battery level. 0x05 = max, 0xEE = USB charging
|
|
s16 accel_x_1{}; // 0x0D 2 X-axis accelerometer (1st half-frame)
|
|
s16 accel_y_1{}; // 0x0F 2 Z-axis accelerometer (1st half-frame)
|
|
s16 accel_z_1{}; // 0x11 2 Y-axis accelerometer (1st half-frame)
|
|
s16 accel_x_2{}; // 0x13 2 X-axis accelerometer (2nd half-frame)
|
|
s16 accel_y_2{}; // 0x15 2 Z-axis accelerometer (2nd half-frame)
|
|
s16 accel_z_2{}; // 0x17 2 Y-axis accelerometer (2nd half-frame)
|
|
s16 gyro_x_1{}; // 0x19 2 X-axis gyroscope (1st half-frame)
|
|
s16 gyro_y_1{}; // 0x1B 2 Z-axis gyroscope (1st half-frame)
|
|
s16 gyro_z_1{}; // 0x1D 2 Y-axis gyroscope (1st half-frame)
|
|
s16 gyro_x_2{}; // 0x1F 2 X-axis gyroscope (2nd half-frame)
|
|
s16 gyro_y_2{}; // 0x21 2 Z-axis gyroscope (2nd half-frame)
|
|
s16 gyro_z_2{}; // 0x23 2 Y-axis gyroscope (2nd half-frame)
|
|
u8 temperature{}; // 0x25 1+ Temperature
|
|
u8 magnetometer_x{}; // 0x26 1+ Temperature + X-axis magnetometer
|
|
};
|
|
#pragma pack(pop)
|
|
|
|
#pragma pack(push, 1)
|
|
struct ps_move_input_report_ZCM1
|
|
{
|
|
ps_move_input_report_common common{};
|
|
|
|
// ID Size Description
|
|
u8 magnetometer_x2{}; // 0x27 1- X-axis magnetometer
|
|
u8 magnetometer_y{}; // 0x28 1+ Z-axis magnetometer
|
|
u16 magnetometer_z{}; // 0x29 1- Y-axis magnetometer
|
|
u8 timestamp_lower{}; // 0x2B 1 Timestamp (lower byte)
|
|
std::array<u8, 5> ext_device_data{}; // 0x2C 5 External device data
|
|
};
|
|
#pragma pack(pop)
|
|
|
|
#pragma pack(push, 1)
|
|
struct ps_move_input_report_ZCM2
|
|
{
|
|
ps_move_input_report_common common{};
|
|
|
|
// ID Size Description
|
|
u16 timestamp2; // 0x27 2 same as common timestamp
|
|
u16 unk; // 0x29 2 Unknown
|
|
u8 timestamp_lower; // 0x2B 1 Timestamp (lower byte)
|
|
};
|
|
#pragma pack(pop)
|
|
|
|
struct ps_move_output_report
|
|
{
|
|
u8 type{};
|
|
u8 zero{};
|
|
u8 r{};
|
|
u8 g{};
|
|
u8 b{};
|
|
u8 zero2{};
|
|
u8 rumble{};
|
|
u8 padding[2];
|
|
};
|
|
|
|
struct ps_move_feature_report
|
|
{
|
|
std::array<u8, 4> data{}; // TODO
|
|
};
|
|
|
|
// Buffer size for calibration data
|
|
constexpr u32 PSMOVE_CALIBRATION_SIZE = 49;
|
|
|
|
// Three blocks, minus header (2 bytes) for blocks 2,3
|
|
constexpr u32 PSMOVE_ZCM1_CALIBRATION_BLOB_SIZE = PSMOVE_CALIBRATION_SIZE * 3 - 2 * 2;
|
|
|
|
// Three blocks, minus header (2 bytes) for block 2
|
|
constexpr u32 PSMOVE_ZCM2_CALIBRATION_BLOB_SIZE = PSMOVE_CALIBRATION_SIZE * 2 - 2 * 1;
|
|
|
|
struct ps_move_calibration_blob
|
|
{
|
|
std::array<u8, std::max(PSMOVE_ZCM1_CALIBRATION_BLOB_SIZE, PSMOVE_ZCM2_CALIBRATION_BLOB_SIZE)> data{};
|
|
};
|
|
}
|
|
|
|
enum
|
|
{
|
|
zero_shift = 0x8000,
|
|
};
|
|
|
|
enum class ps_move_model
|
|
{
|
|
ZCM1, // PS3
|
|
ZCM2, // PS4
|
|
};
|
|
|
|
struct ps_move_calibration
|
|
{
|
|
bool is_valid = false;
|
|
f32 accel_x_factor = 1.0f;
|
|
f32 accel_y_factor = 1.0f;
|
|
f32 accel_z_factor = 1.0f;
|
|
f32 accel_x_offset = 0.0f;
|
|
f32 accel_y_offset = 0.0f;
|
|
f32 accel_z_offset = 0.0f;
|
|
f32 gyro_x_gain = 1.0f;
|
|
f32 gyro_y_gain = 1.0f;
|
|
f32 gyro_z_gain = 1.0f;
|
|
f32 gyro_x_offset = 0.0f;
|
|
f32 gyro_y_offset = 0.0f;
|
|
f32 gyro_z_offset = 0.0f;
|
|
};
|
|
|
|
class ps_move_device : public HidDevice
|
|
{
|
|
public:
|
|
ps_move_model model = ps_move_model::ZCM1;
|
|
reports::ps_move_input_report_ZCM1 input_report_ZCM1{};
|
|
reports::ps_move_input_report_ZCM2 input_report_ZCM2{};
|
|
reports::ps_move_output_report output_report{};
|
|
reports::ps_move_output_report last_output_report{};
|
|
steady_clock::time_point last_output_report_time;
|
|
u32 external_device_id = 0;
|
|
ps_move_calibration calibration{};
|
|
|
|
FusionAhrs ahrs {}; // Used to calculate quaternions from sensor data
|
|
u64 last_ahrs_update_time_us = 0; // Last ahrs update
|
|
|
|
void update_orientation(ps_move_data& move_data);
|
|
void reset_orientation();
|
|
|
|
const reports::ps_move_input_report_common& input_report_common() const;
|
|
};
|
|
|
|
class ps_move_handler final : public hid_pad_handler<ps_move_device>
|
|
{
|
|
enum ps_move_key_codes
|
|
{
|
|
none = 0,
|
|
cross,
|
|
square,
|
|
circle,
|
|
triangle,
|
|
start,
|
|
select,
|
|
ps,
|
|
move,
|
|
t,
|
|
|
|
// Available through external sharpshooter
|
|
firing_mode_1,
|
|
firing_mode_2,
|
|
firing_mode_3,
|
|
reload,
|
|
|
|
// Available through external racing wheel
|
|
dpad_up,
|
|
dpad_down,
|
|
dpad_left,
|
|
dpad_right,
|
|
L1,
|
|
R1,
|
|
L2,
|
|
R2,
|
|
throttle,
|
|
paddle_left,
|
|
paddle_right,
|
|
};
|
|
|
|
public:
|
|
ps_move_handler();
|
|
~ps_move_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:
|
|
#ifdef _WIN32
|
|
hid_device* connect_move_device(ps_move_device* device, std::string_view path);
|
|
#endif
|
|
|
|
DataStatus get_data(ps_move_device* device) override;
|
|
void check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view wide_serial) override;
|
|
int send_output_report(ps_move_device* device) 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;
|
|
PadHandlerBase::connection update_connection(const std::shared_ptr<PadDevice>& device) 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;
|
|
void get_extended_info(const pad_ensemble& binding) override;
|
|
void apply_pad_data(const pad_ensemble& binding) override;
|
|
|
|
void handle_external_device(const pad_ensemble& binding);
|
|
};
|