summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2021-12-18 08:43:19 +0100
committerGitHub <noreply@github.com>2021-12-18 08:43:19 +0100
commit212b497d5c60676036dcd541ca54cf0ab260f344 (patch)
treebdfb846bdec1bbd04cf827017f3adba5cccb9a6c
parentMerge pull request #7399 from ameerj/art-refactor (diff)
parent[input_common] Move variable declaration closer to usage (diff)
downloadyuzu-212b497d5c60676036dcd541ca54cf0ab260f344.tar
yuzu-212b497d5c60676036dcd541ca54cf0ab260f344.tar.gz
yuzu-212b497d5c60676036dcd541ca54cf0ab260f344.tar.bz2
yuzu-212b497d5c60676036dcd541ca54cf0ab260f344.tar.lz
yuzu-212b497d5c60676036dcd541ca54cf0ab260f344.tar.xz
yuzu-212b497d5c60676036dcd541ca54cf0ab260f344.tar.zst
yuzu-212b497d5c60676036dcd541ca54cf0ab260f344.zip
-rw-r--r--src/input_common/drivers/udp_client.cpp74
-rw-r--r--src/input_common/helpers/udp_protocol.h21
-rw-r--r--src/tests/CMakeLists.txt3
-rw-r--r--src/tests/input_common/calibration_configuration_job.cpp136
4 files changed, 190 insertions, 44 deletions
diff --git a/src/input_common/drivers/udp_client.cpp b/src/input_common/drivers/udp_client.cpp
index 4ab991a7d..a1ce4525d 100644
--- a/src/input_common/drivers/udp_client.cpp
+++ b/src/input_common/drivers/udp_client.cpp
@@ -536,42 +536,46 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
std::function<void(u16, u16, u16, u16)> data_callback) {
std::thread([=, this] {
+ u16 min_x{UINT16_MAX};
+ u16 min_y{UINT16_MAX};
+ u16 max_x{};
+ u16 max_y{};
+
Status current_status{Status::Initialized};
- SocketCallback callback{
- [](Response::Version) {}, [](Response::PortInfo) {},
- [&](Response::PadData data) {
- static constexpr u16 CALIBRATION_THRESHOLD = 100;
- static constexpr u16 MAX_VALUE = UINT16_MAX;
-
- if (current_status == Status::Initialized) {
- // Receiving data means the communication is ready now
- current_status = Status::Ready;
- status_callback(current_status);
- }
- const auto& touchpad_0 = data.touch[0];
- if (touchpad_0.is_active == 0) {
- return;
- }
- LOG_DEBUG(Input, "Current touch: {} {}", touchpad_0.x, touchpad_0.y);
- const u16 min_x = std::min(MAX_VALUE, static_cast<u16>(touchpad_0.x));
- const u16 min_y = std::min(MAX_VALUE, static_cast<u16>(touchpad_0.y));
- if (current_status == Status::Ready) {
- // First touch - min data (min_x/min_y)
- current_status = Status::Stage1Completed;
- status_callback(current_status);
- }
- if (touchpad_0.x - min_x > CALIBRATION_THRESHOLD &&
- touchpad_0.y - min_y > CALIBRATION_THRESHOLD) {
- // Set the current position as max value and finishes configuration
- const u16 max_x = touchpad_0.x;
- const u16 max_y = touchpad_0.y;
- current_status = Status::Completed;
- data_callback(min_x, min_y, max_x, max_y);
- status_callback(current_status);
-
- complete_event.Set();
- }
- }};
+ SocketCallback callback{[](Response::Version) {}, [](Response::PortInfo) {},
+ [&](Response::PadData data) {
+ constexpr u16 CALIBRATION_THRESHOLD = 100;
+
+ if (current_status == Status::Initialized) {
+ // Receiving data means the communication is ready now
+ current_status = Status::Ready;
+ status_callback(current_status);
+ }
+ if (data.touch[0].is_active == 0) {
+ return;
+ }
+ LOG_DEBUG(Input, "Current touch: {} {}", data.touch[0].x,
+ data.touch[0].y);
+ min_x = std::min(min_x, static_cast<u16>(data.touch[0].x));
+ min_y = std::min(min_y, static_cast<u16>(data.touch[0].y));
+ if (current_status == Status::Ready) {
+ // First touch - min data (min_x/min_y)
+ current_status = Status::Stage1Completed;
+ status_callback(current_status);
+ }
+ if (data.touch[0].x - min_x > CALIBRATION_THRESHOLD &&
+ data.touch[0].y - min_y > CALIBRATION_THRESHOLD) {
+ // Set the current position as max value and finishes
+ // configuration
+ max_x = data.touch[0].x;
+ max_y = data.touch[0].y;
+ current_status = Status::Completed;
+ data_callback(min_x, min_y, max_x, max_y);
+ status_callback(current_status);
+
+ complete_event.Set();
+ }
+ }};
Socket socket{host, port, std::move(callback)};
std::thread worker_thread{SocketLoop, &socket};
complete_event.Wait();
diff --git a/src/input_common/helpers/udp_protocol.h b/src/input_common/helpers/udp_protocol.h
index bcba12c58..2d5d54ddb 100644
--- a/src/input_common/helpers/udp_protocol.h
+++ b/src/input_common/helpers/udp_protocol.h
@@ -54,6 +54,18 @@ struct Message {
template <typename T>
constexpr Type GetMessageType();
+template <typename T>
+Message<T> CreateMessage(const u32 magic, const T data, const u32 sender_id) {
+ boost::crc_32_type crc;
+ Header header{
+ magic, PROTOCOL_VERSION, sizeof(T) + sizeof(Type), 0, sender_id, GetMessageType<T>(),
+ };
+ Message<T> message{header, data};
+ crc.process_bytes(&message, sizeof(Message<T>));
+ message.header.crc = crc.checksum();
+ return message;
+}
+
namespace Request {
enum RegisterFlags : u8 {
@@ -101,14 +113,7 @@ static_assert(std::is_trivially_copyable_v<PadData>,
*/
template <typename T>
Message<T> Create(const T data, const u32 client_id = 0) {
- boost::crc_32_type crc;
- Header header{
- CLIENT_MAGIC, PROTOCOL_VERSION, sizeof(T) + sizeof(Type), 0, client_id, GetMessageType<T>(),
- };
- Message<T> message{header, data};
- crc.process_bytes(&message, sizeof(Message<T>));
- message.header.crc = crc.checksum();
- return message;
+ return CreateMessage(CLIENT_MAGIC, data, client_id);
}
} // namespace Request
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index c4c012f3d..4a20c0768 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -10,11 +10,12 @@ add_executable(tests
core/network/network.cpp
tests.cpp
video_core/buffer_base.cpp
+ input_common/calibration_configuration_job.cpp
)
create_target_directory_groups(tests)
-target_link_libraries(tests PRIVATE common core)
+target_link_libraries(tests PRIVATE common core input_common)
target_link_libraries(tests PRIVATE ${PLATFORM_LIBRARIES} catch-single-include Threads::Threads)
add_test(NAME tests COMMAND tests)
diff --git a/src/tests/input_common/calibration_configuration_job.cpp b/src/tests/input_common/calibration_configuration_job.cpp
new file mode 100644
index 000000000..8c77d81e9
--- /dev/null
+++ b/src/tests/input_common/calibration_configuration_job.cpp
@@ -0,0 +1,136 @@
+// Copyright 2020 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <array>
+#include <string>
+#include <thread>
+#include <boost/asio.hpp>
+#include <boost/crc.hpp>
+#include <catch2/catch.hpp>
+
+#include "input_common/drivers/udp_client.h"
+#include "input_common/helpers/udp_protocol.h"
+
+class FakeCemuhookServer {
+public:
+ FakeCemuhookServer()
+ : socket(io_service, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0)) {}
+
+ ~FakeCemuhookServer() {
+ is_running = false;
+ boost::system::error_code error_code;
+ socket.shutdown(boost::asio::socket_base::shutdown_both, error_code);
+ socket.close();
+ if (handler.joinable()) {
+ handler.join();
+ }
+ }
+
+ u16 GetPort() {
+ return socket.local_endpoint().port();
+ }
+
+ std::string GetHost() {
+ return socket.local_endpoint().address().to_string();
+ }
+
+ void Run(const std::vector<InputCommon::CemuhookUDP::Response::TouchPad> touch_movement_path) {
+ constexpr size_t HeaderSize = sizeof(InputCommon::CemuhookUDP::Header);
+ constexpr size_t PadDataSize =
+ sizeof(InputCommon::CemuhookUDP::Message<InputCommon::CemuhookUDP::Response::PadData>);
+
+ REQUIRE(touch_movement_path.size() > 0);
+ is_running = true;
+ handler = std::thread([touch_movement_path, this]() {
+ auto current_touch_position = touch_movement_path.begin();
+ while (is_running) {
+ boost::asio::ip::udp::endpoint sender_endpoint;
+ boost::system::error_code error_code;
+ auto received_size = socket.receive_from(boost::asio::buffer(receive_buffer),
+ sender_endpoint, 0, error_code);
+
+ if (received_size < HeaderSize) {
+ continue;
+ }
+
+ InputCommon::CemuhookUDP::Header header{};
+ std::memcpy(&header, receive_buffer.data(), HeaderSize);
+ switch (header.type) {
+ case InputCommon::CemuhookUDP::Type::PadData: {
+ InputCommon::CemuhookUDP::Response::PadData pad_data{};
+ pad_data.touch[0] = *current_touch_position;
+ const auto pad_message = InputCommon::CemuhookUDP::CreateMessage(
+ InputCommon::CemuhookUDP::SERVER_MAGIC, pad_data, 0);
+ std::memcpy(send_buffer.data(), &pad_message, PadDataSize);
+ socket.send_to(boost::asio::buffer(send_buffer, PadDataSize), sender_endpoint,
+ 0, error_code);
+
+ bool can_advance =
+ std::next(current_touch_position) != touch_movement_path.end();
+ if (can_advance) {
+ std::advance(current_touch_position, 1);
+ }
+ break;
+ }
+ case InputCommon::CemuhookUDP::Type::PortInfo:
+ case InputCommon::CemuhookUDP::Type::Version:
+ default:
+ break;
+ }
+ }
+ });
+ }
+
+private:
+ boost::asio::io_service io_service;
+ boost::asio::ip::udp::socket socket;
+ std::array<u8, InputCommon::CemuhookUDP::MAX_PACKET_SIZE> send_buffer;
+ std::array<u8, InputCommon::CemuhookUDP::MAX_PACKET_SIZE> receive_buffer;
+ bool is_running = false;
+ std::thread handler;
+};
+
+TEST_CASE("CalibrationConfigurationJob completed", "[input_common]") {
+ Common::Event complete_event;
+ FakeCemuhookServer server;
+ server.Run({{
+ .is_active = 1,
+ .x = 0,
+ .y = 0,
+ },
+ {
+ .is_active = 1,
+ .x = 200,
+ .y = 200,
+ }});
+
+ InputCommon::CemuhookUDP::CalibrationConfigurationJob::Status status{};
+ u16 min_x{};
+ u16 min_y{};
+ u16 max_x{};
+ u16 max_y{};
+ InputCommon::CemuhookUDP::CalibrationConfigurationJob job(
+ server.GetHost(), server.GetPort(),
+ [&status,
+ &complete_event](InputCommon::CemuhookUDP::CalibrationConfigurationJob::Status status_) {
+ status = status_;
+ if (status ==
+ InputCommon::CemuhookUDP::CalibrationConfigurationJob::Status::Completed) {
+ complete_event.Set();
+ }
+ },
+ [&](u16 min_x_, u16 min_y_, u16 max_x_, u16 max_y_) {
+ min_x = min_x_;
+ min_y = min_y_;
+ max_x = max_x_;
+ max_y = max_y_;
+ });
+
+ complete_event.WaitUntil(std::chrono::system_clock::now() + std::chrono::seconds(10));
+ REQUIRE(status == InputCommon::CemuhookUDP::CalibrationConfigurationJob::Status::Completed);
+ REQUIRE(min_x == 0);
+ REQUIRE(min_y == 0);
+ REQUIRE(max_x == 200);
+ REQUIRE(max_y == 200);
+}