File size: 5,413 Bytes
3708354 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | // SPDX-FileCopyrightText: 2018 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <optional>
#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<CalibrationData> 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<Common::ParamPackage> 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<std::chrono::steady_clock> 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> 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<PadData, MAX_UDP_CLIENTS * PADS_PER_CLIENT> pads{};
std::array<ClientConnection, MAX_UDP_CLIENTS> 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<void(Status)> status_callback,
std::function<void(u16, u16, u16, u16)> data_callback);
~CalibrationConfigurationJob();
void Stop();
private:
Common::Event complete_event;
};
void TestCommunication(const std::string& host, u16 port,
const std::function<void()>& success_callback,
const std::function<void()>& failure_callback);
} // namespace InputCommon::CemuhookUDP
|