summaryrefslogtreecommitdiff
path: root/src/input_common/udp/client.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common/udp/client.cpp')
-rw-r--r--src/input_common/udp/client.cpp143
1 files changed, 94 insertions, 49 deletions
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp
index c0bb90048..17a9225d7 100644
--- a/src/input_common/udp/client.cpp
+++ b/src/input_common/udp/client.cpp
@@ -136,15 +136,7 @@ static void SocketLoop(Socket* socket) {
136 136
137Client::Client() { 137Client::Client() {
138 LOG_INFO(Input, "Udp Initialization started"); 138 LOG_INFO(Input, "Udp Initialization started");
139 for (std::size_t client = 0; client < clients.size(); client++) { 139 ReloadSockets();
140 const auto pad = client % 4;
141 StartCommunication(client, Settings::values.udp_input_address,
142 Settings::values.udp_input_port, pad, 24872);
143 // Set motion parameters
144 // SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode
145 // Real HW values are unknown, 0.0001 is an approximate to Standard
146 clients[client].motion.SetGyroThreshold(0.0001f);
147 }
148} 140}
149 141
150Client::~Client() { 142Client::~Client() {
@@ -167,26 +159,61 @@ std::vector<Common::ParamPackage> Client::GetInputDevices() const {
167 return devices; 159 return devices;
168} 160}
169 161
170bool Client::DeviceConnected(std::size_t pad) const { 162bool Client::DeviceConnected(std::size_t client) const {
171 // Use last timestamp to detect if the socket has stopped sending data 163 // Use last timestamp to detect if the socket has stopped sending data
172 const auto now = std::chrono::system_clock::now(); 164 const auto now = std::chrono::steady_clock::now();
173 const auto time_difference = static_cast<u64>( 165 const auto time_difference =
174 std::chrono::duration_cast<std::chrono::milliseconds>(now - clients[pad].last_motion_update) 166 static_cast<u64>(std::chrono::duration_cast<std::chrono::milliseconds>(
175 .count()); 167 now - clients[client].last_motion_update)
176 return time_difference < 1000 && clients[pad].active == 1; 168 .count());
169 return time_difference < 1000 && clients[client].active == 1;
177} 170}
178 171
179void Client::ReloadUDPClient() { 172void Client::ReloadSockets() {
180 for (std::size_t client = 0; client < clients.size(); client++) { 173 Reset();
181 ReloadSocket(Settings::values.udp_input_address, Settings::values.udp_input_port, client); 174
175 std::stringstream servers_ss(Settings::values.udp_input_servers);
176 std::string server_token;
177 std::size_t client = 0;
178 while (std::getline(servers_ss, server_token, ',')) {
179 if (client == max_udp_clients) {
180 break;
181 }
182 std::stringstream server_ss(server_token);
183 std::string token;
184 std::getline(server_ss, token, ':');
185 std::string udp_input_address = token;
186 std::getline(server_ss, token, ':');
187 char* temp;
188 const u16 udp_input_port = static_cast<u16>(std::strtol(token.c_str(), &temp, 0));
189 if (*temp != '\0') {
190 LOG_ERROR(Input, "Port number is not valid {}", token);
191 continue;
192 }
193
194 for (std::size_t pad = 0; pad < 4; ++pad) {
195 const std::size_t client_number =
196 GetClientNumber(udp_input_address, udp_input_port, pad);
197 if (client_number != max_udp_clients) {
198 LOG_ERROR(Input, "Duplicated UDP servers found");
199 continue;
200 }
201 StartCommunication(client++, udp_input_address, udp_input_port, pad, 24872);
202 }
182 } 203 }
183} 204}
184void Client::ReloadSocket(const std::string& host, u16 port, std::size_t pad_index, u32 client_id) { 205
185 // client number must be determined from host / port and pad index 206std::size_t Client::GetClientNumber(std::string_view host, u16 port, std::size_t pad) const {
186 const std::size_t client = pad_index; 207 for (std::size_t client = 0; client < clients.size(); client++) {
187 clients[client].socket->Stop(); 208 if (clients[client].active == -1) {
188 clients[client].thread.join(); 209 continue;
189 StartCommunication(client, host, port, pad_index, client_id); 210 }
211 if (clients[client].host == host && clients[client].port == port &&
212 clients[client].pad_index == pad) {
213 return client;
214 }
215 }
216 return max_udp_clients;
190} 217}
191 218
192void Client::OnVersion([[maybe_unused]] Response::Version data) { 219void Client::OnVersion([[maybe_unused]] Response::Version data) {
@@ -197,9 +224,7 @@ void Client::OnPortInfo([[maybe_unused]] Response::PortInfo data) {
197 LOG_TRACE(Input, "PortInfo packet received: {}", data.model); 224 LOG_TRACE(Input, "PortInfo packet received: {}", data.model);
198} 225}
199 226
200void Client::OnPadData(Response::PadData data) { 227void Client::OnPadData(Response::PadData data, std::size_t client) {
201 // Client number must be determined from host / port and pad index
202 const std::size_t client = data.info.id;
203 LOG_TRACE(Input, "PadData packet received"); 228 LOG_TRACE(Input, "PadData packet received");
204 if (data.packet_counter == clients[client].packet_sequence) { 229 if (data.packet_counter == clients[client].packet_sequence) {
205 LOG_WARNING( 230 LOG_WARNING(
@@ -208,9 +233,9 @@ void Client::OnPadData(Response::PadData data) {
208 clients[client].packet_sequence, data.packet_counter); 233 clients[client].packet_sequence, data.packet_counter);
209 return; 234 return;
210 } 235 }
211 clients[client].active = data.info.is_pad_active; 236 clients[client].active = static_cast<s8>(data.info.is_pad_active);
212 clients[client].packet_sequence = data.packet_counter; 237 clients[client].packet_sequence = data.packet_counter;
213 const auto now = std::chrono::system_clock::now(); 238 const auto now = std::chrono::steady_clock::now();
214 const auto time_difference = 239 const auto time_difference =
215 static_cast<u64>(std::chrono::duration_cast<std::chrono::microseconds>( 240 static_cast<u64>(std::chrono::duration_cast<std::chrono::microseconds>(
216 now - clients[client].last_motion_update) 241 now - clients[client].last_motion_update)
@@ -264,16 +289,28 @@ void Client::StartCommunication(std::size_t client, const std::string& host, u16
264 std::size_t pad_index, u32 client_id) { 289 std::size_t pad_index, u32 client_id) {
265 SocketCallback callback{[this](Response::Version version) { OnVersion(version); }, 290 SocketCallback callback{[this](Response::Version version) { OnVersion(version); },
266 [this](Response::PortInfo info) { OnPortInfo(info); }, 291 [this](Response::PortInfo info) { OnPortInfo(info); },
267 [this](Response::PadData data) { OnPadData(data); }}; 292 [this, client](Response::PadData data) { OnPadData(data, client); }};
268 LOG_INFO(Input, "Starting communication with UDP input server on {}:{}", host, port); 293 LOG_INFO(Input, "Starting communication with UDP input server on {}:{}:{}", host, port,
294 pad_index);
295 clients[client].host = host;
296 clients[client].port = port;
297 clients[client].pad_index = pad_index;
298 clients[client].active = 0;
269 clients[client].socket = std::make_unique<Socket>(host, port, pad_index, client_id, callback); 299 clients[client].socket = std::make_unique<Socket>(host, port, pad_index, client_id, callback);
270 clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()}; 300 clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()};
301 // Set motion parameters
302 // SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode
303 // Real HW values are unknown, 0.0001 is an approximate to Standard
304 clients[client].motion.SetGyroThreshold(0.0001f);
271} 305}
272 306
273void Client::Reset() { 307void Client::Reset() {
274 for (auto& client : clients) { 308 for (auto& client : clients) {
275 client.socket->Stop(); 309 if (client.thread.joinable()) {
276 client.thread.join(); 310 client.active = -1;
311 client.socket->Stop();
312 client.thread.join();
313 }
277 } 314 }
278} 315}
279 316
@@ -283,52 +320,60 @@ void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& a
283 LOG_DEBUG(Input, "UDP Controller {}: gyro=({}, {}, {}), accel=({}, {}, {}), touch={}", 320 LOG_DEBUG(Input, "UDP Controller {}: gyro=({}, {}, {}), accel=({}, {}, {}), touch={}",
284 client, gyro[0], gyro[1], gyro[2], acc[0], acc[1], acc[2], touch); 321 client, gyro[0], gyro[1], gyro[2], acc[0], acc[1], acc[2], touch);
285 } 322 }
286 UDPPadStatus pad; 323 UDPPadStatus pad{
324 .host = clients[client].host,
325 .port = clients[client].port,
326 .pad_index = clients[client].pad_index,
327 };
287 if (touch) { 328 if (touch) {
288 pad.touch = PadTouch::Click; 329 pad.touch = PadTouch::Click;
289 pad_queue[client].Push(pad); 330 pad_queue.Push(pad);
290 } 331 }
291 for (size_t i = 0; i < 3; ++i) { 332 for (size_t i = 0; i < 3; ++i) {
292 if (gyro[i] > 5.0f || gyro[i] < -5.0f) { 333 if (gyro[i] > 5.0f || gyro[i] < -5.0f) {
293 pad.motion = static_cast<PadMotion>(i); 334 pad.motion = static_cast<PadMotion>(i);
294 pad.motion_value = gyro[i]; 335 pad.motion_value = gyro[i];
295 pad_queue[client].Push(pad); 336 pad_queue.Push(pad);
296 } 337 }
297 if (acc[i] > 1.75f || acc[i] < -1.75f) { 338 if (acc[i] > 1.75f || acc[i] < -1.75f) {
298 pad.motion = static_cast<PadMotion>(i + 3); 339 pad.motion = static_cast<PadMotion>(i + 3);
299 pad.motion_value = acc[i]; 340 pad.motion_value = acc[i];
300 pad_queue[client].Push(pad); 341 pad_queue.Push(pad);
301 } 342 }
302 } 343 }
303} 344}
304 345
305void Client::BeginConfiguration() { 346void Client::BeginConfiguration() {
306 for (auto& pq : pad_queue) { 347 pad_queue.Clear();
307 pq.Clear();
308 }
309 configuring = true; 348 configuring = true;
310} 349}
311 350
312void Client::EndConfiguration() { 351void Client::EndConfiguration() {
313 for (auto& pq : pad_queue) { 352 pad_queue.Clear();
314 pq.Clear();
315 }
316 configuring = false; 353 configuring = false;
317} 354}
318 355
319DeviceStatus& Client::GetPadState(std::size_t pad) { 356DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) {
320 return clients[pad].status; 357 const std::size_t client_number = GetClientNumber(host, port, pad);
358 if (client_number == max_udp_clients) {
359 return clients[0].status;
360 }
361 return clients[client_number].status;
321} 362}
322 363
323const DeviceStatus& Client::GetPadState(std::size_t pad) const { 364const DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) const {
324 return clients[pad].status; 365 const std::size_t client_number = GetClientNumber(host, port, pad);
366 if (client_number == max_udp_clients) {
367 return clients[0].status;
368 }
369 return clients[client_number].status;
325} 370}
326 371
327std::array<Common::SPSCQueue<UDPPadStatus>, 4>& Client::GetPadQueue() { 372Common::SPSCQueue<UDPPadStatus>& Client::GetPadQueue() {
328 return pad_queue; 373 return pad_queue;
329} 374}
330 375
331const std::array<Common::SPSCQueue<UDPPadStatus>, 4>& Client::GetPadQueue() const { 376const Common::SPSCQueue<UDPPadStatus>& Client::GetPadQueue() const {
332 return pad_queue; 377 return pad_queue;
333} 378}
334 379