mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-04 16:32:39 +00:00
devices: add mouse abstraction
This commit is contained in:
parent
b76c98e217
commit
31b3b1976b
@ -490,6 +490,9 @@ set(CORE src/core/aerolib/stubs.cpp
|
||||
src/core/crypto/keys.h
|
||||
src/core/devices/base_device.cpp
|
||||
src/core/devices/base_device.h
|
||||
src/core/devices/hid_device.cpp
|
||||
src/core/devices/hid_device.h
|
||||
src/core/devices/hid_device_mouse.cpp
|
||||
src/core/file_format/pfs.h
|
||||
src/core/file_format/pkg.cpp
|
||||
src/core/file_format/pkg.h
|
||||
|
68
src/core/devices/hid_device.cpp
Normal file
68
src/core/devices/hid_device.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <core/libraries/system/msgdialog_ui.h>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "common/singleton.h"
|
||||
#include "common/va_ctx.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "hid_device.h"
|
||||
#include "input/mouse.h"
|
||||
#include "ioccom.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
struct InitHidRaw {
|
||||
u32 user_id;
|
||||
u32 type;
|
||||
u32 _unknown2;
|
||||
};
|
||||
static_assert(sizeof(InitHidRaw) == 0xC);
|
||||
|
||||
constexpr auto HID_CMD_INIT_HANDLE_FOR_USER_ID = _IOW('H', 0x2, InitHidRaw);
|
||||
|
||||
int HidDevice::GenericCallback(u64 cmd, Common::VaCtx* args) {
|
||||
LOG_TRACE(Core_Devices, "HID({:X}) generic: ioctl cmd={:X}", handle, cmd);
|
||||
if (cmd == HID_CMD_INIT_HANDLE_FOR_USER_ID) {
|
||||
auto data = vaArgPtr<InitHidRaw>(&args->va_list);
|
||||
this->user_id = data->user_id;
|
||||
if (data->type == 0) {
|
||||
LOG_INFO(Core_Devices, "HID({:X}) open: type=mouse, user_id={}", handle, data->user_id);
|
||||
this->m_callback = &HidDevice::MouseCallback;
|
||||
// FIXME Replace by status bar
|
||||
if (!Common::Singleton<Input::GameMouse>::Instance()->m_connected) {
|
||||
using namespace ::Libraries::MsgDialog;
|
||||
ShowMsgDialog(MsgDialogState(MsgDialogState::UserState{
|
||||
.type = ButtonType::YESNO,
|
||||
.msg = "Game wants to use your mouse.\nDo you want to allow it?",
|
||||
}),
|
||||
false, [](DialogResult result) {
|
||||
if (result.buttonId == ButtonId::YES) {
|
||||
auto* mouse = Common::Singleton<Input::GameMouse>::Instance();
|
||||
mouse->m_connected = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING(Core_Devices, "HID({:X}) open: unknown type={}", handle, data->type);
|
||||
}
|
||||
return static_cast<int>(handle);
|
||||
}
|
||||
LOG_WARNING(Core_Devices, "HID({:X}) generic: unknown ioctl cmd = {:X}", handle, cmd);
|
||||
return ORBIS_KERNEL_ERROR_ENOTTY;
|
||||
}
|
||||
|
||||
BaseDevice* HidDevice::Create(u32 handle, const char*, int, u16) {
|
||||
return new HidDevice(handle);
|
||||
}
|
||||
|
||||
HidDevice::HidDevice(u32 handle) : handle{handle} {}
|
||||
|
||||
HidDevice::~HidDevice() = default;
|
||||
|
||||
int HidDevice::ioctl(u64 cmd, Common::VaCtx* args) {
|
||||
return (this->*m_callback)(cmd, args);
|
||||
}
|
||||
|
||||
} // namespace Core::Devices
|
30
src/core/devices/hid_device.h
Normal file
30
src/core/devices/hid_device.h
Normal file
@ -0,0 +1,30 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
class HidDevice final : BaseDevice {
|
||||
u32 handle;
|
||||
u32 user_id{};
|
||||
|
||||
int MouseCallback(u64 cmd, Common::VaCtx* args);
|
||||
|
||||
int GenericCallback(u64 cmd, Common::VaCtx* args);
|
||||
|
||||
int (HidDevice::*m_callback)(u64 cmd, Common::VaCtx* args) = &HidDevice::GenericCallback;
|
||||
|
||||
public:
|
||||
static BaseDevice* Create(u32 handle, const char*, int, u16);
|
||||
|
||||
explicit HidDevice(u32 handle);
|
||||
|
||||
~HidDevice() override;
|
||||
|
||||
int ioctl(u64 cmd, Common::VaCtx* args) override;
|
||||
};
|
||||
|
||||
} // namespace Core::Devices
|
76
src/core/devices/hid_device_mouse.cpp
Normal file
76
src/core/devices/hid_device_mouse.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "common/singleton.h"
|
||||
#include "hid_device.h"
|
||||
#include "input/mouse.h"
|
||||
#include "ioccom.h"
|
||||
|
||||
struct MouseInfo {};
|
||||
|
||||
struct MouseDataEntry {
|
||||
std::array<u8, 8> _unknown1;
|
||||
s16 x;
|
||||
s16 y;
|
||||
u8 buttons;
|
||||
bool system_capture;
|
||||
s8 wheel;
|
||||
s8 tilt;
|
||||
std::array<u8, 8> _reserved;
|
||||
};
|
||||
|
||||
static_assert(sizeof(MouseDataEntry) == 0x18);
|
||||
|
||||
struct MouseData {
|
||||
u32 handle;
|
||||
std::array<u8, 4> _unknown1;
|
||||
MouseDataEntry* data;
|
||||
int max_data;
|
||||
std::array<u8, 4> _unknown2;
|
||||
int* read_count;
|
||||
};
|
||||
static_assert(sizeof(MouseData) == 0x20);
|
||||
|
||||
constexpr auto HID_CMD_READ_MOUSE_STATE = _IOW('H', 0x19, MouseData);
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
int HidDevice::MouseCallback(u64 cmd, Common::VaCtx* args) {
|
||||
switch (cmd) {
|
||||
case HID_CMD_READ_DEVICE_INFO: {
|
||||
auto info = vaArgPtr<DeviceInfo<MouseInfo>>(&args->va_list);
|
||||
info->data = nullptr;
|
||||
// TODO Fill data with the mouse info
|
||||
return ORBIS_OK;
|
||||
}
|
||||
case HID_CMD_READ_MOUSE_STATE: {
|
||||
auto mouse_data = vaArgPtr<MouseData>(&args->va_list);
|
||||
auto* mouse = Common::Singleton<Input::GameMouse>::Instance();
|
||||
if (!mouse->m_connected) {
|
||||
*mouse_data->read_count = 0;
|
||||
return 0;
|
||||
}
|
||||
std::array<Input::MouseState, 64> states;
|
||||
int total = std::min((int)states.size(), mouse_data->max_data);
|
||||
total = mouse->ReadStates(states.data(), total);
|
||||
for (int i = 0; i < total; ++i) {
|
||||
const auto& s = states[i];
|
||||
mouse_data->data[i] = MouseDataEntry{
|
||||
.x = static_cast<s16>(s.x_axis),
|
||||
.y = static_cast<s16>(s.y_axis),
|
||||
.buttons = static_cast<u8>(s.button_state),
|
||||
.system_capture = false,
|
||||
.wheel = static_cast<s8>(s.wheel),
|
||||
.tilt = static_cast<s8>(s.tilt),
|
||||
};
|
||||
}
|
||||
return total;
|
||||
}
|
||||
default:
|
||||
LOG_WARNING(Core_Devices, "HID({:X}) mouse: unknown ioctl request: {:X}", handle, cmd);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Core::Devices
|
@ -65,3 +65,13 @@ def parse(v):
|
||||
print('group', chr(v >> 8 & 0xFF))
|
||||
print('num', hex(v & 0xFF))
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
struct DeviceInfo {
|
||||
int handle;
|
||||
std::array<u8, 4> _pad1;
|
||||
T* data;
|
||||
};
|
||||
static_assert(sizeof(DeviceInfo<void>) == 0x10);
|
||||
|
||||
constexpr auto HID_CMD_READ_DEVICE_INFO = _IOW('H', 0x1, DeviceInfo<void>);
|
||||
|
@ -14,11 +14,13 @@
|
||||
#include <map>
|
||||
#include <ranges>
|
||||
|
||||
#include "core/devices/hid_device.h"
|
||||
|
||||
using FactoryDevice = std::function<Core::Devices::BaseDevice*(u32, const char*, int, u16)>;
|
||||
|
||||
// prefix path
|
||||
static std::map<std::string, FactoryDevice> available_device = {
|
||||
{"/dev/hid", &Core::Devices::HidDevice::Create},
|
||||
};
|
||||
|
||||
namespace Libraries::Kernel {
|
||||
|
@ -408,7 +408,6 @@ int PS4_SYSV_ABI kernel_ioctl(int fd, u64 cmd, VA_ARGS) {
|
||||
}
|
||||
VA_CTX(ctx);
|
||||
int result = file->device->ioctl(cmd, &ctx);
|
||||
LOG_TRACE(Lib_Kernel, "ioctl: fd = {:X} cmd = {:X} result = {}", fd, cmd, result);
|
||||
if (result < 0) {
|
||||
ErrSceToPosix(result);
|
||||
return -1;
|
||||
|
@ -90,7 +90,7 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) {
|
||||
Libraries::SharePlay::RegisterlibSceSharePlay(sym);
|
||||
Libraries::Remoteplay::RegisterlibSceRemoteplay(sym);
|
||||
Libraries::Videodec::RegisterlibSceVideodec(sym);
|
||||
Libraries::Mouse::RegisterlibSceMouse(sym);
|
||||
// Libraries::Mouse::RegisterlibSceMouse(sym);
|
||||
}
|
||||
|
||||
} // namespace Libraries
|
||||
|
@ -117,10 +117,10 @@ void Emulator::Run(const std::filesystem::path& file) {
|
||||
auto& game_info = Common::ElfInfo::Instance();
|
||||
|
||||
// Loading param.sfo file if exists
|
||||
std::string id;
|
||||
std::string title;
|
||||
std::string app_version;
|
||||
u32 fw_version;
|
||||
std::string id = "unknown_serial";
|
||||
std::string title = "unknown_title";
|
||||
std::string app_version = "unknown_version";
|
||||
u32 fw_version = 0x4700000;
|
||||
|
||||
std::filesystem::path sce_sys_folder = eboot_path.parent_path() / "sce_sys";
|
||||
if (std::filesystem::is_directory(sce_sys_folder)) {
|
||||
@ -274,8 +274,8 @@ void Emulator::Run(const std::filesystem::path& file) {
|
||||
}
|
||||
|
||||
void Emulator::LoadSystemModules(const std::filesystem::path& file, std::string game_serial) {
|
||||
constexpr std::array<SysModules, 11> ModulesToLoad{
|
||||
{{"libSceNgs2.sprx", &Libraries::Ngs2::RegisterlibSceNgs2},
|
||||
constexpr std::array<SysModules, 12> ModulesToLoad{{
|
||||
{"libSceNgs2.sprx", &Libraries::Ngs2::RegisterlibSceNgs2},
|
||||
{"libSceFiber.sprx", &Libraries::Fiber::RegisterlibSceFiber},
|
||||
{"libSceUlt.sprx", nullptr},
|
||||
{"libSceJson.sprx", nullptr},
|
||||
@ -285,7 +285,9 @@ void Emulator::LoadSystemModules(const std::filesystem::path& file, std::string
|
||||
{"libSceRtc.sprx", &Libraries::Rtc::RegisterlibSceRtc},
|
||||
{"libSceJpegEnc.sprx", nullptr},
|
||||
{"libSceRazorCpu.sprx", nullptr},
|
||||
{"libSceCesCs.sprx", nullptr}}};
|
||||
{"libSceCesCs.sprx", nullptr},
|
||||
{"libSceMouse.sprx", nullptr},
|
||||
}};
|
||||
|
||||
std::vector<std::filesystem::path> found_modules;
|
||||
const auto& sys_module_path = Common::FS::GetUserPath(Common::FS::PathType::SysModuleDir);
|
||||
|
@ -12,10 +12,18 @@ GameMouse::GameMouse() {
|
||||
}
|
||||
|
||||
int GameMouse::ReadStates(MouseState* states, int states_num) {
|
||||
if (states_num == 0) {
|
||||
return 0;
|
||||
}
|
||||
std::scoped_lock lock{m_mutex};
|
||||
|
||||
const u32 count = std::min(m_states_num, u32(states_num));
|
||||
|
||||
if (count == 0) {
|
||||
states[0] = m_last_state;
|
||||
return 1;
|
||||
}
|
||||
|
||||
u32 begin = (m_index - m_states_num + 1) % MAX_MOUSE_STATES;
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
u32 idx = (begin + i) % MAX_MOUSE_STATES;
|
||||
|
Loading…
Reference in New Issue
Block a user