summaryrefslogtreecommitdiff
path: root/src/input_common/udp
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common/udp')
-rw-r--r--src/input_common/udp/client.cpp140
-rw-r--r--src/input_common/udp/client.h2
-rw-r--r--src/input_common/udp/protocol.h32
-rw-r--r--src/input_common/udp/udp.cpp18
4 files changed, 116 insertions, 76 deletions
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp
index da5227058..befa4c86d 100644
--- a/src/input_common/udp/client.cpp
+++ b/src/input_common/udp/client.cpp
@@ -59,7 +59,8 @@ public:
59 void StartReceive() { 59 void StartReceive() {
60 socket.async_receive_from( 60 socket.async_receive_from(
61 boost::asio::buffer(receive_buffer), receive_endpoint, 61 boost::asio::buffer(receive_buffer), receive_endpoint,
62 [this](const boost::system::error_code& error, std::size_t bytes_transferred) { 62 [this](const boost::system::error_code& error, std::size_t bytes_transferred)
63 {
63 HandleReceive(error, bytes_transferred); 64 HandleReceive(error, bytes_transferred);
64 }); 65 });
65 } 66 }
@@ -211,21 +212,27 @@ void Client::StartCommunication(const std::string& host, u16 port, u8 pad_index,
211void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 client_id, 212void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 client_id,
212 std::function<void()> success_callback, 213 std::function<void()> success_callback,
213 std::function<void()> failure_callback) { 214 std::function<void()> failure_callback) {
214 std::thread([=] { 215 std::thread([=]
215 Common::Event success_event; 216 {
216 SocketCallback callback{[](Response::Version version) {}, [](Response::PortInfo info) {}, 217 Common::Event success_event;
217 [&](Response::PadData data) { success_event.Set(); }}; 218 SocketCallback callback{[](Response::Version version)
218 Socket socket{host, port, pad_index, client_id, std::move(callback)}; 219 {
219 std::thread worker_thread{SocketLoop, &socket}; 220 },
220 bool result = success_event.WaitFor(std::chrono::seconds(8)); 221 [](Response::PortInfo info)
221 socket.Stop(); 222 {
222 worker_thread.join(); 223 },
223 if (result) { 224 [&](Response::PadData data) { success_event.Set(); }};
224 success_callback(); 225 Socket socket{host, port, pad_index, client_id, std::move(callback)};
225 } else { 226 std::thread worker_thread{SocketLoop, &socket};
226 failure_callback(); 227 bool result = success_event.WaitFor(std::chrono::seconds(8));
227 } 228 socket.Stop();
228 }) 229 worker_thread.join();
230 if (result) {
231 success_callback();
232 } else {
233 failure_callback();
234 }
235 })
229 .detach(); 236 .detach();
230} 237}
231 238
@@ -234,53 +241,60 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
234 std::function<void(Status)> status_callback, 241 std::function<void(Status)> status_callback,
235 std::function<void(u16, u16, u16, u16)> data_callback) { 242 std::function<void(u16, u16, u16, u16)> data_callback) {
236 243
237 std::thread([=] { 244 std::thread([=]
238 constexpr u16 CALIBRATION_THRESHOLD = 100; 245 {
239 246 constexpr u16 CALIBRATION_THRESHOLD = 100;
240 u16 min_x{UINT16_MAX}; 247
241 u16 min_y{UINT16_MAX}; 248 u16 min_x{UINT16_MAX};
242 u16 max_x{}; 249 u16 min_y{UINT16_MAX};
243 u16 max_y{}; 250 u16 max_x{};
244 251 u16 max_y{};
245 Status current_status{Status::Initialized}; 252
246 SocketCallback callback{[](Response::Version version) {}, [](Response::PortInfo info) {}, 253 Status current_status{Status::Initialized};
247 [&](Response::PadData data) { 254 SocketCallback callback{[](Response::Version version)
248 if (current_status == Status::Initialized) { 255 {
249 // Receiving data means the communication is ready now 256 },
250 current_status = Status::Ready; 257 [](Response::PortInfo info)
251 status_callback(current_status); 258 {
252 } 259 },
253 if (!data.touch_1.is_active) { 260 [&](Response::PadData data)
254 return; 261 {
255 } 262 if (current_status == Status::Initialized) {
256 LOG_DEBUG(Input, "Current touch: {} {}", data.touch_1.x, 263 // Receiving data means the communication is ready now
257 data.touch_1.y); 264 current_status = Status::Ready;
258 min_x = std::min(min_x, static_cast<u16>(data.touch_1.x)); 265 status_callback(current_status);
259 min_y = std::min(min_y, static_cast<u16>(data.touch_1.y)); 266 }
260 if (current_status == Status::Ready) { 267 if (!data.touch_1.is_active) {
261 // First touch - min data (min_x/min_y) 268 return;
262 current_status = Status::Stage1Completed; 269 }
263 status_callback(current_status); 270 LOG_DEBUG(Input, "Current touch: {} {}", data.touch_1.x,
264 } 271 data.touch_1.y);
265 if (data.touch_1.x - min_x > CALIBRATION_THRESHOLD && 272 min_x = std::min(min_x, static_cast<u16>(data.touch_1.x));
266 data.touch_1.y - min_y > CALIBRATION_THRESHOLD) { 273 min_y = std::min(min_y, static_cast<u16>(data.touch_1.y));
267 // Set the current position as max value and finishes 274 if (current_status == Status::Ready) {
268 // configuration 275 // First touch - min data (min_x/min_y)
269 max_x = data.touch_1.x; 276 current_status = Status::Stage1Completed;
270 max_y = data.touch_1.y; 277 status_callback(current_status);
271 current_status = Status::Completed; 278 }
272 data_callback(min_x, min_y, max_x, max_y); 279 if (data.touch_1.x - min_x > CALIBRATION_THRESHOLD &&
273 status_callback(current_status); 280 data.touch_1.y - min_y > CALIBRATION_THRESHOLD) {
274 281 // Set the current position as max value and finishes
275 complete_event.Set(); 282 // configuration
276 } 283 max_x = data.touch_1.x;
277 }}; 284 max_y = data.touch_1.y;
278 Socket socket{host, port, pad_index, client_id, std::move(callback)}; 285 current_status = Status::Completed;
279 std::thread worker_thread{SocketLoop, &socket}; 286 data_callback(min_x, min_y, max_x, max_y);
280 complete_event.Wait(); 287 status_callback(current_status);
281 socket.Stop(); 288
282 worker_thread.join(); 289 complete_event.Set();
283 }) 290 }
291 }};
292 Socket socket{host, port, pad_index, client_id, std::move(callback)};
293 std::thread worker_thread{SocketLoop, &socket};
294 complete_event.Wait();
295 socket.Stop();
296 worker_thread.join();
297 })
284 .detach(); 298 .detach();
285} 299}
286 300
diff --git a/src/input_common/udp/client.h b/src/input_common/udp/client.h
index b8c654755..b58e319b6 100644
--- a/src/input_common/udp/client.h
+++ b/src/input_common/udp/client.h
@@ -40,6 +40,7 @@ struct DeviceStatus {
40 u16 max_x{}; 40 u16 max_x{};
41 u16 max_y{}; 41 u16 max_y{};
42 }; 42 };
43
43 std::optional<CalibrationData> touch_calibration; 44 std::optional<CalibrationData> touch_calibration;
44}; 45};
45 46
@@ -72,6 +73,7 @@ public:
72 Stage1Completed, 73 Stage1Completed,
73 Completed, 74 Completed,
74 }; 75 };
76
75 /** 77 /**
76 * Constructs and starts the job with the specified parameter. 78 * Constructs and starts the job with the specified parameter.
77 * 79 *
diff --git a/src/input_common/udp/protocol.h b/src/input_common/udp/protocol.h
index 3ba4d1fc8..2b31846db 100644
--- a/src/input_common/udp/protocol.h
+++ b/src/input_common/udp/protocol.h
@@ -35,6 +35,7 @@ struct Header {
35 ///> the data 35 ///> the data
36 Type type{}; 36 Type type{};
37}; 37};
38
38static_assert(sizeof(Header) == 20, "UDP Message Header struct has wrong size"); 39static_assert(sizeof(Header) == 20, "UDP Message Header struct has wrong size");
39static_assert(std::is_trivially_copyable_v<Header>, "UDP Message Header is not trivially copyable"); 40static_assert(std::is_trivially_copyable_v<Header>, "UDP Message Header is not trivially copyable");
40 41
@@ -54,7 +55,9 @@ constexpr Type GetMessageType();
54 55
55namespace Request { 56namespace Request {
56 57
57struct Version {}; 58struct Version {
59};
60
58/** 61/**
59 * Requests the server to send information about what controllers are plugged into the ports 62 * Requests the server to send information about what controllers are plugged into the ports
60 * In citra's case, we only have one controller, so for simplicity's sake, we can just send a 63 * In citra's case, we only have one controller, so for simplicity's sake, we can just send a
@@ -62,12 +65,14 @@ struct Version {};
62 * nice to make this configurable 65 * nice to make this configurable
63 */ 66 */
64constexpr u32 MAX_PORTS = 4; 67constexpr u32 MAX_PORTS = 4;
68
65struct PortInfo { 69struct PortInfo {
66 u32_le pad_count{}; ///> Number of ports to request data for 70 u32_le pad_count{}; ///> Number of ports to request data for
67 std::array<u8, MAX_PORTS> port; 71 std::array<u8, MAX_PORTS> port;
68}; 72};
73
69static_assert(std::is_trivially_copyable_v<PortInfo>, 74static_assert(std::is_trivially_copyable_v<PortInfo>,
70 "UDP Request PortInfo is not trivially copyable"); 75 "UDP Request PortInfo is not trivially copyable");
71 76
72/** 77/**
73 * Request the latest pad information from the server. If the server hasn't received this message 78 * Request the latest pad information from the server. If the server hasn't received this message
@@ -80,6 +85,7 @@ struct PadData {
80 Id, 85 Id,
81 Mac, 86 Mac,
82 }; 87 };
88
83 /// Determines which method will be used as a look up for the controller 89 /// Determines which method will be used as a look up for the controller
84 Flags flags{}; 90 Flags flags{};
85 /// Index of the port of the controller to retrieve data about 91 /// Index of the port of the controller to retrieve data about
@@ -87,9 +93,10 @@ struct PadData {
87 /// Mac address of the controller to retrieve data about 93 /// Mac address of the controller to retrieve data about
88 MacAddress mac; 94 MacAddress mac;
89}; 95};
96
90static_assert(sizeof(PadData) == 8, "UDP Request PadData struct has wrong size"); 97static_assert(sizeof(PadData) == 8, "UDP Request PadData struct has wrong size");
91static_assert(std::is_trivially_copyable_v<PadData>, 98static_assert(std::is_trivially_copyable_v<PadData>,
92 "UDP Request PadData is not trivially copyable"); 99 "UDP Request PadData is not trivially copyable");
93 100
94/** 101/**
95 * Creates a message with the proper header data that can be sent to the server. 102 * Creates a message with the proper header data that can be sent to the server.
@@ -114,9 +121,10 @@ namespace Response {
114struct Version { 121struct Version {
115 u16_le version{}; 122 u16_le version{};
116}; 123};
124
117static_assert(sizeof(Version) == 2, "UDP Response Version struct has wrong size"); 125static_assert(sizeof(Version) == 2, "UDP Response Version struct has wrong size");
118static_assert(std::is_trivially_copyable_v<Version>, 126static_assert(std::is_trivially_copyable_v<Version>,
119 "UDP Response Version is not trivially copyable"); 127 "UDP Response Version is not trivially copyable");
120 128
121struct PortInfo { 129struct PortInfo {
122 u8 id{}; 130 u8 id{};
@@ -127,9 +135,10 @@ struct PortInfo {
127 u8 battery{}; 135 u8 battery{};
128 u8 is_pad_active{}; 136 u8 is_pad_active{};
129}; 137};
138
130static_assert(sizeof(PortInfo) == 12, "UDP Response PortInfo struct has wrong size"); 139static_assert(sizeof(PortInfo) == 12, "UDP Response PortInfo struct has wrong size");
131static_assert(std::is_trivially_copyable_v<PortInfo>, 140static_assert(std::is_trivially_copyable_v<PortInfo>,
132 "UDP Response PortInfo is not trivially copyable"); 141 "UDP Response PortInfo is not trivially copyable");
133 142
134#pragma pack(push, 1) 143#pragma pack(push, 1)
135struct PadData { 144struct PadData {
@@ -206,16 +215,16 @@ struct PadData {
206 215
207static_assert(sizeof(PadData) == 80, "UDP Response PadData struct has wrong size "); 216static_assert(sizeof(PadData) == 80, "UDP Response PadData struct has wrong size ");
208static_assert(std::is_trivially_copyable_v<PadData>, 217static_assert(std::is_trivially_copyable_v<PadData>,
209 "UDP Response PadData is not trivially copyable"); 218 "UDP Response PadData is not trivially copyable");
210 219
211static_assert(sizeof(Message<PadData>) == MAX_PACKET_SIZE, 220static_assert(sizeof(Message<PadData>) == MAX_PACKET_SIZE,
212 "UDP MAX_PACKET_SIZE is no longer larger than Message<PadData>"); 221 "UDP MAX_PACKET_SIZE is no longer larger than Message<PadData>");
213 222
214static_assert(sizeof(PadData::AnalogButton) == 12, 223static_assert(sizeof(PadData::AnalogButton) == 12,
215 "UDP Response AnalogButton struct has wrong size "); 224 "UDP Response AnalogButton struct has wrong size ");
216static_assert(sizeof(PadData::TouchPad) == 6, "UDP Response TouchPad struct has wrong size "); 225static_assert(sizeof(PadData::TouchPad) == 6, "UDP Response TouchPad struct has wrong size ");
217static_assert(sizeof(PadData::Accelerometer) == 12, 226static_assert(sizeof(PadData::Accelerometer) == 12,
218 "UDP Response Accelerometer struct has wrong size "); 227 "UDP Response Accelerometer struct has wrong size ");
219static_assert(sizeof(PadData::Gyroscope) == 12, "UDP Response Gyroscope struct has wrong size "); 228static_assert(sizeof(PadData::Gyroscope) == 12, "UDP Response Gyroscope struct has wrong size ");
220 229
221/** 230/**
@@ -232,22 +241,27 @@ template <>
232constexpr Type GetMessageType<Request::Version>() { 241constexpr Type GetMessageType<Request::Version>() {
233 return Type::Version; 242 return Type::Version;
234} 243}
244
235template <> 245template <>
236constexpr Type GetMessageType<Request::PortInfo>() { 246constexpr Type GetMessageType<Request::PortInfo>() {
237 return Type::PortInfo; 247 return Type::PortInfo;
238} 248}
249
239template <> 250template <>
240constexpr Type GetMessageType<Request::PadData>() { 251constexpr Type GetMessageType<Request::PadData>() {
241 return Type::PadData; 252 return Type::PadData;
242} 253}
254
243template <> 255template <>
244constexpr Type GetMessageType<Response::Version>() { 256constexpr Type GetMessageType<Response::Version>() {
245 return Type::Version; 257 return Type::Version;
246} 258}
259
247template <> 260template <>
248constexpr Type GetMessageType<Response::PortInfo>() { 261constexpr Type GetMessageType<Response::PortInfo>() {
249 return Type::PortInfo; 262 return Type::PortInfo;
250} 263}
264
251template <> 265template <>
252constexpr Type GetMessageType<Response::PadData>() { 266constexpr Type GetMessageType<Response::PadData>() {
253 return Type::PadData; 267 return Type::PadData;
diff --git a/src/input_common/udp/udp.cpp b/src/input_common/udp/udp.cpp
index 8c6ef1394..343c3985e 100644
--- a/src/input_common/udp/udp.cpp
+++ b/src/input_common/udp/udp.cpp
@@ -16,7 +16,10 @@ namespace InputCommon::CemuhookUDP {
16 16
17class UDPTouchDevice final : public Input::TouchDevice { 17class UDPTouchDevice final : public Input::TouchDevice {
18public: 18public:
19 explicit UDPTouchDevice(std::shared_ptr<DeviceStatus> status_) : status(std::move(status_)) {} 19 explicit UDPTouchDevice(std::shared_ptr<DeviceStatus> status_)
20 : status(std::move(status_)) {
21 }
22
20 std::tuple<float, float, bool> GetStatus() const override { 23 std::tuple<float, float, bool> GetStatus() const override {
21 std::lock_guard guard(status->update_mutex); 24 std::lock_guard guard(status->update_mutex);
22 return status->touch_status; 25 return status->touch_status;
@@ -28,7 +31,10 @@ private:
28 31
29class UDPMotionDevice final : public Input::MotionDevice { 32class UDPMotionDevice final : public Input::MotionDevice {
30public: 33public:
31 explicit UDPMotionDevice(std::shared_ptr<DeviceStatus> status_) : status(std::move(status_)) {} 34 explicit UDPMotionDevice(std::shared_ptr<DeviceStatus> status_)
35 : status(std::move(status_)) {
36 }
37
32 std::tuple<Common::Vec3<float>, Common::Vec3<float>> GetStatus() const override { 38 std::tuple<Common::Vec3<float>, Common::Vec3<float>> GetStatus() const override {
33 std::lock_guard guard(status->update_mutex); 39 std::lock_guard guard(status->update_mutex);
34 return status->motion_status; 40 return status->motion_status;
@@ -40,7 +46,9 @@ private:
40 46
41class UDPTouchFactory final : public Input::Factory<Input::TouchDevice> { 47class UDPTouchFactory final : public Input::Factory<Input::TouchDevice> {
42public: 48public:
43 explicit UDPTouchFactory(std::shared_ptr<DeviceStatus> status_) : status(std::move(status_)) {} 49 explicit UDPTouchFactory(std::shared_ptr<DeviceStatus> status_)
50 : status(std::move(status_)) {
51 }
44 52
45 std::unique_ptr<Input::TouchDevice> Create(const Common::ParamPackage& params) override { 53 std::unique_ptr<Input::TouchDevice> Create(const Common::ParamPackage& params) override {
46 { 54 {
@@ -61,7 +69,9 @@ private:
61 69
62class UDPMotionFactory final : public Input::Factory<Input::MotionDevice> { 70class UDPMotionFactory final : public Input::Factory<Input::MotionDevice> {
63public: 71public:
64 explicit UDPMotionFactory(std::shared_ptr<DeviceStatus> status_) : status(std::move(status_)) {} 72 explicit UDPMotionFactory(std::shared_ptr<DeviceStatus> status_)
73 : status(std::move(status_)) {
74 }
65 75
66 std::unique_ptr<Input::MotionDevice> Create(const Common::ParamPackage& params) override { 76 std::unique_ptr<Input::MotionDevice> Create(const Common::ParamPackage& params) override {
67 return std::make_unique<UDPMotionDevice>(status); 77 return std::make_unique<UDPMotionDevice>(status);