// SPDX-FileCopyrightText: 2018 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include #include "common/common_types.h" #include "common/thread.h" #include "input_common/input_engine.h" namespace InputCommon::CemuhookUDP { class Socket; namespace Response { enum class Battery : u8; struct PadData; struct PortInfo; struct TouchPad; struct Version; } // namespace Response enum class PadTouch { Click, Undefined, }; struct UDPPadStatus { std::string host{"127.0.0.1"}; u16 port{26760}; std::size_t pad_index{}; }; struct DeviceStatus { std::mutex update_mutex; // calibration data for scaling the device's touch area to 3ds struct CalibrationData { u16 min_x{}; u16 min_y{}; u16 max_x{}; u16 max_y{}; }; std::optional touch_calibration; }; /** * A button device factory representing a keyboard. It receives keyboard events and forward them * to all button devices it created. */ class UDPClient final : public InputEngine { public: explicit UDPClient(std::string input_engine_); ~UDPClient() override; void ReloadSockets(); /// Used for automapping features std::vector GetInputDevices() const override; ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override; AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override; MotionMapping GetMotionMappingForDevice(const Common::ParamPackage& params) override; Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override; bool IsStickInverted(const Common::ParamPackage& params) override; private: enum class PadButton { Undefined = 0x0000, Share = 0x0001, L3 = 0x0002, R3 = 0x0004, Options = 0x0008, Up = 0x0010, Right = 0x0020, Down = 0x0040, Left = 0x0080, L2 = 0x0100, R2 = 0x0200, L1 = 0x0400, R1 = 0x0800, Triangle = 0x1000, Circle = 0x2000, Cross = 0x4000, Square = 0x8000, Touch1 = 0x10000, Touch2 = 0x20000, Home = 0x40000, TouchHardPress = 0x80000, }; enum class PadAxes : u8 { LeftStickX, LeftStickY, RightStickX, RightStickY, AnalogLeft, AnalogDown, AnalogRight, AnalogUp, AnalogSquare, AnalogCross, AnalogCircle, AnalogTriangle, AnalogR1, AnalogL1, AnalogR2, AnalogL3, AnalogR3, Touch1X, Touch1Y, Touch2X, Touch2Y, Undefined, }; struct PadData { std::size_t pad_index{}; bool connected{}; DeviceStatus status; u64 packet_sequence{}; std::chrono::time_point last_update; }; struct ClientConnection { ClientConnection(); ~ClientConnection(); Common::UUID uuid{"00000000-0000-0000-0000-00007F000001"}; std::string host{"127.0.0.1"}; u16 port{26760}; s8 active{-1}; std::unique_ptr socket; std::thread thread; }; // For shutting down, clear all data, join all threads, release usb void Reset(); // Translates configuration to client number std::size_t GetClientNumber(std::string_view host, u16 port) const; // Translates UDP battery level to input engine battery level Common::Input::BatteryLevel GetBatteryLevel(Response::Battery battery) const; void OnVersion(Response::Version); void OnPortInfo(Response::PortInfo); void OnPadData(Response::PadData, std::size_t client); void StartCommunication(std::size_t client, const std::string& host, u16 port); PadIdentifier GetPadIdentifier(std::size_t pad_index) const; Common::UUID GetHostUUID(const std::string& host) const; Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) 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; std::array pads{}; std::array clients{}; }; /// An async job allowing configuration of the touchpad calibration. class CalibrationConfigurationJob { public: enum class Status { Initialized, Ready, Stage1Completed, Completed, }; /** * Constructs and starts the job with the specified parameter. * * @param status_callback Callback for job status updates * @param data_callback Called when calibration data is ready */ explicit CalibrationConfigurationJob(const std::string& host, u16 port, std::function status_callback, std::function data_callback); ~CalibrationConfigurationJob(); void Stop(); private: Common::Event complete_event; }; void TestCommunication(const std::string& host, u16 port, const std::function& success_callback, const std::function& failure_callback); } // namespace InputCommon::CemuhookUDP