summaryrefslogtreecommitdiffstats
path: root/src/input_common
diff options
context:
space:
mode:
authorNarr the Reg <juangerman-13@hotmail.com>2021-11-26 22:45:37 +0100
committerNarr the Reg <juangerman-13@hotmail.com>2021-11-26 22:46:36 +0100
commit639402850ac65c694967ef6519becb65abe89b39 (patch)
tree55ab559c417a519ac8b93a746428842e53c19a31 /src/input_common
parentservice/hid: Finish converting LIFO objects and address some nits (diff)
downloadyuzu-639402850ac65c694967ef6519becb65abe89b39.tar
yuzu-639402850ac65c694967ef6519becb65abe89b39.tar.gz
yuzu-639402850ac65c694967ef6519becb65abe89b39.tar.bz2
yuzu-639402850ac65c694967ef6519becb65abe89b39.tar.lz
yuzu-639402850ac65c694967ef6519becb65abe89b39.tar.xz
yuzu-639402850ac65c694967ef6519becb65abe89b39.tar.zst
yuzu-639402850ac65c694967ef6519becb65abe89b39.zip
Diffstat (limited to 'src/input_common')
-rw-r--r--src/input_common/drivers/udp_client.cpp206
-rw-r--r--src/input_common/drivers/udp_client.h56
-rw-r--r--src/input_common/helpers/udp_protocol.h75
-rw-r--r--src/input_common/input_mapping.cpp6
-rw-r--r--src/input_common/main.cpp26
5 files changed, 334 insertions, 35 deletions
diff --git a/src/input_common/drivers/udp_client.cpp b/src/input_common/drivers/udp_client.cpp
index 7cab707da..fdee0f2d5 100644
--- a/src/input_common/drivers/udp_client.cpp
+++ b/src/input_common/drivers/udp_client.cpp
@@ -103,7 +103,7 @@ private:
// Send a request for getting pad data for the pad
const Request::PadData pad_data{
- Request::PadData::Flags::AllPorts,
+ Request::RegisterFlags::AllPads,
0,
EMPTY_MAC_ADDRESS,
};
@@ -247,7 +247,12 @@ void UDPClient::OnPadData(Response::PadData data, std::size_t client) {
for (std::size_t id = 0; id < data.touch.size(); ++id) {
const auto touch_pad = data.touch[id];
- const int touch_id = static_cast<int>(client * 2 + id);
+ const auto touch_axis_x_id =
+ static_cast<int>(id == 0 ? PadAxes::Touch1X : PadAxes::Touch2X);
+ const auto touch_axis_y_id =
+ static_cast<int>(id == 0 ? PadAxes::Touch1Y : PadAxes::Touch2Y);
+ const auto touch_button_id =
+ static_cast<int>(id == 0 ? PadButton::Touch1 : PadButton::touch2);
// TODO: Use custom calibration per device
const Common::ParamPackage touch_param(Settings::values.touch_device.GetValue());
@@ -264,14 +269,35 @@ void UDPClient::OnPadData(Response::PadData data, std::size_t client) {
static_cast<f32>(max_y - min_y);
if (touch_pad.is_active) {
- SetAxis(identifier, touch_id * 2, x);
- SetAxis(identifier, touch_id * 2 + 1, y);
- SetButton(identifier, touch_id, true);
+ SetAxis(identifier, touch_axis_x_id, x);
+ SetAxis(identifier, touch_axis_y_id, y);
+ SetButton(identifier, touch_button_id, true);
continue;
}
- SetAxis(identifier, touch_id * 2, 0);
- SetAxis(identifier, touch_id * 2 + 1, 0);
- SetButton(identifier, touch_id, false);
+ SetAxis(identifier, touch_axis_x_id, 0);
+ SetAxis(identifier, touch_axis_y_id, 0);
+ SetButton(identifier, touch_button_id, false);
+ }
+
+ SetAxis(identifier, static_cast<int>(PadAxes::LeftStickX),
+ (data.left_stick_x - 127.0f) / 127.0f);
+ SetAxis(identifier, static_cast<int>(PadAxes::LeftStickY),
+ (data.left_stick_y - 127.0f) / 127.0f);
+ SetAxis(identifier, static_cast<int>(PadAxes::RightStickX),
+ (data.right_stick_x - 127.0f) / 127.0f);
+ SetAxis(identifier, static_cast<int>(PadAxes::RightStickY),
+ (data.right_stick_y - 127.0f) / 127.0f);
+
+ static constexpr std::array<PadButton, 16> buttons{
+ PadButton::Share, PadButton::L3, PadButton::R3, PadButton::Options,
+ PadButton::Up, PadButton::Right, PadButton::Down, PadButton::Left,
+ PadButton::L2, PadButton::R2, PadButton::L1, PadButton::R1,
+ PadButton::Triangle, PadButton::Circle, PadButton::Cross, PadButton::Square};
+
+ for (std::size_t i = 0; i < buttons.size(); ++i) {
+ const bool button_status = (data.digital_button & (1U << i)) != 0;
+ const int button = static_cast<int>(buttons[i]);
+ SetButton(identifier, button, button_status);
}
}
@@ -317,6 +343,170 @@ void UDPClient::Reset() {
}
}
+std::vector<Common::ParamPackage> UDPClient::GetInputDevices() const {
+ std::vector<Common::ParamPackage> devices;
+ if (!Settings::values.enable_udp_controller) {
+ return devices;
+ }
+ for (std::size_t client = 0; client < clients.size(); client++) {
+ if (clients[client].active != 1) {
+ continue;
+ }
+ for (std::size_t index = 0; index < PADS_PER_CLIENT; ++index) {
+ const std::size_t pad_index = client * PADS_PER_CLIENT + index;
+ if (!pads[pad_index].connected) {
+ continue;
+ }
+ const auto pad_identifier = GetPadIdentifier(pad_index);
+ Common::ParamPackage identifier{};
+ identifier.Set("engine", GetEngineName());
+ identifier.Set("display", fmt::format("UDP Controller {}", pad_identifier.pad));
+ identifier.Set("guid", pad_identifier.guid.Format());
+ identifier.Set("port", static_cast<int>(pad_identifier.port));
+ identifier.Set("pad", static_cast<int>(pad_identifier.pad));
+ devices.emplace_back(identifier);
+ }
+ }
+ return devices;
+}
+
+ButtonMapping UDPClient::GetButtonMappingForDevice(const Common::ParamPackage& params) {
+ // This list excludes any button that can't be really mapped
+ static constexpr std::array<std::pair<Settings::NativeButton::Values, PadButton>, 18>
+ switch_to_dsu_button = {
+ std::pair{Settings::NativeButton::A, PadButton::Circle},
+ {Settings::NativeButton::B, PadButton::Cross},
+ {Settings::NativeButton::X, PadButton::Triangle},
+ {Settings::NativeButton::Y, PadButton::Square},
+ {Settings::NativeButton::Plus, PadButton::Options},
+ {Settings::NativeButton::Minus, PadButton::Share},
+ {Settings::NativeButton::DLeft, PadButton::Left},
+ {Settings::NativeButton::DUp, PadButton::Up},
+ {Settings::NativeButton::DRight, PadButton::Right},
+ {Settings::NativeButton::DDown, PadButton::Down},
+ {Settings::NativeButton::L, PadButton::L1},
+ {Settings::NativeButton::R, PadButton::R1},
+ {Settings::NativeButton::ZL, PadButton::L2},
+ {Settings::NativeButton::ZR, PadButton::R2},
+ {Settings::NativeButton::SL, PadButton::L2},
+ {Settings::NativeButton::SR, PadButton::R2},
+ {Settings::NativeButton::LStick, PadButton::L3},
+ {Settings::NativeButton::RStick, PadButton::R3},
+ };
+ if (!params.Has("guid") || !params.Has("port") || !params.Has("pad")) {
+ return {};
+ }
+
+ ButtonMapping mapping{};
+ for (const auto& [switch_button, dsu_button] : switch_to_dsu_button) {
+ Common::ParamPackage button_params{};
+ button_params.Set("engine", GetEngineName());
+ button_params.Set("guid", params.Get("guid", ""));
+ button_params.Set("port", params.Get("port", 0));
+ button_params.Set("pad", params.Get("pad", 0));
+ button_params.Set("button", static_cast<int>(dsu_button));
+ mapping.insert_or_assign(switch_button, std::move(button_params));
+ }
+
+ return mapping;
+}
+
+AnalogMapping UDPClient::GetAnalogMappingForDevice(const Common::ParamPackage& params) {
+ if (!params.Has("guid") || !params.Has("port") || !params.Has("pad")) {
+ return {};
+ }
+
+ AnalogMapping mapping = {};
+ Common::ParamPackage left_analog_params;
+ left_analog_params.Set("engine", GetEngineName());
+ left_analog_params.Set("guid", params.Get("guid", ""));
+ left_analog_params.Set("port", params.Get("port", 0));
+ left_analog_params.Set("pad", params.Get("pad", 0));
+ left_analog_params.Set("axis_x", static_cast<int>(PadAxes::LeftStickX));
+ left_analog_params.Set("axis_y", static_cast<int>(PadAxes::LeftStickY));
+ mapping.insert_or_assign(Settings::NativeAnalog::LStick, std::move(left_analog_params));
+ Common::ParamPackage right_analog_params;
+ right_analog_params.Set("engine", GetEngineName());
+ right_analog_params.Set("guid", params.Get("guid", ""));
+ right_analog_params.Set("port", params.Get("port", 0));
+ right_analog_params.Set("pad", params.Get("pad", 0));
+ right_analog_params.Set("axis_x", static_cast<int>(PadAxes::RightStickX));
+ right_analog_params.Set("axis_y", static_cast<int>(PadAxes::RightStickY));
+ mapping.insert_or_assign(Settings::NativeAnalog::RStick, std::move(right_analog_params));
+ return mapping;
+}
+
+MotionMapping UDPClient::GetMotionMappingForDevice(const Common::ParamPackage& params) {
+ if (!params.Has("guid") || !params.Has("port") || !params.Has("pad")) {
+ return {};
+ }
+
+ MotionMapping mapping = {};
+ Common::ParamPackage motion_params;
+ motion_params.Set("engine", GetEngineName());
+ motion_params.Set("guid", params.Get("guid", ""));
+ motion_params.Set("port", params.Get("port", 0));
+ motion_params.Set("pad", params.Get("pad", 0));
+ motion_params.Set("motion", 0);
+ mapping.insert_or_assign(Settings::NativeMotion::MotionLeft, std::move(motion_params));
+ mapping.insert_or_assign(Settings::NativeMotion::MotionRight, std::move(motion_params));
+ return mapping;
+}
+
+Common::Input::ButtonNames UDPClient::GetUIButtonName(const Common::ParamPackage& params) const {
+ PadButton button = static_cast<PadButton>(params.Get("button", 0));
+ switch (button) {
+ case PadButton::Left:
+ return Common::Input::ButtonNames::ButtonLeft;
+ case PadButton::Right:
+ return Common::Input::ButtonNames::ButtonRight;
+ case PadButton::Down:
+ return Common::Input::ButtonNames::ButtonDown;
+ case PadButton::Up:
+ return Common::Input::ButtonNames::ButtonUp;
+ case PadButton::L1:
+ return Common::Input::ButtonNames::L1;
+ case PadButton::L2:
+ return Common::Input::ButtonNames::L2;
+ case PadButton::L3:
+ return Common::Input::ButtonNames::L3;
+ case PadButton::R1:
+ return Common::Input::ButtonNames::R1;
+ case PadButton::R2:
+ return Common::Input::ButtonNames::R2;
+ case PadButton::R3:
+ return Common::Input::ButtonNames::R3;
+ case PadButton::Circle:
+ return Common::Input::ButtonNames::Circle;
+ case PadButton::Cross:
+ return Common::Input::ButtonNames::Cross;
+ case PadButton::Square:
+ return Common::Input::ButtonNames::Square;
+ case PadButton::Triangle:
+ return Common::Input::ButtonNames::Triangle;
+ case PadButton::Share:
+ return Common::Input::ButtonNames::Share;
+ case PadButton::Options:
+ return Common::Input::ButtonNames::Options;
+ default:
+ return Common::Input::ButtonNames::Undefined;
+ }
+}
+
+Common::Input::ButtonNames UDPClient::GetUIName(const Common::ParamPackage& params) const {
+ if (params.Has("button")) {
+ return GetUIButtonName(params);
+ }
+ if (params.Has("axis")) {
+ return Common::Input::ButtonNames::Value;
+ }
+ if (params.Has("motion")) {
+ return Common::Input::ButtonNames::Engine;
+ }
+
+ return Common::Input::ButtonNames::Invalid;
+}
+
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/drivers/udp_client.h b/src/input_common/drivers/udp_client.h
index 1f02adba5..5d483f26b 100644
--- a/src/input_common/drivers/udp_client.h
+++ b/src/input_common/drivers/udp_client.h
@@ -56,7 +56,61 @@ public:
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;
+
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,
+ };
+
+ 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{};
@@ -90,6 +144,8 @@ private:
const PadIdentifier GetPadIdentifier(std::size_t pad_index) const;
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;
diff --git a/src/input_common/helpers/udp_protocol.h b/src/input_common/helpers/udp_protocol.h
index 1bdc9209e..bcba12c58 100644
--- a/src/input_common/helpers/udp_protocol.h
+++ b/src/input_common/helpers/udp_protocol.h
@@ -56,6 +56,12 @@ constexpr Type GetMessageType();
namespace Request {
+enum RegisterFlags : u8 {
+ AllPads,
+ PadID,
+ PadMACAdddress,
+};
+
struct Version {};
/**
* Requests the server to send information about what controllers are plugged into the ports
@@ -77,13 +83,8 @@ static_assert(std::is_trivially_copyable_v<PortInfo>,
* timeout seems to be 5 seconds.
*/
struct PadData {
- enum class Flags : u8 {
- AllPorts,
- Id,
- Mac,
- };
/// Determines which method will be used as a look up for the controller
- Flags flags{};
+ RegisterFlags flags{};
/// Index of the port of the controller to retrieve data about
u8 port_id{};
/// Mac address of the controller to retrieve data about
@@ -113,6 +114,36 @@ Message<T> Create(const T data, const u32 client_id = 0) {
namespace Response {
+enum class ConnectionType : u8 {
+ None,
+ Usb,
+ Bluetooth,
+};
+
+enum class State : u8 {
+ Disconnected,
+ Reserved,
+ Connected,
+};
+
+enum class Model : u8 {
+ None,
+ PartialGyro,
+ FullGyro,
+ Generic,
+};
+
+enum class Battery : u8 {
+ None = 0x00,
+ Dying = 0x01,
+ Low = 0x02,
+ Medium = 0x03,
+ High = 0x04,
+ Full = 0x05,
+ Charging = 0xEE,
+ Charged = 0xEF,
+};
+
struct Version {
u16_le version{};
};
@@ -122,11 +153,11 @@ static_assert(std::is_trivially_copyable_v<Version>,
struct PortInfo {
u8 id{};
- u8 state{};
- u8 model{};
- u8 connection_type{};
+ State state{};
+ Model model{};
+ ConnectionType connection_type{};
MacAddress mac;
- u8 battery{};
+ Battery battery{};
u8 is_pad_active{};
};
static_assert(sizeof(PortInfo) == 12, "UDP Response PortInfo struct has wrong size");
@@ -177,18 +208,18 @@ struct PadData {
u8 right_stick_y{};
struct AnalogButton {
- u8 button_8{};
- u8 button_7{};
- u8 button_6{};
- u8 button_5{};
- u8 button_12{};
- u8 button_11{};
- u8 button_10{};
- u8 button_9{};
- u8 button_16{};
- u8 button_15{};
- u8 button_14{};
- u8 button_13{};
+ u8 button_dpad_left_analog{};
+ u8 button_dpad_down_analog{};
+ u8 button_dpad_right_analog{};
+ u8 button_dpad_up_analog{};
+ u8 button_square_analog{};
+ u8 button_cross_analog{};
+ u8 button_circle_analog{};
+ u8 button_triangle_analog{};
+ u8 button_r1_analog{};
+ u8 button_l1_analog{};
+ u8 trigger_r2{};
+ u8 trigger_l2{};
} analog_button;
std::array<TouchPad, 2> touch;
diff --git a/src/input_common/input_mapping.cpp b/src/input_common/input_mapping.cpp
index c5218f2cb..6e0024b2d 100644
--- a/src/input_common/input_mapping.cpp
+++ b/src/input_common/input_mapping.cpp
@@ -3,6 +3,7 @@
// Refer to the license.txt file included
#include "common/common_types.h"
+#include "common/settings.h"
#include "input_common/input_engine.h"
#include "input_common/input_mapping.h"
@@ -182,6 +183,11 @@ bool MappingFactory::IsDriverValid(const MappingData& data) const {
if (data.engine == "keyboard" && data.pad.port != 0) {
return false;
}
+ // To prevent mapping with two devices we disable any UDP except motion
+ if (!Settings::values.enable_udp_controller && data.engine == "cemuhookudp" &&
+ data.type != EngineInputType::Motion) {
+ return false;
+ }
// The following drivers don't need to be mapped
if (data.engine == "tas") {
return false;
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index 39e4935dc..940744c5f 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -63,9 +63,12 @@ struct InputSubsystem::Impl {
udp_client = std::make_shared<CemuhookUDP::UDPClient>("cemuhookudp");
udp_client->SetMappingCallback(mapping_callback);
- udp_client_factory = std::make_shared<InputFactory>(udp_client);
+ udp_client_input_factory = std::make_shared<InputFactory>(udp_client);
+ udp_client_output_factory = std::make_shared<OutputFactory>(udp_client);
Common::Input::RegisterFactory<Common::Input::InputDevice>(udp_client->GetEngineName(),
- udp_client_factory);
+ udp_client_input_factory);
+ Common::Input::RegisterFactory<Common::Input::OutputDevice>(udp_client->GetEngineName(),
+ udp_client_output_factory);
tas_input = std::make_shared<TasInput::Tas>("tas");
tas_input->SetMappingCallback(mapping_callback);
@@ -110,6 +113,7 @@ struct InputSubsystem::Impl {
gcadapter.reset();
Common::Input::UnregisterFactory<Common::Input::InputDevice>(udp_client->GetEngineName());
+ Common::Input::UnregisterFactory<Common::Input::OutputDevice>(udp_client->GetEngineName());
udp_client.reset();
Common::Input::UnregisterFactory<Common::Input::InputDevice>(tas_input->GetEngineName());
@@ -137,6 +141,8 @@ struct InputSubsystem::Impl {
devices.insert(devices.end(), mouse_devices.begin(), mouse_devices.end());
auto gcadapter_devices = gcadapter->GetInputDevices();
devices.insert(devices.end(), gcadapter_devices.begin(), gcadapter_devices.end());
+ auto udp_devices = udp_client->GetInputDevices();
+ devices.insert(devices.end(), udp_devices.begin(), udp_devices.end());
#ifdef HAVE_SDL2
auto sdl_devices = sdl->GetInputDevices();
devices.insert(devices.end(), sdl_devices.begin(), sdl_devices.end());
@@ -157,6 +163,9 @@ struct InputSubsystem::Impl {
if (engine == gcadapter->GetEngineName()) {
return gcadapter->GetAnalogMappingForDevice(params);
}
+ if (engine == udp_client->GetEngineName()) {
+ return udp_client->GetAnalogMappingForDevice(params);
+ }
if (engine == tas_input->GetEngineName()) {
return tas_input->GetAnalogMappingForDevice(params);
}
@@ -177,6 +186,9 @@ struct InputSubsystem::Impl {
if (engine == gcadapter->GetEngineName()) {
return gcadapter->GetButtonMappingForDevice(params);
}
+ if (engine == udp_client->GetEngineName()) {
+ return udp_client->GetButtonMappingForDevice(params);
+ }
if (engine == tas_input->GetEngineName()) {
return tas_input->GetButtonMappingForDevice(params);
}
@@ -194,8 +206,8 @@ struct InputSubsystem::Impl {
return {};
}
const std::string engine = params.Get("engine", "");
- if (engine == gcadapter->GetEngineName()) {
- return gcadapter->GetMotionMappingForDevice(params);
+ if (engine == udp_client->GetEngineName()) {
+ return udp_client->GetMotionMappingForDevice(params);
}
#ifdef HAVE_SDL2
if (engine == sdl->GetEngineName()) {
@@ -238,6 +250,9 @@ struct InputSubsystem::Impl {
if (engine == gcadapter->GetEngineName()) {
return true;
}
+ if (engine == udp_client->GetEngineName()) {
+ return true;
+ }
if (engine == tas_input->GetEngineName()) {
return true;
}
@@ -286,12 +301,13 @@ struct InputSubsystem::Impl {
std::shared_ptr<InputFactory> mouse_factory;
std::shared_ptr<InputFactory> gcadapter_input_factory;
std::shared_ptr<InputFactory> touch_screen_factory;
- std::shared_ptr<InputFactory> udp_client_factory;
+ std::shared_ptr<InputFactory> udp_client_input_factory;
std::shared_ptr<InputFactory> tas_input_factory;
std::shared_ptr<OutputFactory> keyboard_output_factory;
std::shared_ptr<OutputFactory> mouse_output_factory;
std::shared_ptr<OutputFactory> gcadapter_output_factory;
+ std::shared_ptr<OutputFactory> udp_client_output_factory;
std::shared_ptr<OutputFactory> tas_output_factory;
#ifdef HAVE_SDL2