diff options
author | german77 <juangerman-13@hotmail.com> | 2021-09-21 00:33:19 +0200 |
---|---|---|
committer | Narr the Reg <juangerman-13@hotmail.com> | 2021-11-25 03:30:22 +0100 |
commit | 10241886ddbead1a24a5924debf83a4fad0ade0d (patch) | |
tree | 6ae225005be45394225533ff2a45f1aae660ab59 /src/input_common/drivers | |
parent | input_common: Rewrite tas input (diff) | |
download | yuzu-10241886ddbead1a24a5924debf83a4fad0ade0d.tar yuzu-10241886ddbead1a24a5924debf83a4fad0ade0d.tar.gz yuzu-10241886ddbead1a24a5924debf83a4fad0ade0d.tar.bz2 yuzu-10241886ddbead1a24a5924debf83a4fad0ade0d.tar.lz yuzu-10241886ddbead1a24a5924debf83a4fad0ade0d.tar.xz yuzu-10241886ddbead1a24a5924debf83a4fad0ade0d.tar.zst yuzu-10241886ddbead1a24a5924debf83a4fad0ade0d.zip |
Diffstat (limited to '')
-rw-r--r-- | src/input_common/drivers/udp_client.cpp (renamed from src/input_common/udp/client.cpp) | 242 | ||||
-rw-r--r-- | src/input_common/drivers/udp_client.h (renamed from src/input_common/udp/client.h) | 80 |
2 files changed, 52 insertions, 270 deletions
diff --git a/src/input_common/udp/client.cpp b/src/input_common/drivers/udp_client.cpp index bcc29c4e0..6fcc3a01b 100644 --- a/src/input_common/udp/client.cpp +++ b/src/input_common/drivers/udp_client.cpp @@ -2,15 +2,13 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include <chrono> -#include <cstring> -#include <functional> #include <random> -#include <thread> #include <boost/asio.hpp> + #include "common/logging/log.h" +#include "common/param_package.h" #include "common/settings.h" -#include "input_common/udp/client.h" +#include "input_common/drivers/udp_client.h" #include "input_common/helpers/udp_protocol.h" using boost::asio::ip::udp; @@ -86,7 +84,6 @@ private: case Type::PadData: { Response::PadData pad_data; std::memcpy(&pad_data, &receive_buffer[sizeof(Header)], sizeof(Response::PadData)); - SanitizeMotion(pad_data); callback.pad_data(std::move(pad_data)); break; } @@ -115,28 +112,6 @@ private: StartSend(timer.expiry()); } - void SanitizeMotion(Response::PadData& data) { - // Zero out any non number value - if (!std::isnormal(data.gyro.pitch)) { - data.gyro.pitch = 0; - } - if (!std::isnormal(data.gyro.roll)) { - data.gyro.roll = 0; - } - if (!std::isnormal(data.gyro.yaw)) { - data.gyro.yaw = 0; - } - if (!std::isnormal(data.accel.x)) { - data.accel.x = 0; - } - if (!std::isnormal(data.accel.y)) { - data.accel.y = 0; - } - if (!std::isnormal(data.accel.z)) { - data.accel.z = 0; - } - } - SocketCallback callback; boost::asio::io_service io_service; boost::asio::basic_waitable_timer<clock> timer; @@ -160,48 +135,23 @@ static void SocketLoop(Socket* socket) { socket->Loop(); } -Client::Client() { +UDPClient::UDPClient(const std::string& input_engine_) : InputEngine(input_engine_) { LOG_INFO(Input, "Udp Initialization started"); - finger_id.fill(MAX_TOUCH_FINGERS); ReloadSockets(); } -Client::~Client() { +UDPClient::~UDPClient() { Reset(); } -Client::ClientConnection::ClientConnection() = default; +UDPClient::ClientConnection::ClientConnection() = default; -Client::ClientConnection::~ClientConnection() = default; - -std::vector<Common::ParamPackage> Client::GetInputDevices() const { - std::vector<Common::ParamPackage> devices; - for (std::size_t pad = 0; pad < pads.size(); pad++) { - if (!DeviceConnected(pad)) { - continue; - } - std::string name = fmt::format("UDP Controller {}", pad); - devices.emplace_back(Common::ParamPackage{ - {"class", "cemuhookudp"}, - {"display", std::move(name)}, - {"port", std::to_string(pad)}, - }); - } - return devices; -} - -bool Client::DeviceConnected(std::size_t pad) const { - // Use last timestamp to detect if the socket has stopped sending data - const auto now = std::chrono::steady_clock::now(); - const auto time_difference = static_cast<u64>( - std::chrono::duration_cast<std::chrono::milliseconds>(now - pads[pad].last_update).count()); - return time_difference < 1000 && pads[pad].connected; -} +UDPClient::ClientConnection::~ClientConnection() = default; -void Client::ReloadSockets() { +void UDPClient::ReloadSockets() { Reset(); - std::stringstream servers_ss(static_cast<std::string>(Settings::values.udp_input_servers)); + std::stringstream servers_ss(Settings::values.udp_input_servers.GetValue()); std::string server_token; std::size_t client = 0; while (std::getline(servers_ss, server_token, ',')) { @@ -229,7 +179,7 @@ void Client::ReloadSockets() { } } -std::size_t Client::GetClientNumber(std::string_view host, u16 port) const { +std::size_t UDPClient::GetClientNumber(std::string_view host, u16 port) const { for (std::size_t client = 0; client < clients.size(); client++) { if (clients[client].active == -1) { continue; @@ -241,15 +191,15 @@ std::size_t Client::GetClientNumber(std::string_view host, u16 port) const { return MAX_UDP_CLIENTS; } -void Client::OnVersion([[maybe_unused]] Response::Version data) { +void UDPClient::OnVersion([[maybe_unused]] Response::Version data) { LOG_TRACE(Input, "Version packet received: {}", data.version); } -void Client::OnPortInfo([[maybe_unused]] Response::PortInfo data) { +void UDPClient::OnPortInfo([[maybe_unused]] Response::PortInfo data) { LOG_TRACE(Input, "PortInfo packet received: {}", data.model); } -void Client::OnPadData(Response::PadData data, std::size_t client) { +void UDPClient::OnPadData(Response::PadData data, std::size_t client) { const std::size_t pad_index = (client * PADS_PER_CLIENT) + data.info.id; if (pad_index >= pads.size()) { @@ -277,32 +227,25 @@ void Client::OnPadData(Response::PadData data, std::size_t client) { .count()); pads[pad_index].last_update = now; - const Common::Vec3f raw_gyroscope = {data.gyro.pitch, data.gyro.roll, -data.gyro.yaw}; - pads[pad_index].motion.SetAcceleration({data.accel.x, -data.accel.z, data.accel.y}); // Gyroscope values are not it the correct scale from better joy. // Dividing by 312 allows us to make one full turn = 1 turn // This must be a configurable valued called sensitivity - pads[pad_index].motion.SetGyroscope(raw_gyroscope / 312.0f); - pads[pad_index].motion.UpdateRotation(time_difference); - pads[pad_index].motion.UpdateOrientation(time_difference); - - { - std::lock_guard guard(pads[pad_index].status.update_mutex); - pads[pad_index].status.motion_status = pads[pad_index].motion.GetMotion(); - - for (std::size_t id = 0; id < data.touch.size(); ++id) { - UpdateTouchInput(data.touch[id], client, id); - } - - if (configuring) { - const Common::Vec3f gyroscope = pads[pad_index].motion.GetGyroscope(); - const Common::Vec3f accelerometer = pads[pad_index].motion.GetAcceleration(); - UpdateYuzuSettings(client, data.info.id, accelerometer, gyroscope); - } - } + const float gyro_scale = 1.0f / 312.0f; + + const BasicMotion motion{ + .gyro_x = data.gyro.pitch * gyro_scale, + .gyro_y = data.gyro.roll * gyro_scale, + .gyro_z = -data.gyro.yaw * gyro_scale, + .accel_x = data.accel.x, + .accel_y = -data.accel.z, + .accel_z = data.accel.y, + .delta_timestamp = time_difference, + }; + const PadIdentifier identifier = GetPadIdentifier(pad_index); + SetMotion(identifier, 0, motion); } -void Client::StartCommunication(std::size_t client, const std::string& host, u16 port) { +void UDPClient::StartCommunication(std::size_t client, const std::string& host, u16 port) { SocketCallback callback{[this](Response::Version version) { OnVersion(version); }, [this](Response::PortInfo info) { OnPortInfo(info); }, [this, client](Response::PadData data) { OnPadData(data, client); }}; @@ -312,16 +255,22 @@ void Client::StartCommunication(std::size_t client, const std::string& host, u16 clients[client].active = 0; clients[client].socket = std::make_unique<Socket>(host, port, callback); clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()}; - - // Set motion parameters - // SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode - // Real HW values are unknown, 0.0001 is an approximate to Standard - for (std::size_t pad = 0; pad < PADS_PER_CLIENT; pad++) { - pads[client * PADS_PER_CLIENT + pad].motion.SetGyroThreshold(0.0001f); + for (std::size_t index = 0; index < PADS_PER_CLIENT; ++index) { + const PadIdentifier identifier = GetPadIdentifier(client * PADS_PER_CLIENT + index); + PreSetController(identifier); } } -void Client::Reset() { +const PadIdentifier UDPClient::GetPadIdentifier(std::size_t pad_index) const { + const std::size_t client = pad_index / PADS_PER_CLIENT; + return { + .guid = Common::UUID{clients[client].host}, + .port = static_cast<std::size_t>(clients[client].port), + .pad = pad_index, + }; +} + +void UDPClient::Reset() { for (auto& client : clients) { if (client.thread.joinable()) { client.active = -1; @@ -331,117 +280,6 @@ void Client::Reset() { } } -void Client::UpdateYuzuSettings(std::size_t client, std::size_t pad_index, - const Common::Vec3<float>& acc, const Common::Vec3<float>& gyro) { - if (gyro.Length() > 0.2f) { - LOG_DEBUG(Input, "UDP Controller {}: gyro=({}, {}, {}), accel=({}, {}, {})", client, - gyro[0], gyro[1], gyro[2], acc[0], acc[1], acc[2]); - } - UDPPadStatus pad{ - .host = clients[client].host, - .port = clients[client].port, - .pad_index = pad_index, - }; - for (std::size_t i = 0; i < 3; ++i) { - if (gyro[i] > 5.0f || gyro[i] < -5.0f) { - pad.motion = static_cast<PadMotion>(i); - pad.motion_value = gyro[i]; - pad_queue.Push(pad); - } - if (acc[i] > 1.75f || acc[i] < -1.75f) { - pad.motion = static_cast<PadMotion>(i + 3); - pad.motion_value = acc[i]; - pad_queue.Push(pad); - } - } -} - -std::optional<std::size_t> Client::GetUnusedFingerID() const { - std::size_t first_free_id = 0; - while (first_free_id < MAX_TOUCH_FINGERS) { - if (!std::get<2>(touch_status[first_free_id])) { - return first_free_id; - } else { - first_free_id++; - } - } - return std::nullopt; -} - -void Client::UpdateTouchInput(Response::TouchPad& touch_pad, std::size_t client, std::size_t id) { - // TODO: Use custom calibration per device - const Common::ParamPackage touch_param(Settings::values.touch_device.GetValue()); - const u16 min_x = static_cast<u16>(touch_param.Get("min_x", 100)); - const u16 min_y = static_cast<u16>(touch_param.Get("min_y", 50)); - const u16 max_x = static_cast<u16>(touch_param.Get("max_x", 1800)); - const u16 max_y = static_cast<u16>(touch_param.Get("max_y", 850)); - const std::size_t touch_id = client * 2 + id; - if (touch_pad.is_active) { - if (finger_id[touch_id] == MAX_TOUCH_FINGERS) { - const auto first_free_id = GetUnusedFingerID(); - if (!first_free_id) { - // Invalid finger id skip to next input - return; - } - finger_id[touch_id] = *first_free_id; - } - auto& [x, y, pressed] = touch_status[finger_id[touch_id]]; - x = static_cast<float>(std::clamp(static_cast<u16>(touch_pad.x), min_x, max_x) - min_x) / - static_cast<float>(max_x - min_x); - y = static_cast<float>(std::clamp(static_cast<u16>(touch_pad.y), min_y, max_y) - min_y) / - static_cast<float>(max_y - min_y); - pressed = true; - return; - } - - if (finger_id[touch_id] != MAX_TOUCH_FINGERS) { - touch_status[finger_id[touch_id]] = {}; - finger_id[touch_id] = MAX_TOUCH_FINGERS; - } -} - -void Client::BeginConfiguration() { - pad_queue.Clear(); - configuring = true; -} - -void Client::EndConfiguration() { - pad_queue.Clear(); - configuring = false; -} - -DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) { - const std::size_t client_number = GetClientNumber(host, port); - if (client_number == MAX_UDP_CLIENTS || pad >= PADS_PER_CLIENT) { - return pads[0].status; - } - return pads[(client_number * PADS_PER_CLIENT) + pad].status; -} - -const DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) const { - const std::size_t client_number = GetClientNumber(host, port); - if (client_number == MAX_UDP_CLIENTS || pad >= PADS_PER_CLIENT) { - return pads[0].status; - } - return pads[(client_number * PADS_PER_CLIENT) + pad].status; -} - -Input::TouchStatus& Client::GetTouchState() { - return touch_status; -} - -const Input::TouchStatus& Client::GetTouchState() const { - return touch_status; -} - -Common::SPSCQueue<UDPPadStatus>& Client::GetPadQueue() { - return pad_queue; -} - -const Common::SPSCQueue<UDPPadStatus>& Client::GetPadQueue() const { - return pad_queue; -} - void TestCommunication(const std::string& host, u16 port, const std::function<void()>& success_callback, const std::function<void()>& failure_callback) { diff --git a/src/input_common/udp/client.h b/src/input_common/drivers/udp_client.h index 380f9bb76..58b2e921d 100644 --- a/src/input_common/udp/client.h +++ b/src/input_common/drivers/udp_client.h @@ -1,23 +1,14 @@ -// Copyright 2018 Citra Emulator Project +// Copyright 2021 yuzu Emulator Project // Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// Refer to the license.txt file included #pragma once -#include <functional> -#include <memory> -#include <mutex> #include <optional> -#include <string> -#include <thread> -#include <tuple> + #include "common/common_types.h" -#include "common/param_package.h" #include "common/thread.h" -#include "common/threadsafe_queue.h" -#include "common/vector_math.h" -#include "core/frontend/input.h" -#include "input_common/motion_input.h" +#include "input_common/input_engine.h" namespace InputCommon::CemuhookUDP { @@ -30,16 +21,6 @@ struct TouchPad; struct Version; } // namespace Response -enum class PadMotion { - GyroX, - GyroY, - GyroZ, - AccX, - AccY, - AccZ, - Undefined, -}; - enum class PadTouch { Click, Undefined, @@ -49,14 +30,10 @@ struct UDPPadStatus { std::string host{"127.0.0.1"}; u16 port{26760}; std::size_t pad_index{}; - PadMotion motion{PadMotion::Undefined}; - f32 motion_value{0.0f}; }; struct DeviceStatus { std::mutex update_mutex; - Input::MotionStatus motion_status; - std::tuple<float, float, bool> touch_status; // calibration data for scaling the device's touch area to 3ds struct CalibrationData { @@ -68,32 +45,17 @@ struct DeviceStatus { std::optional<CalibrationData> touch_calibration; }; -class Client { +/** + * A button device factory representing a keyboard. It receives keyboard events and forward them + * to all button devices it created. + */ +class UDPClient final : public InputCommon::InputEngine { public: - // Initialize the UDP client capture and read sequence - Client(); - - // Close and release the client - ~Client(); - - // Used for polling - void BeginConfiguration(); - void EndConfiguration(); - - std::vector<Common::ParamPackage> GetInputDevices() const; + explicit UDPClient(const std::string& input_engine_); + ~UDPClient(); - bool DeviceConnected(std::size_t pad) const; void ReloadSockets(); - Common::SPSCQueue<UDPPadStatus>& GetPadQueue(); - const Common::SPSCQueue<UDPPadStatus>& GetPadQueue() const; - - DeviceStatus& GetPadState(const std::string& host, u16 port, std::size_t pad); - const DeviceStatus& GetPadState(const std::string& host, u16 port, std::size_t pad) const; - - Input::TouchStatus& GetTouchState(); - const Input::TouchStatus& GetTouchState() const; - private: struct PadData { std::size_t pad_index{}; @@ -101,9 +63,6 @@ private: DeviceStatus status; u64 packet_sequence{}; - // Realtime values - // motion is initalized with PID values for drift correction on joycons - InputCommon::MotionInput motion{0.3f, 0.005f, 0.0f}; std::chrono::time_point<std::chrono::steady_clock> last_update; }; @@ -127,28 +86,13 @@ private: void OnPortInfo(Response::PortInfo); void OnPadData(Response::PadData, std::size_t client); void StartCommunication(std::size_t client, const std::string& host, u16 port); - void UpdateYuzuSettings(std::size_t client, std::size_t pad_index, - const Common::Vec3<float>& acc, const Common::Vec3<float>& gyro); - - // Returns an unused finger id, if there is no fingers available std::nullopt will be - // returned - std::optional<std::size_t> GetUnusedFingerID() const; - - // Merges and updates all touch inputs into the touch_status array - void UpdateTouchInput(Response::TouchPad& touch_pad, std::size_t client, std::size_t id); - - bool configuring = false; + const PadIdentifier GetPadIdentifier(std::size_t pad_index) const; // Allocate clients for 8 udp servers static constexpr std::size_t MAX_UDP_CLIENTS = 8; static constexpr std::size_t PADS_PER_CLIENT = 4; - // Each client can have up 2 touch inputs - static constexpr std::size_t MAX_TOUCH_FINGERS = MAX_UDP_CLIENTS * 2; std::array<PadData, MAX_UDP_CLIENTS * PADS_PER_CLIENT> pads{}; std::array<ClientConnection, MAX_UDP_CLIENTS> clients{}; - Common::SPSCQueue<UDPPadStatus> pad_queue{}; - Input::TouchStatus touch_status{}; - std::array<std::size_t, MAX_TOUCH_FINGERS> finger_id{}; }; /// An async job allowing configuration of the touchpad calibration. |