1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-25 12:12:50 +01:00

DS4/DualSense/SDL: add touchpad support

This commit is contained in:
Megamouse 2024-07-30 22:51:17 +02:00
parent 12fbff22b2
commit 30f49a61df
8 changed files with 216 additions and 6 deletions

View File

@ -261,9 +261,13 @@ PadHandlerBase::connection PadHandlerBase::get_next_button_press(const std::stri
const bool is_trigger = get_is_left_trigger(device, keycode) || get_is_right_trigger(device, keycode);
const bool is_stick = !is_trigger && (get_is_left_stick(device, keycode) || get_is_right_stick(device, keycode));
const bool is_button = !is_trigger && !is_stick;
const bool is_touch_motion = !is_trigger && !is_stick && get_is_touch_pad_motion(device, keycode);
const bool is_button = !is_trigger && !is_stick && !is_touch_motion;
if ((is_trigger && (value > m_trigger_threshold)) || (is_stick && (value > m_thumb_threshold)) || (is_button && (value > 0)))
if ((is_trigger && (value > m_trigger_threshold)) ||
(is_stick && (value > m_thumb_threshold)) ||
(is_button && (value > 0)) ||
(is_touch_motion && (value > 255 * 0.9)))
{
if (get_blacklist)
{

View File

@ -290,6 +290,7 @@ private:
virtual bool get_is_right_trigger(const std::shared_ptr<PadDevice>& /*device*/, u64 /*keyCode*/) { return false; }
virtual bool get_is_left_stick(const std::shared_ptr<PadDevice>& /*device*/, u64 /*keyCode*/) { return false; }
virtual bool get_is_right_stick(const std::shared_ptr<PadDevice>& /*device*/, u64 /*keyCode*/) { return false; }
virtual bool get_is_touch_pad_motion(const std::shared_ptr<PadDevice>& /*device*/, u64 /*keyCode*/) { return false; }
virtual PadHandlerBase::connection update_connection(const std::shared_ptr<PadDevice>& /*device*/) { return connection::disconnected; }
virtual void get_extended_info(const pad_ensemble& /*binding*/) {}
virtual void apply_pad_data(const pad_ensemble& /*binding*/) {}

View File

@ -85,6 +85,10 @@ ds4_pad_handler::ds4_pad_handler()
{ DS4KeyCodes::Share, "Share" },
{ DS4KeyCodes::PSButton, "PS Button" },
{ DS4KeyCodes::TouchPad, "Touch Pad" },
{ DS4KeyCodes::Touch_L, "Touch Left" },
{ DS4KeyCodes::Touch_R, "Touch Right" },
{ DS4KeyCodes::Touch_U, "Touch Up" },
{ DS4KeyCodes::Touch_D, "Touch Down" },
{ DS4KeyCodes::L1, "L1" },
{ DS4KeyCodes::L2, "L2" },
{ DS4KeyCodes::L3, "L3" },
@ -333,6 +337,47 @@ std::unordered_map<u64, u16> ds4_pad_handler::get_button_values(const std::share
keyBuffer[DS4KeyCodes::L2] = input.z;
keyBuffer[DS4KeyCodes::R2] = input.rz;
// Touch Pad
const auto apply_touch = [&keyBuffer](const ds4_touch_report& touch)
{
for (const ds4_touch_point& point : touch.points)
{
if (!(point.contact & DS4_TOUCH_POINT_INACTIVE))
{
const s32 x = (point.x_hi << 8) | point.x_lo;
const s32 y = (point.y_hi << 4) | point.y_lo;
const f32 x_scaled = ScaledInput(static_cast<float>(x), 0.0f, static_cast<float>(DS4_TOUCHPAD_WIDTH), 0.0f, 255.0f);
const f32 y_scaled = ScaledInput(static_cast<float>(y), 0.0f, static_cast<float>(DS4_TOUCHPAD_HEIGHT), 0.0f, 255.0f);
keyBuffer[DS4KeyCodes::Touch_L] = Clamp0To255((127.5f - x_scaled) * 2.0f);
keyBuffer[DS4KeyCodes::Touch_R] = Clamp0To255((x_scaled - 127.5f) * 2.0f);
keyBuffer[DS4KeyCodes::Touch_U] = Clamp0To255((127.5f - y_scaled) * 2.0f);
keyBuffer[DS4KeyCodes::Touch_D] = Clamp0To255((y_scaled - 127.5f) * 2.0f);
}
}
};
if (ds4_dev->bt_controller)
{
const ds4_input_report_bt& report = ds4_dev->report_bt;
for (u32 i = 0; i < std::min<u32>(report.num_touch_reports, ::size32(report.touch_reports)); i++)
{
apply_touch(report.touch_reports[i]);
}
}
else
{
const ds4_input_report_usb& report = ds4_dev->report_usb;
for (u32 i = 0; i < std::min<u32>(report.num_touch_reports, ::size32(report.touch_reports)); i++)
{
apply_touch(report.touch_reports[i]);
}
}
return keyBuffer;
}
@ -759,6 +804,20 @@ bool ds4_pad_handler::get_is_right_stick(const std::shared_ptr<PadDevice>& /*dev
}
}
bool ds4_pad_handler::get_is_touch_pad_motion(const std::shared_ptr<PadDevice>& /*device*/, u64 keyCode)
{
switch (keyCode)
{
case DS4KeyCodes::Touch_L:
case DS4KeyCodes::Touch_R:
case DS4KeyCodes::Touch_U:
case DS4KeyCodes::Touch_D:
return true;
default:
return false;
}
}
PadHandlerBase::connection ds4_pad_handler::update_connection(const std::shared_ptr<PadDevice>& device)
{
DS4Device* ds4_dev = static_cast<DS4Device*>(device.get());

View File

@ -19,6 +19,7 @@ namespace reports
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
{
@ -33,7 +34,7 @@ namespace reports
struct ds4_touch_report
{
u8 timestamp;
ds4_touch_point points[2];
std::array<ds4_touch_point, 2> points;
};
static_assert(sizeof(ds4_touch_report) == 9);
@ -61,7 +62,7 @@ namespace reports
u8 report_id;
ds4_input_report_common common;
u8 num_touch_reports;
ds4_touch_report touch_reports[3];
std::array<ds4_touch_report, 3> touch_reports;
u8 reserved[3];
};
static_assert(sizeof(ds4_input_report_usb) == DS4_INPUT_REPORT_USB_SIZE);
@ -72,7 +73,7 @@ namespace reports
u8 reserved[2];
ds4_input_report_common common;
u8 num_touch_reports;
ds4_touch_report touch_reports[4];
std::array<ds4_touch_report, 4> touch_reports;
u8 reserved2[2];
u8 crc32[4];
};
@ -150,6 +151,11 @@ class ds4_pad_handler final : public hid_pad_handler<DS4Device>
PSButton,
TouchPad,
Touch_L,
Touch_R,
Touch_U,
Touch_D,
L2,
R2,
@ -184,6 +190,7 @@ private:
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;

View File

@ -52,6 +52,10 @@ dualsense_pad_handler::dualsense_pad_handler()
{ DualSenseKeyCodes::PSButton, "PS Button" },
{ DualSenseKeyCodes::Mic, "Mic" },
{ DualSenseKeyCodes::TouchPad, "Touch Pad" },
{ DualSenseKeyCodes::Touch_L, "Touch Left" },
{ DualSenseKeyCodes::Touch_R, "Touch Right" },
{ DualSenseKeyCodes::Touch_U, "Touch Up" },
{ DualSenseKeyCodes::Touch_D, "Touch Down" },
{ DualSenseKeyCodes::L1, "L1" },
{ DualSenseKeyCodes::L2, "L2" },
{ DualSenseKeyCodes::L3, "L3" },
@ -538,6 +542,20 @@ bool dualsense_pad_handler::get_is_right_stick(const std::shared_ptr<PadDevice>&
}
}
bool dualsense_pad_handler::get_is_touch_pad_motion(const std::shared_ptr<PadDevice>& /*device*/, u64 keyCode)
{
switch (keyCode)
{
case DualSenseKeyCodes::Touch_L:
case DualSenseKeyCodes::Touch_R:
case DualSenseKeyCodes::Touch_U:
case DualSenseKeyCodes::Touch_D:
return true;
default:
return false;
}
}
PadHandlerBase::connection dualsense_pad_handler::update_connection(const std::shared_ptr<PadDevice>& device)
{
DualSenseDevice* dualsense_dev = static_cast<DualSenseDevice*>(device.get());
@ -728,6 +746,25 @@ std::unordered_map<u64, u16> dualsense_pad_handler::get_button_values(const std:
keyBuffer[DualSenseKeyCodes::TouchPad] = ((data & 0x02) != 0) ? 255 : 0;
keyBuffer[DualSenseKeyCodes::Mic] = ((data & 0x04) != 0) ? 255 : 0;
// Touch Pad
for (const dualsense_touch_point& point : input.points)
{
if (!(point.contact & DUALSENSE_TOUCH_POINT_INACTIVE))
{
const s32 x = (point.x_hi << 8) | point.x_lo;
const s32 y = (point.y_hi << 4) | point.y_lo;
const f32 x_scaled = ScaledInput(static_cast<float>(x), 0.0f, static_cast<float>(DUALSENSE_TOUCHPAD_WIDTH), 0.0f, 255.0f);
const f32 y_scaled = ScaledInput(static_cast<float>(y), 0.0f, static_cast<float>(DUALSENSE_TOUCHPAD_HEIGHT), 0.0f, 255.0f);
keyBuffer[DualSenseKeyCodes::Touch_L] = Clamp0To255((127.5f - x_scaled) * 2.0f);
keyBuffer[DualSenseKeyCodes::Touch_R] = Clamp0To255((x_scaled - 127.5f) * 2.0f);
keyBuffer[DualSenseKeyCodes::Touch_U] = Clamp0To255((127.5f - y_scaled) * 2.0f);
keyBuffer[DualSenseKeyCodes::Touch_D] = Clamp0To255((y_scaled - 127.5f) * 2.0f);
}
}
if (dualsense_dev->feature_set == DualSenseDevice::DualSenseFeatureSet::Edge)
{
keyBuffer[DualSenseKeyCodes::EdgeFnL] = ((data & 0x10) != 0) ? 255 : 0;

View File

@ -19,6 +19,7 @@ namespace reports
constexpr u32 DUALSENSE_INPUT_REPORT_GYRO_X_OFFSET = 15;
constexpr u32 DUALSENSE_TOUCHPAD_WIDTH = 1920;
constexpr u32 DUALSENSE_TOUCHPAD_HEIGHT = 1080;
constexpr u32 DUALSENSE_TOUCH_POINT_INACTIVE = 0x80;
enum
{
@ -82,7 +83,7 @@ namespace reports
le_t<u16, 1> accel[3];
le_t<u32, 1> sensor_timestamp;
u8 reserved2;
dualsense_touch_point points[2];
std::array<dualsense_touch_point, 2> points;
u8 reserved3[12];
u8 status;
u8 reserved4[10];
@ -210,6 +211,11 @@ class dualsense_pad_handler final : public hid_pad_handler<DualSenseDevice>
Mic,
TouchPad,
Touch_L,
Touch_R,
Touch_U,
Touch_D,
L2,
R2,
@ -247,6 +253,7 @@ private:
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;
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;

View File

@ -143,6 +143,10 @@ sdl_pad_handler::sdl_pad_handler() : PadHandlerBase(pad_handler::sdl)
{ SDLKeyCodes::Paddle3, "Paddle 3" },
{ SDLKeyCodes::Paddle4, "Paddle 4" },
{ SDLKeyCodes::Touchpad, "Touchpad" },
{ SDLKeyCodes::Touch_L, "Touch Left" },
{ SDLKeyCodes::Touch_R, "Touch Right" },
{ SDLKeyCodes::Touch_U, "Touch Up" },
{ SDLKeyCodes::Touch_D, "Touch Down" },
{ SDLKeyCodes::LT, "LT" },
{ SDLKeyCodes::RT, "RT" },
{ SDLKeyCodes::LSXNeg, "LS X-" },
@ -342,6 +346,27 @@ SDLDevice::sdl_info sdl_pad_handler::get_sdl_info(int i)
info.has_accel = SDL_GameControllerHasSensor(info.game_controller, SDL_SENSOR_ACCEL);
info.has_gyro = SDL_GameControllerHasSensor(info.game_controller, SDL_SENSOR_GYRO);
if (const int num_touchpads = SDL_GameControllerGetNumTouchpads(info.game_controller); num_touchpads > 0)
{
info.touchpads.resize(num_touchpads);
for (int i = 0; i < num_touchpads; i++)
{
SDLDevice::touchpad& touchpad = ::at32(info.touchpads, i);
touchpad.index = i;
if (const int num_fingers = SDL_GameControllerGetNumTouchpadFingers(info.game_controller, touchpad.index); num_fingers > 0)
{
touchpad.fingers.resize(num_fingers);
for (int f = 0; f < num_fingers; f++)
{
::at32(touchpad.fingers, f).index = f;
}
}
}
}
sdl_log.notice("Found game controller %d: type=%d, name='%s', path='%s', serial='%s', vid=0x%x, pid=0x%x, product_version=0x%x, firmware_version=0x%x, has_led=%d, has_rumble=%d, has_rumble_triggers=%d, has_accel=%d, has_gyro=%d",
i, static_cast<int>(info.type), info.name, info.path, info.serial, info.vid, info.pid, info.product_version, info.firmware_version, info.has_led, info.has_rumble, info.has_rumble_triggers, info.has_accel, info.has_gyro);
@ -913,6 +938,20 @@ bool sdl_pad_handler::get_is_right_stick(const std::shared_ptr<PadDevice>& /*dev
}
}
bool sdl_pad_handler::get_is_touch_pad_motion(const std::shared_ptr<PadDevice>& /*device*/, u64 keyCode)
{
switch (keyCode)
{
case SDLKeyCodes::Touch_L:
case SDLKeyCodes::Touch_R:
case SDLKeyCodes::Touch_U:
case SDLKeyCodes::Touch_D:
return true;
default:
return false;
}
}
std::unordered_map<u64, u16> sdl_pad_handler::get_button_values(const std::shared_ptr<PadDevice>& device)
{
std::unordered_map<u64, u16> values;
@ -962,6 +1001,40 @@ std::unordered_map<u64, u16> sdl_pad_handler::get_button_values(const std::share
}
}
for (const SDLDevice::touchpad& touchpad : dev->sdl.touchpads)
{
for (const SDLDevice::touch_point& finger : touchpad.fingers)
{
u8 state = 0; // 1 means the finger is touching the pad
f32 x = 0.0f; // 0 = left, 1 = right
f32 y = 0.0f; // 0 = top, 1 = bottom
f32 pressure = 0.0f; // In the current SDL version the pressure is always 1 if the state is 1
if (SDL_GameControllerGetTouchpadFinger(dev->sdl.game_controller, touchpad.index, finger.index, &state, &x, &y, &pressure) != 0)
{
sdl_log.error("Could not get touchpad %d finger %d data of device %d! SDL Error: %s", touchpad.index, finger.index, dev->player_id, SDL_GetError());
}
else
{
sdl_log.trace("touchpad=%d, finger=%d, state=%d, x=%f, y=%f, pressure=%f", touchpad.index, finger.index, state, x, y, pressure);
if (state == 0)
{
continue;
}
const f32 x_scaled = ScaledInput(x, 0.0f, 1.0f, 0.0f, 255.0f);
const f32 y_scaled = ScaledInput(y, 0.0f, 1.0f, 0.0f, 255.0f);
values[SDLKeyCodes::Touch_L] = Clamp0To255((127.5f - x_scaled) * 2.0f);
values[SDLKeyCodes::Touch_R] = Clamp0To255((x_scaled - 127.5f) * 2.0f);
values[SDLKeyCodes::Touch_U] = Clamp0To255((127.5f - y_scaled) * 2.0f);
values[SDLKeyCodes::Touch_D] = Clamp0To255((y_scaled - 127.5f) * 2.0f);
}
}
}
return values;
}

View File

@ -8,6 +8,20 @@
class SDLDevice : public PadDevice
{
public:
struct touch_point
{
int index = 0;
int x = 0;
int y = 0;
};
struct touchpad
{
int index = 0;
std::vector<touch_point> fingers;
};
struct sdl_info
{
SDL_GameController* game_controller = nullptr;
@ -37,6 +51,8 @@ public:
std::set<SDL_GameControllerButton> button_ids;
std::set<SDL_GameControllerAxis> axis_ids;
std::vector<touchpad> touchpads;
};
sdl_info sdl{};
@ -81,6 +97,11 @@ class sdl_pad_handler : public PadHandlerBase
Paddle4,
Touchpad,
Touch_L,
Touch_R,
Touch_U,
Touch_D,
LT,
RT,
@ -124,6 +145,7 @@ private:
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;
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;