devices: add mouse abstraction

This commit is contained in:
Vinicius Rangel 2024-11-11 15:26:11 -03:00
parent b76c98e217
commit 31b3b1976b
No known key found for this signature in database
GPG Key ID: A5B154D904B761D9
10 changed files with 216 additions and 18 deletions

View File

@ -490,6 +490,9 @@ set(CORE src/core/aerolib/stubs.cpp
src/core/crypto/keys.h src/core/crypto/keys.h
src/core/devices/base_device.cpp src/core/devices/base_device.cpp
src/core/devices/base_device.h 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/pfs.h
src/core/file_format/pkg.cpp src/core/file_format/pkg.cpp
src/core/file_format/pkg.h src/core/file_format/pkg.h

View 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

View 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

View 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

View File

@ -65,3 +65,13 @@ def parse(v):
print('group', chr(v >> 8 & 0xFF)) print('group', chr(v >> 8 & 0xFF))
print('num', hex(v & 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>);

View File

@ -14,11 +14,13 @@
#include <map> #include <map>
#include <ranges> #include <ranges>
#include "core/devices/hid_device.h"
using FactoryDevice = std::function<Core::Devices::BaseDevice*(u32, const char*, int, u16)>; using FactoryDevice = std::function<Core::Devices::BaseDevice*(u32, const char*, int, u16)>;
// prefix path // prefix path
static std::map<std::string, FactoryDevice> available_device = { static std::map<std::string, FactoryDevice> available_device = {
{"/dev/hid", &Core::Devices::HidDevice::Create},
}; };
namespace Libraries::Kernel { namespace Libraries::Kernel {

View File

@ -408,7 +408,6 @@ int PS4_SYSV_ABI kernel_ioctl(int fd, u64 cmd, VA_ARGS) {
} }
VA_CTX(ctx); VA_CTX(ctx);
int result = file->device->ioctl(cmd, &ctx); int result = file->device->ioctl(cmd, &ctx);
LOG_TRACE(Lib_Kernel, "ioctl: fd = {:X} cmd = {:X} result = {}", fd, cmd, result);
if (result < 0) { if (result < 0) {
ErrSceToPosix(result); ErrSceToPosix(result);
return -1; return -1;

View File

@ -90,7 +90,7 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) {
Libraries::SharePlay::RegisterlibSceSharePlay(sym); Libraries::SharePlay::RegisterlibSceSharePlay(sym);
Libraries::Remoteplay::RegisterlibSceRemoteplay(sym); Libraries::Remoteplay::RegisterlibSceRemoteplay(sym);
Libraries::Videodec::RegisterlibSceVideodec(sym); Libraries::Videodec::RegisterlibSceVideodec(sym);
Libraries::Mouse::RegisterlibSceMouse(sym); // Libraries::Mouse::RegisterlibSceMouse(sym);
} }
} // namespace Libraries } // namespace Libraries

View File

@ -117,10 +117,10 @@ void Emulator::Run(const std::filesystem::path& file) {
auto& game_info = Common::ElfInfo::Instance(); auto& game_info = Common::ElfInfo::Instance();
// Loading param.sfo file if exists // Loading param.sfo file if exists
std::string id; std::string id = "unknown_serial";
std::string title; std::string title = "unknown_title";
std::string app_version; std::string app_version = "unknown_version";
u32 fw_version; u32 fw_version = 0x4700000;
std::filesystem::path sce_sys_folder = eboot_path.parent_path() / "sce_sys"; std::filesystem::path sce_sys_folder = eboot_path.parent_path() / "sce_sys";
if (std::filesystem::is_directory(sce_sys_folder)) { if (std::filesystem::is_directory(sce_sys_folder)) {
@ -274,18 +274,20 @@ void Emulator::Run(const std::filesystem::path& file) {
} }
void Emulator::LoadSystemModules(const std::filesystem::path& file, std::string game_serial) { void Emulator::LoadSystemModules(const std::filesystem::path& file, std::string game_serial) {
constexpr std::array<SysModules, 11> ModulesToLoad{ constexpr std::array<SysModules, 12> ModulesToLoad{{
{{"libSceNgs2.sprx", &Libraries::Ngs2::RegisterlibSceNgs2}, {"libSceNgs2.sprx", &Libraries::Ngs2::RegisterlibSceNgs2},
{"libSceFiber.sprx", &Libraries::Fiber::RegisterlibSceFiber}, {"libSceFiber.sprx", &Libraries::Fiber::RegisterlibSceFiber},
{"libSceUlt.sprx", nullptr}, {"libSceUlt.sprx", nullptr},
{"libSceJson.sprx", nullptr}, {"libSceJson.sprx", nullptr},
{"libSceJson2.sprx", nullptr}, {"libSceJson2.sprx", nullptr},
{"libSceLibcInternal.sprx", &Libraries::LibcInternal::RegisterlibSceLibcInternal}, {"libSceLibcInternal.sprx", &Libraries::LibcInternal::RegisterlibSceLibcInternal},
{"libSceDiscMap.sprx", &Libraries::DiscMap::RegisterlibSceDiscMap}, {"libSceDiscMap.sprx", &Libraries::DiscMap::RegisterlibSceDiscMap},
{"libSceRtc.sprx", &Libraries::Rtc::RegisterlibSceRtc}, {"libSceRtc.sprx", &Libraries::Rtc::RegisterlibSceRtc},
{"libSceJpegEnc.sprx", nullptr}, {"libSceJpegEnc.sprx", nullptr},
{"libSceRazorCpu.sprx", nullptr}, {"libSceRazorCpu.sprx", nullptr},
{"libSceCesCs.sprx", nullptr}}}; {"libSceCesCs.sprx", nullptr},
{"libSceMouse.sprx", nullptr},
}};
std::vector<std::filesystem::path> found_modules; std::vector<std::filesystem::path> found_modules;
const auto& sys_module_path = Common::FS::GetUserPath(Common::FS::PathType::SysModuleDir); const auto& sys_module_path = Common::FS::GetUserPath(Common::FS::PathType::SysModuleDir);

View File

@ -12,10 +12,18 @@ GameMouse::GameMouse() {
} }
int GameMouse::ReadStates(MouseState* states, int states_num) { int GameMouse::ReadStates(MouseState* states, int states_num) {
if (states_num == 0) {
return 0;
}
std::scoped_lock lock{m_mutex}; std::scoped_lock lock{m_mutex};
const u32 count = std::min(m_states_num, u32(states_num)); 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; u32 begin = (m_index - m_states_num + 1) % MAX_MOUSE_STATES;
for (u32 i = 0; i < count; i++) { for (u32 i = 0; i < count; i++) {
u32 idx = (begin + i) % MAX_MOUSE_STATES; u32 idx = (begin + i) % MAX_MOUSE_STATES;