diff options
| -rw-r--r-- | src/input_common/udp/client.cpp | 147 | ||||
| -rw-r--r-- | src/input_common/udp/client.h | 44 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_motion_touch.cpp | 9 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_motion_touch.h | 3 |
4 files changed, 101 insertions, 102 deletions
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp index df73f9ff7..e72df924b 100644 --- a/src/input_common/udp/client.cpp +++ b/src/input_common/udp/client.cpp | |||
| @@ -27,11 +27,9 @@ class Socket { | |||
| 27 | public: | 27 | public: |
| 28 | using clock = std::chrono::system_clock; | 28 | using clock = std::chrono::system_clock; |
| 29 | 29 | ||
| 30 | explicit Socket(const std::string& host, u16 port, std::size_t pad_index_, | 30 | explicit Socket(const std::string& host, u16 port, SocketCallback callback_) |
| 31 | SocketCallback callback_) | ||
| 32 | : callback(std::move(callback_)), timer(io_service), | 31 | : callback(std::move(callback_)), timer(io_service), |
| 33 | socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(GenerateRandomClientId()), | 32 | socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(GenerateRandomClientId()) { |
| 34 | pad_index(pad_index_) { | ||
| 35 | boost::system::error_code ec{}; | 33 | boost::system::error_code ec{}; |
| 36 | auto ipv4 = boost::asio::ip::make_address_v4(host, ec); | 34 | auto ipv4 = boost::asio::ip::make_address_v4(host, ec); |
| 37 | if (ec.value() != boost::system::errc::success) { | 35 | if (ec.value() != boost::system::errc::success) { |
| @@ -99,15 +97,15 @@ private: | |||
| 99 | void HandleSend(const boost::system::error_code&) { | 97 | void HandleSend(const boost::system::error_code&) { |
| 100 | boost::system::error_code _ignored{}; | 98 | boost::system::error_code _ignored{}; |
| 101 | // Send a request for getting port info for the pad | 99 | // Send a request for getting port info for the pad |
| 102 | const Request::PortInfo port_info{1, {static_cast<u8>(pad_index), 0, 0, 0}}; | 100 | const Request::PortInfo port_info{4, {0, 1, 2, 3}}; |
| 103 | const auto port_message = Request::Create(port_info, client_id); | 101 | const auto port_message = Request::Create(port_info, client_id); |
| 104 | std::memcpy(&send_buffer1, &port_message, PORT_INFO_SIZE); | 102 | std::memcpy(&send_buffer1, &port_message, PORT_INFO_SIZE); |
| 105 | socket.send_to(boost::asio::buffer(send_buffer1), send_endpoint, {}, _ignored); | 103 | socket.send_to(boost::asio::buffer(send_buffer1), send_endpoint, {}, _ignored); |
| 106 | 104 | ||
| 107 | // Send a request for getting pad data for the pad | 105 | // Send a request for getting pad data for the pad |
| 108 | const Request::PadData pad_data{ | 106 | const Request::PadData pad_data{ |
| 109 | Request::PadData::Flags::Id, | 107 | Request::PadData::Flags::AllPorts, |
| 110 | static_cast<u8>(pad_index), | 108 | 0, |
| 111 | EMPTY_MAC_ADDRESS, | 109 | EMPTY_MAC_ADDRESS, |
| 112 | }; | 110 | }; |
| 113 | const auto pad_message = Request::Create(pad_data, client_id); | 111 | const auto pad_message = Request::Create(pad_data, client_id); |
| @@ -122,7 +120,6 @@ private: | |||
| 122 | udp::socket socket; | 120 | udp::socket socket; |
| 123 | 121 | ||
| 124 | const u32 client_id; | 122 | const u32 client_id; |
| 125 | std::size_t pad_index{}; | ||
| 126 | 123 | ||
| 127 | static constexpr std::size_t PORT_INFO_SIZE = sizeof(Message<Request::PortInfo>); | 124 | static constexpr std::size_t PORT_INFO_SIZE = sizeof(Message<Request::PortInfo>); |
| 128 | static constexpr std::size_t PAD_DATA_SIZE = sizeof(Message<Request::PadData>); | 125 | static constexpr std::size_t PAD_DATA_SIZE = sizeof(Message<Request::PadData>); |
| @@ -150,34 +147,32 @@ Client::~Client() { | |||
| 150 | Reset(); | 147 | Reset(); |
| 151 | } | 148 | } |
| 152 | 149 | ||
| 153 | Client::ClientData::ClientData() = default; | 150 | Client::ClientConnection::ClientConnection() = default; |
| 154 | 151 | ||
| 155 | Client::ClientData::~ClientData() = default; | 152 | Client::ClientConnection::~ClientConnection() = default; |
| 156 | 153 | ||
| 157 | std::vector<Common::ParamPackage> Client::GetInputDevices() const { | 154 | std::vector<Common::ParamPackage> Client::GetInputDevices() const { |
| 158 | std::vector<Common::ParamPackage> devices; | 155 | std::vector<Common::ParamPackage> devices; |
| 159 | for (std::size_t client = 0; client < clients.size(); client++) { | 156 | for (std::size_t pad = 0; pad < pads.size(); pad++) { |
| 160 | if (!DeviceConnected(client)) { | 157 | if (!DeviceConnected(pad)) { |
| 161 | continue; | 158 | continue; |
| 162 | } | 159 | } |
| 163 | std::string name = fmt::format("UDP Controller {}", client); | 160 | std::string name = fmt::format("UDP Controller {}", pad); |
| 164 | devices.emplace_back(Common::ParamPackage{ | 161 | devices.emplace_back(Common::ParamPackage{ |
| 165 | {"class", "cemuhookudp"}, | 162 | {"class", "cemuhookudp"}, |
| 166 | {"display", std::move(name)}, | 163 | {"display", std::move(name)}, |
| 167 | {"port", std::to_string(client)}, | 164 | {"port", std::to_string(pad)}, |
| 168 | }); | 165 | }); |
| 169 | } | 166 | } |
| 170 | return devices; | 167 | return devices; |
| 171 | } | 168 | } |
| 172 | 169 | ||
| 173 | bool Client::DeviceConnected(std::size_t client) const { | 170 | bool Client::DeviceConnected(std::size_t pad) const { |
| 174 | // Use last timestamp to detect if the socket has stopped sending data | 171 | // Use last timestamp to detect if the socket has stopped sending data |
| 175 | const auto now = std::chrono::steady_clock::now(); | 172 | const auto now = std::chrono::steady_clock::now(); |
| 176 | const auto time_difference = | 173 | const auto time_difference = static_cast<u64>( |
| 177 | static_cast<u64>(std::chrono::duration_cast<std::chrono::milliseconds>( | 174 | std::chrono::duration_cast<std::chrono::milliseconds>(now - pads[pad].last_update).count()); |
| 178 | now - clients[client].last_motion_update) | 175 | return time_difference < 1000 && pads[pad].connected; |
| 179 | .count()); | ||
| 180 | return time_difference < 1000 && clients[client].active == 1; | ||
| 181 | } | 176 | } |
| 182 | 177 | ||
| 183 | void Client::ReloadSockets() { | 178 | void Client::ReloadSockets() { |
| @@ -202,25 +197,21 @@ void Client::ReloadSockets() { | |||
| 202 | continue; | 197 | continue; |
| 203 | } | 198 | } |
| 204 | 199 | ||
| 205 | for (std::size_t pad = 0; pad < 4; ++pad) { | 200 | const std::size_t client_number = GetClientNumber(udp_input_address, udp_input_port); |
| 206 | const std::size_t client_number = | 201 | if (client_number != MAX_UDP_CLIENTS) { |
| 207 | GetClientNumber(udp_input_address, udp_input_port, pad); | 202 | LOG_ERROR(Input, "Duplicated UDP servers found"); |
| 208 | if (client_number != MAX_UDP_CLIENTS) { | 203 | continue; |
| 209 | LOG_ERROR(Input, "Duplicated UDP servers found"); | ||
| 210 | continue; | ||
| 211 | } | ||
| 212 | StartCommunication(client++, udp_input_address, udp_input_port, pad); | ||
| 213 | } | 204 | } |
| 205 | StartCommunication(client++, udp_input_address, udp_input_port); | ||
| 214 | } | 206 | } |
| 215 | } | 207 | } |
| 216 | 208 | ||
| 217 | std::size_t Client::GetClientNumber(std::string_view host, u16 port, std::size_t pad) const { | 209 | std::size_t Client::GetClientNumber(std::string_view host, u16 port) const { |
| 218 | for (std::size_t client = 0; client < clients.size(); client++) { | 210 | for (std::size_t client = 0; client < clients.size(); client++) { |
| 219 | if (clients[client].active == -1) { | 211 | if (clients[client].active == -1) { |
| 220 | continue; | 212 | continue; |
| 221 | } | 213 | } |
| 222 | if (clients[client].host == host && clients[client].port == port && | 214 | if (clients[client].host == host && clients[client].port == port) { |
| 223 | clients[client].pad_index == pad) { | ||
| 224 | return client; | 215 | return client; |
| 225 | } | 216 | } |
| 226 | } | 217 | } |
| @@ -236,69 +227,75 @@ void Client::OnPortInfo([[maybe_unused]] Response::PortInfo data) { | |||
| 236 | } | 227 | } |
| 237 | 228 | ||
| 238 | void Client::OnPadData(Response::PadData data, std::size_t client) { | 229 | void Client::OnPadData(Response::PadData data, std::size_t client) { |
| 239 | // Accept packets only for the correct pad | 230 | const std::size_t pad_index = (client * PADS_PER_CLIENT) + data.info.id; |
| 240 | if (static_cast<u8>(clients[client].pad_index) != data.info.id) { | 231 | |
| 232 | if (pad_index >= pads.size()) { | ||
| 233 | LOG_ERROR(Input, "Invalid pad id {}", data.info.id); | ||
| 241 | return; | 234 | return; |
| 242 | } | 235 | } |
| 243 | 236 | ||
| 244 | LOG_TRACE(Input, "PadData packet received"); | 237 | LOG_TRACE(Input, "PadData packet received"); |
| 245 | if (data.packet_counter == clients[client].packet_sequence) { | 238 | if (data.packet_counter == pads[pad_index].packet_sequence) { |
| 246 | LOG_WARNING( | 239 | LOG_WARNING( |
| 247 | Input, | 240 | Input, |
| 248 | "PadData packet dropped because its stale info. Current count: {} Packet count: {}", | 241 | "PadData packet dropped because its stale info. Current count: {} Packet count: {}", |
| 249 | clients[client].packet_sequence, data.packet_counter); | 242 | pads[pad_index].packet_sequence, data.packet_counter); |
| 243 | pads[pad_index].connected = false; | ||
| 250 | return; | 244 | return; |
| 251 | } | 245 | } |
| 252 | clients[client].active = static_cast<s8>(data.info.is_pad_active); | 246 | |
| 253 | clients[client].packet_sequence = data.packet_counter; | 247 | clients[client].active = 1; |
| 248 | pads[pad_index].connected = true; | ||
| 249 | pads[pad_index].packet_sequence = data.packet_counter; | ||
| 250 | |||
| 254 | const auto now = std::chrono::steady_clock::now(); | 251 | const auto now = std::chrono::steady_clock::now(); |
| 255 | const auto time_difference = | 252 | const auto time_difference = static_cast<u64>( |
| 256 | static_cast<u64>(std::chrono::duration_cast<std::chrono::microseconds>( | 253 | std::chrono::duration_cast<std::chrono::microseconds>(now - pads[pad_index].last_update) |
| 257 | now - clients[client].last_motion_update) | 254 | .count()); |
| 258 | .count()); | 255 | pads[pad_index].last_update = now; |
| 259 | clients[client].last_motion_update = now; | 256 | |
| 260 | const Common::Vec3f raw_gyroscope = {data.gyro.pitch, data.gyro.roll, -data.gyro.yaw}; | 257 | const Common::Vec3f raw_gyroscope = {data.gyro.pitch, data.gyro.roll, -data.gyro.yaw}; |
| 261 | clients[client].motion.SetAcceleration({data.accel.x, -data.accel.z, data.accel.y}); | 258 | pads[pad_index].motion.SetAcceleration({data.accel.x, -data.accel.z, data.accel.y}); |
| 262 | // Gyroscope values are not it the correct scale from better joy. | 259 | // Gyroscope values are not it the correct scale from better joy. |
| 263 | // Dividing by 312 allows us to make one full turn = 1 turn | 260 | // Dividing by 312 allows us to make one full turn = 1 turn |
| 264 | // This must be a configurable valued called sensitivity | 261 | // This must be a configurable valued called sensitivity |
| 265 | clients[client].motion.SetGyroscope(raw_gyroscope / 312.0f); | 262 | pads[pad_index].motion.SetGyroscope(raw_gyroscope / 312.0f); |
| 266 | clients[client].motion.UpdateRotation(time_difference); | 263 | pads[pad_index].motion.UpdateRotation(time_difference); |
| 267 | clients[client].motion.UpdateOrientation(time_difference); | 264 | pads[pad_index].motion.UpdateOrientation(time_difference); |
| 268 | 265 | ||
| 269 | { | 266 | { |
| 270 | std::lock_guard guard(clients[client].status.update_mutex); | 267 | std::lock_guard guard(pads[pad_index].status.update_mutex); |
| 271 | clients[client].status.motion_status = clients[client].motion.GetMotion(); | 268 | pads[pad_index].status.motion_status = pads[pad_index].motion.GetMotion(); |
| 272 | 269 | ||
| 273 | for (std::size_t id = 0; id < data.touch.size(); ++id) { | 270 | for (std::size_t id = 0; id < data.touch.size(); ++id) { |
| 274 | UpdateTouchInput(data.touch[id], client, id); | 271 | UpdateTouchInput(data.touch[id], client, id); |
| 275 | } | 272 | } |
| 276 | 273 | ||
| 277 | if (configuring) { | 274 | if (configuring) { |
| 278 | const Common::Vec3f gyroscope = clients[client].motion.GetGyroscope(); | 275 | const Common::Vec3f gyroscope = pads[pad_index].motion.GetGyroscope(); |
| 279 | const Common::Vec3f accelerometer = clients[client].motion.GetAcceleration(); | 276 | const Common::Vec3f accelerometer = pads[pad_index].motion.GetAcceleration(); |
| 280 | UpdateYuzuSettings(client, accelerometer, gyroscope); | 277 | UpdateYuzuSettings(client, data.info.id, accelerometer, gyroscope); |
| 281 | } | 278 | } |
| 282 | } | 279 | } |
| 283 | } | 280 | } |
| 284 | 281 | ||
| 285 | void Client::StartCommunication(std::size_t client, const std::string& host, u16 port, | 282 | void Client::StartCommunication(std::size_t client, const std::string& host, u16 port) { |
| 286 | std::size_t pad_index) { | ||
| 287 | SocketCallback callback{[this](Response::Version version) { OnVersion(version); }, | 283 | SocketCallback callback{[this](Response::Version version) { OnVersion(version); }, |
| 288 | [this](Response::PortInfo info) { OnPortInfo(info); }, | 284 | [this](Response::PortInfo info) { OnPortInfo(info); }, |
| 289 | [this, client](Response::PadData data) { OnPadData(data, client); }}; | 285 | [this, client](Response::PadData data) { OnPadData(data, client); }}; |
| 290 | LOG_INFO(Input, "Starting communication with UDP input server on {}:{}:{}", host, port, | 286 | LOG_INFO(Input, "Starting communication with UDP input server on {}:{}", host, port); |
| 291 | pad_index); | ||
| 292 | clients[client].host = host; | 287 | clients[client].host = host; |
| 293 | clients[client].port = port; | 288 | clients[client].port = port; |
| 294 | clients[client].pad_index = pad_index; | ||
| 295 | clients[client].active = 0; | 289 | clients[client].active = 0; |
| 296 | clients[client].socket = std::make_unique<Socket>(host, port, pad_index, callback); | 290 | clients[client].socket = std::make_unique<Socket>(host, port, callback); |
| 297 | clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()}; | 291 | clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()}; |
| 292 | |||
| 298 | // Set motion parameters | 293 | // Set motion parameters |
| 299 | // SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode | 294 | // SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode |
| 300 | // Real HW values are unknown, 0.0001 is an approximate to Standard | 295 | // Real HW values are unknown, 0.0001 is an approximate to Standard |
| 301 | clients[client].motion.SetGyroThreshold(0.0001f); | 296 | for (std::size_t pad = 0; pad < PADS_PER_CLIENT; pad++) { |
| 297 | pads[client * PADS_PER_CLIENT + pad].motion.SetGyroThreshold(0.0001f); | ||
| 298 | } | ||
| 302 | } | 299 | } |
| 303 | 300 | ||
| 304 | void Client::Reset() { | 301 | void Client::Reset() { |
| @@ -311,8 +308,8 @@ void Client::Reset() { | |||
| 311 | } | 308 | } |
| 312 | } | 309 | } |
| 313 | 310 | ||
| 314 | void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc, | 311 | void Client::UpdateYuzuSettings(std::size_t client, std::size_t pad_index, |
| 315 | const Common::Vec3<float>& gyro) { | 312 | const Common::Vec3<float>& acc, const Common::Vec3<float>& gyro) { |
| 316 | if (gyro.Length() > 0.2f) { | 313 | if (gyro.Length() > 0.2f) { |
| 317 | LOG_DEBUG(Input, "UDP Controller {}: gyro=({}, {}, {}), accel=({}, {}, {})", client, | 314 | LOG_DEBUG(Input, "UDP Controller {}: gyro=({}, {}, {}), accel=({}, {}, {})", client, |
| 318 | gyro[0], gyro[1], gyro[2], acc[0], acc[1], acc[2]); | 315 | gyro[0], gyro[1], gyro[2], acc[0], acc[1], acc[2]); |
| @@ -320,7 +317,7 @@ void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& a | |||
| 320 | UDPPadStatus pad{ | 317 | UDPPadStatus pad{ |
| 321 | .host = clients[client].host, | 318 | .host = clients[client].host, |
| 322 | .port = clients[client].port, | 319 | .port = clients[client].port, |
| 323 | .pad_index = clients[client].pad_index, | 320 | .pad_index = pad_index, |
| 324 | }; | 321 | }; |
| 325 | for (std::size_t i = 0; i < 3; ++i) { | 322 | for (std::size_t i = 0; i < 3; ++i) { |
| 326 | if (gyro[i] > 5.0f || gyro[i] < -5.0f) { | 323 | if (gyro[i] > 5.0f || gyro[i] < -5.0f) { |
| @@ -391,19 +388,19 @@ void Client::EndConfiguration() { | |||
| 391 | } | 388 | } |
| 392 | 389 | ||
| 393 | DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) { | 390 | DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) { |
| 394 | const std::size_t client_number = GetClientNumber(host, port, pad); | 391 | const std::size_t client_number = GetClientNumber(host, port); |
| 395 | if (client_number == MAX_UDP_CLIENTS) { | 392 | if (client_number == MAX_UDP_CLIENTS || pad >= PADS_PER_CLIENT) { |
| 396 | return clients[0].status; | 393 | return pads[0].status; |
| 397 | } | 394 | } |
| 398 | return clients[client_number].status; | 395 | return pads[(client_number * PADS_PER_CLIENT) + pad].status; |
| 399 | } | 396 | } |
| 400 | 397 | ||
| 401 | const DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) const { | 398 | const DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) const { |
| 402 | const std::size_t client_number = GetClientNumber(host, port, pad); | 399 | const std::size_t client_number = GetClientNumber(host, port); |
| 403 | if (client_number == MAX_UDP_CLIENTS) { | 400 | if (client_number == MAX_UDP_CLIENTS || pad >= PADS_PER_CLIENT) { |
| 404 | return clients[0].status; | 401 | return pads[0].status; |
| 405 | } | 402 | } |
| 406 | return clients[client_number].status; | 403 | return pads[(client_number * PADS_PER_CLIENT) + pad].status; |
| 407 | } | 404 | } |
| 408 | 405 | ||
| 409 | Input::TouchStatus& Client::GetTouchState() { | 406 | Input::TouchStatus& Client::GetTouchState() { |
| @@ -422,7 +419,7 @@ const Common::SPSCQueue<UDPPadStatus>& Client::GetPadQueue() const { | |||
| 422 | return pad_queue; | 419 | return pad_queue; |
| 423 | } | 420 | } |
| 424 | 421 | ||
| 425 | void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, | 422 | void TestCommunication(const std::string& host, u16 port, |
| 426 | const std::function<void()>& success_callback, | 423 | const std::function<void()>& success_callback, |
| 427 | const std::function<void()>& failure_callback) { | 424 | const std::function<void()>& failure_callback) { |
| 428 | std::thread([=] { | 425 | std::thread([=] { |
| @@ -432,9 +429,10 @@ void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, | |||
| 432 | .port_info = [](Response::PortInfo) {}, | 429 | .port_info = [](Response::PortInfo) {}, |
| 433 | .pad_data = [&](Response::PadData) { success_event.Set(); }, | 430 | .pad_data = [&](Response::PadData) { success_event.Set(); }, |
| 434 | }; | 431 | }; |
| 435 | Socket socket{host, port, pad_index, std::move(callback)}; | 432 | Socket socket{host, port, std::move(callback)}; |
| 436 | std::thread worker_thread{SocketLoop, &socket}; | 433 | std::thread worker_thread{SocketLoop, &socket}; |
| 437 | const bool result = success_event.WaitFor(std::chrono::seconds(5)); | 434 | const bool result = |
| 435 | success_event.WaitUntil(std::chrono::steady_clock::now() + std::chrono::seconds(10)); | ||
| 438 | socket.Stop(); | 436 | socket.Stop(); |
| 439 | worker_thread.join(); | 437 | worker_thread.join(); |
| 440 | if (result) { | 438 | if (result) { |
| @@ -446,8 +444,7 @@ void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, | |||
| 446 | } | 444 | } |
| 447 | 445 | ||
| 448 | CalibrationConfigurationJob::CalibrationConfigurationJob( | 446 | CalibrationConfigurationJob::CalibrationConfigurationJob( |
| 449 | const std::string& host, u16 port, std::size_t pad_index, | 447 | const std::string& host, u16 port, std::function<void(Status)> status_callback, |
| 450 | std::function<void(Status)> status_callback, | ||
| 451 | std::function<void(u16, u16, u16, u16)> data_callback) { | 448 | std::function<void(u16, u16, u16, u16)> data_callback) { |
| 452 | 449 | ||
| 453 | std::thread([=, this] { | 450 | std::thread([=, this] { |
| @@ -491,7 +488,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob( | |||
| 491 | complete_event.Set(); | 488 | complete_event.Set(); |
| 492 | } | 489 | } |
| 493 | }}; | 490 | }}; |
| 494 | Socket socket{host, port, pad_index, std::move(callback)}; | 491 | Socket socket{host, port, std::move(callback)}; |
| 495 | std::thread worker_thread{SocketLoop, &socket}; | 492 | std::thread worker_thread{SocketLoop, &socket}; |
| 496 | complete_event.Wait(); | 493 | complete_event.Wait(); |
| 497 | socket.Stop(); | 494 | socket.Stop(); |
diff --git a/src/input_common/udp/client.h b/src/input_common/udp/client.h index e9e438e88..a11ea3068 100644 --- a/src/input_common/udp/client.h +++ b/src/input_common/udp/client.h | |||
| @@ -84,7 +84,7 @@ public: | |||
| 84 | 84 | ||
| 85 | std::vector<Common::ParamPackage> GetInputDevices() const; | 85 | std::vector<Common::ParamPackage> GetInputDevices() const; |
| 86 | 86 | ||
| 87 | bool DeviceConnected(std::size_t client) const; | 87 | bool DeviceConnected(std::size_t pad) const; |
| 88 | void ReloadSockets(); | 88 | void ReloadSockets(); |
| 89 | 89 | ||
| 90 | Common::SPSCQueue<UDPPadStatus>& GetPadQueue(); | 90 | Common::SPSCQueue<UDPPadStatus>& GetPadQueue(); |
| @@ -97,38 +97,40 @@ public: | |||
| 97 | const Input::TouchStatus& GetTouchState() const; | 97 | const Input::TouchStatus& GetTouchState() const; |
| 98 | 98 | ||
| 99 | private: | 99 | private: |
| 100 | struct ClientData { | 100 | struct PadData { |
| 101 | ClientData(); | ||
| 102 | ~ClientData(); | ||
| 103 | |||
| 104 | std::string host{"127.0.0.1"}; | ||
| 105 | u16 port{26760}; | ||
| 106 | std::size_t pad_index{}; | 101 | std::size_t pad_index{}; |
| 107 | std::unique_ptr<Socket> socket; | 102 | bool connected{}; |
| 108 | DeviceStatus status; | 103 | DeviceStatus status; |
| 109 | std::thread thread; | ||
| 110 | u64 packet_sequence{}; | 104 | u64 packet_sequence{}; |
| 111 | s8 active{-1}; | ||
| 112 | 105 | ||
| 113 | // Realtime values | 106 | // Realtime values |
| 114 | // motion is initalized with PID values for drift correction on joycons | 107 | // motion is initalized with PID values for drift correction on joycons |
| 115 | InputCommon::MotionInput motion{0.3f, 0.005f, 0.0f}; | 108 | InputCommon::MotionInput motion{0.3f, 0.005f, 0.0f}; |
| 116 | std::chrono::time_point<std::chrono::steady_clock> last_motion_update; | 109 | std::chrono::time_point<std::chrono::steady_clock> last_update; |
| 110 | }; | ||
| 111 | |||
| 112 | struct ClientConnection { | ||
| 113 | ClientConnection(); | ||
| 114 | ~ClientConnection(); | ||
| 115 | std::string host{"127.0.0.1"}; | ||
| 116 | u16 port{26760}; | ||
| 117 | s8 active{-1}; | ||
| 118 | std::unique_ptr<Socket> socket; | ||
| 119 | std::thread thread; | ||
| 117 | }; | 120 | }; |
| 118 | 121 | ||
| 119 | // For shutting down, clear all data, join all threads, release usb | 122 | // For shutting down, clear all data, join all threads, release usb |
| 120 | void Reset(); | 123 | void Reset(); |
| 121 | 124 | ||
| 122 | // Translates configuration to client number | 125 | // Translates configuration to client number |
| 123 | std::size_t GetClientNumber(std::string_view host, u16 port, std::size_t pad) const; | 126 | std::size_t GetClientNumber(std::string_view host, u16 port) const; |
| 124 | 127 | ||
| 125 | void OnVersion(Response::Version); | 128 | void OnVersion(Response::Version); |
| 126 | void OnPortInfo(Response::PortInfo); | 129 | void OnPortInfo(Response::PortInfo); |
| 127 | void OnPadData(Response::PadData, std::size_t client); | 130 | void OnPadData(Response::PadData, std::size_t client); |
| 128 | void StartCommunication(std::size_t client, const std::string& host, u16 port, | 131 | void StartCommunication(std::size_t client, const std::string& host, u16 port); |
| 129 | std::size_t pad_index); | 132 | void UpdateYuzuSettings(std::size_t client, std::size_t pad_index, |
| 130 | void UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc, | 133 | const Common::Vec3<float>& acc, const Common::Vec3<float>& gyro); |
| 131 | const Common::Vec3<float>& gyro); | ||
| 132 | 134 | ||
| 133 | // Returns an unused finger id, if there is no fingers available std::nullopt will be | 135 | // Returns an unused finger id, if there is no fingers available std::nullopt will be |
| 134 | // returned | 136 | // returned |
| @@ -140,10 +142,12 @@ private: | |||
| 140 | bool configuring = false; | 142 | bool configuring = false; |
| 141 | 143 | ||
| 142 | // Allocate clients for 8 udp servers | 144 | // Allocate clients for 8 udp servers |
| 143 | static constexpr std::size_t MAX_UDP_CLIENTS = 4 * 8; | 145 | static constexpr std::size_t MAX_UDP_CLIENTS = 8; |
| 146 | static constexpr std::size_t PADS_PER_CLIENT = 4; | ||
| 144 | // Each client can have up 2 touch inputs | 147 | // Each client can have up 2 touch inputs |
| 145 | static constexpr std::size_t MAX_TOUCH_FINGERS = MAX_UDP_CLIENTS * 2; | 148 | static constexpr std::size_t MAX_TOUCH_FINGERS = MAX_UDP_CLIENTS * 2; |
| 146 | std::array<ClientData, MAX_UDP_CLIENTS> clients{}; | 149 | std::array<PadData, MAX_UDP_CLIENTS * PADS_PER_CLIENT> pads{}; |
| 150 | std::array<ClientConnection, MAX_UDP_CLIENTS> clients{}; | ||
| 147 | Common::SPSCQueue<UDPPadStatus> pad_queue{}; | 151 | Common::SPSCQueue<UDPPadStatus> pad_queue{}; |
| 148 | Input::TouchStatus touch_status{}; | 152 | Input::TouchStatus touch_status{}; |
| 149 | std::array<std::size_t, MAX_TOUCH_FINGERS> finger_id{}; | 153 | std::array<std::size_t, MAX_TOUCH_FINGERS> finger_id{}; |
| @@ -164,7 +168,7 @@ public: | |||
| 164 | * @param status_callback Callback for job status updates | 168 | * @param status_callback Callback for job status updates |
| 165 | * @param data_callback Called when calibration data is ready | 169 | * @param data_callback Called when calibration data is ready |
| 166 | */ | 170 | */ |
| 167 | explicit CalibrationConfigurationJob(const std::string& host, u16 port, std::size_t pad_index, | 171 | explicit CalibrationConfigurationJob(const std::string& host, u16 port, |
| 168 | std::function<void(Status)> status_callback, | 172 | std::function<void(Status)> status_callback, |
| 169 | std::function<void(u16, u16, u16, u16)> data_callback); | 173 | std::function<void(u16, u16, u16, u16)> data_callback); |
| 170 | ~CalibrationConfigurationJob(); | 174 | ~CalibrationConfigurationJob(); |
| @@ -174,7 +178,7 @@ private: | |||
| 174 | Common::Event complete_event; | 178 | Common::Event complete_event; |
| 175 | }; | 179 | }; |
| 176 | 180 | ||
| 177 | void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, | 181 | void TestCommunication(const std::string& host, u16 port, |
| 178 | const std::function<void()>& success_callback, | 182 | const std::function<void()>& success_callback, |
| 179 | const std::function<void()>& failure_callback); | 183 | const std::function<void()>& failure_callback); |
| 180 | 184 | ||
diff --git a/src/yuzu/configuration/configure_motion_touch.cpp b/src/yuzu/configuration/configure_motion_touch.cpp index 52fdf7265..083d1ea43 100644 --- a/src/yuzu/configuration/configure_motion_touch.cpp +++ b/src/yuzu/configuration/configure_motion_touch.cpp | |||
| @@ -23,8 +23,7 @@ | |||
| 23 | #include "yuzu/configuration/configure_touch_from_button.h" | 23 | #include "yuzu/configuration/configure_touch_from_button.h" |
| 24 | 24 | ||
| 25 | CalibrationConfigurationDialog::CalibrationConfigurationDialog(QWidget* parent, | 25 | CalibrationConfigurationDialog::CalibrationConfigurationDialog(QWidget* parent, |
| 26 | const std::string& host, u16 port, | 26 | const std::string& host, u16 port) |
| 27 | u8 pad_index) | ||
| 28 | : QDialog(parent) { | 27 | : QDialog(parent) { |
| 29 | layout = new QVBoxLayout; | 28 | layout = new QVBoxLayout; |
| 30 | status_label = new QLabel(tr("Communicating with the server...")); | 29 | status_label = new QLabel(tr("Communicating with the server...")); |
| @@ -41,7 +40,7 @@ CalibrationConfigurationDialog::CalibrationConfigurationDialog(QWidget* parent, | |||
| 41 | 40 | ||
| 42 | using namespace InputCommon::CemuhookUDP; | 41 | using namespace InputCommon::CemuhookUDP; |
| 43 | job = std::make_unique<CalibrationConfigurationJob>( | 42 | job = std::make_unique<CalibrationConfigurationJob>( |
| 44 | host, port, pad_index, | 43 | host, port, |
| 45 | [this](CalibrationConfigurationJob::Status status) { | 44 | [this](CalibrationConfigurationJob::Status status) { |
| 46 | QString text; | 45 | QString text; |
| 47 | switch (status) { | 46 | switch (status) { |
| @@ -217,7 +216,7 @@ void ConfigureMotionTouch::OnCemuhookUDPTest() { | |||
| 217 | ui->udp_test->setText(tr("Testing")); | 216 | ui->udp_test->setText(tr("Testing")); |
| 218 | udp_test_in_progress = true; | 217 | udp_test_in_progress = true; |
| 219 | InputCommon::CemuhookUDP::TestCommunication( | 218 | InputCommon::CemuhookUDP::TestCommunication( |
| 220 | ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()), 0, | 219 | ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()), |
| 221 | [this] { | 220 | [this] { |
| 222 | LOG_INFO(Frontend, "UDP input test success"); | 221 | LOG_INFO(Frontend, "UDP input test success"); |
| 223 | QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, true)); | 222 | QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, true)); |
| @@ -232,7 +231,7 @@ void ConfigureMotionTouch::OnConfigureTouchCalibration() { | |||
| 232 | ui->touch_calibration_config->setEnabled(false); | 231 | ui->touch_calibration_config->setEnabled(false); |
| 233 | ui->touch_calibration_config->setText(tr("Configuring")); | 232 | ui->touch_calibration_config->setText(tr("Configuring")); |
| 234 | CalibrationConfigurationDialog dialog(this, ui->udp_server->text().toStdString(), | 233 | CalibrationConfigurationDialog dialog(this, ui->udp_server->text().toStdString(), |
| 235 | static_cast<u16>(ui->udp_port->text().toUInt()), 0); | 234 | static_cast<u16>(ui->udp_port->text().toUInt())); |
| 236 | dialog.exec(); | 235 | dialog.exec(); |
| 237 | if (dialog.completed) { | 236 | if (dialog.completed) { |
| 238 | min_x = dialog.min_x; | 237 | min_x = dialog.min_x; |
diff --git a/src/yuzu/configuration/configure_motion_touch.h b/src/yuzu/configuration/configure_motion_touch.h index d76bc8154..8b707d2ff 100644 --- a/src/yuzu/configuration/configure_motion_touch.h +++ b/src/yuzu/configuration/configure_motion_touch.h | |||
| @@ -29,8 +29,7 @@ class ConfigureMotionTouch; | |||
| 29 | class CalibrationConfigurationDialog : public QDialog { | 29 | class CalibrationConfigurationDialog : public QDialog { |
| 30 | Q_OBJECT | 30 | Q_OBJECT |
| 31 | public: | 31 | public: |
| 32 | explicit CalibrationConfigurationDialog(QWidget* parent, const std::string& host, u16 port, | 32 | explicit CalibrationConfigurationDialog(QWidget* parent, const std::string& host, u16 port); |
| 33 | u8 pad_index); | ||
| 34 | ~CalibrationConfigurationDialog() override; | 33 | ~CalibrationConfigurationDialog() override; |
| 35 | 34 | ||
| 36 | private: | 35 | private: |