summaryrefslogtreecommitdiff
path: root/src/input_common/helpers/joycon_driver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common/helpers/joycon_driver.cpp')
-rw-r--r--src/input_common/helpers/joycon_driver.cpp160
1 files changed, 137 insertions, 23 deletions
diff --git a/src/input_common/helpers/joycon_driver.cpp b/src/input_common/helpers/joycon_driver.cpp
index 95106f16d..ec984a647 100644
--- a/src/input_common/helpers/joycon_driver.cpp
+++ b/src/input_common/helpers/joycon_driver.cpp
@@ -2,6 +2,7 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "common/logging/log.h" 4#include "common/logging/log.h"
5#include "common/scope_exit.h"
5#include "common/swap.h" 6#include "common/swap.h"
6#include "common/thread.h" 7#include "common/thread.h"
7#include "input_common/helpers/joycon_driver.h" 8#include "input_common/helpers/joycon_driver.h"
@@ -71,6 +72,7 @@ DriverResult JoyconDriver::InitializeDevice() {
71 nfc_enabled = false; 72 nfc_enabled = false;
72 passive_enabled = false; 73 passive_enabled = false;
73 irs_enabled = false; 74 irs_enabled = false;
75 input_only_device = false;
74 gyro_sensitivity = Joycon::GyroSensitivity::DPS2000; 76 gyro_sensitivity = Joycon::GyroSensitivity::DPS2000;
75 gyro_performance = Joycon::GyroPerformance::HZ833; 77 gyro_performance = Joycon::GyroPerformance::HZ833;
76 accelerometer_sensitivity = Joycon::AccelerometerSensitivity::G8; 78 accelerometer_sensitivity = Joycon::AccelerometerSensitivity::G8;
@@ -85,16 +87,23 @@ DriverResult JoyconDriver::InitializeDevice() {
85 rumble_protocol = std::make_unique<RumbleProtocol>(hidapi_handle); 87 rumble_protocol = std::make_unique<RumbleProtocol>(hidapi_handle);
86 88
87 // Get fixed joycon info 89 // Get fixed joycon info
88 generic_protocol->GetVersionNumber(version); 90 if (generic_protocol->GetVersionNumber(version) != DriverResult::Success) {
89 generic_protocol->SetLowPowerMode(false); 91 // If this command fails the device doesn't accept configuration commands
90 generic_protocol->GetColor(color); 92 input_only_device = true;
91 if (handle_device_type == ControllerType::Pro) {
92 // Some 3rd party controllers aren't pro controllers
93 generic_protocol->GetControllerType(device_type);
94 } else {
95 device_type = handle_device_type;
96 } 93 }
97 generic_protocol->GetSerialNumber(serial_number); 94
95 if (!input_only_device) {
96 generic_protocol->SetLowPowerMode(false);
97 generic_protocol->GetColor(color);
98 if (handle_device_type == ControllerType::Pro) {
99 // Some 3rd party controllers aren't pro controllers
100 generic_protocol->GetControllerType(device_type);
101 } else {
102 device_type = handle_device_type;
103 }
104 generic_protocol->GetSerialNumber(serial_number);
105 }
106
98 supported_features = GetSupportedFeatures(); 107 supported_features = GetSupportedFeatures();
99 108
100 // Get Calibration data 109 // Get Calibration data
@@ -112,7 +121,7 @@ DriverResult JoyconDriver::InitializeDevice() {
112 joycon_poller = std::make_unique<JoyconPoller>(device_type, left_stick_calibration, 121 joycon_poller = std::make_unique<JoyconPoller>(device_type, left_stick_calibration,
113 right_stick_calibration, motion_calibration); 122 right_stick_calibration, motion_calibration);
114 123
115 // Start pooling for data 124 // Start polling for data
116 is_connected = true; 125 is_connected = true;
117 if (!input_thread_running) { 126 if (!input_thread_running) {
118 input_thread = 127 input_thread =
@@ -208,7 +217,7 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) {
208 joycon_poller->UpdateCamera(irs_protocol->GetImage(), irs_protocol->GetIrsFormat()); 217 joycon_poller->UpdateCamera(irs_protocol->GetImage(), irs_protocol->GetIrsFormat());
209 } 218 }
210 219
211 if (nfc_protocol->IsEnabled()) { 220 if (nfc_protocol->IsPolling()) {
212 if (amiibo_detected) { 221 if (amiibo_detected) {
213 if (!nfc_protocol->HasAmiibo()) { 222 if (!nfc_protocol->HasAmiibo()) {
214 joycon_poller->UpdateAmiibo({}); 223 joycon_poller->UpdateAmiibo({});
@@ -218,10 +227,10 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) {
218 } 227 }
219 228
220 if (!amiibo_detected) { 229 if (!amiibo_detected) {
221 std::vector<u8> data(0x21C); 230 Joycon::TagInfo tag_info;
222 const auto result = nfc_protocol->ScanAmiibo(data); 231 const auto result = nfc_protocol->GetTagInfo(tag_info);
223 if (result == DriverResult::Success) { 232 if (result == DriverResult::Success) {
224 joycon_poller->UpdateAmiibo(data); 233 joycon_poller->UpdateAmiibo(tag_info);
225 amiibo_detected = true; 234 amiibo_detected = true;
226 } 235 }
227 } 236 }
@@ -247,6 +256,7 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) {
247} 256}
248 257
249DriverResult JoyconDriver::SetPollingMode() { 258DriverResult JoyconDriver::SetPollingMode() {
259 SCOPE_EXIT({ disable_input_thread = false; });
250 disable_input_thread = true; 260 disable_input_thread = true;
251 261
252 rumble_protocol->EnableRumble(vibration_enabled && supported_features.vibration); 262 rumble_protocol->EnableRumble(vibration_enabled && supported_features.vibration);
@@ -259,6 +269,10 @@ DriverResult JoyconDriver::SetPollingMode() {
259 generic_protocol->EnableImu(false); 269 generic_protocol->EnableImu(false);
260 } 270 }
261 271
272 if (input_only_device) {
273 return DriverResult::NotSupported;
274 }
275
262 if (irs_protocol->IsEnabled()) { 276 if (irs_protocol->IsEnabled()) {
263 irs_protocol->DisableIrs(); 277 irs_protocol->DisableIrs();
264 } 278 }
@@ -276,24 +290,21 @@ DriverResult JoyconDriver::SetPollingMode() {
276 if (irs_enabled && supported_features.irs) { 290 if (irs_enabled && supported_features.irs) {
277 auto result = irs_protocol->EnableIrs(); 291 auto result = irs_protocol->EnableIrs();
278 if (result == DriverResult::Success) { 292 if (result == DriverResult::Success) {
279 disable_input_thread = false;
280 return result; 293 return result;
281 } 294 }
282 irs_protocol->DisableIrs(); 295 irs_protocol->DisableIrs();
283 LOG_ERROR(Input, "Error enabling IRS"); 296 LOG_ERROR(Input, "Error enabling IRS");
297 return result;
284 } 298 }
285 299
286 if (nfc_enabled && supported_features.nfc) { 300 if (nfc_enabled && supported_features.nfc) {
287 auto result = nfc_protocol->EnableNfc(); 301 auto result = nfc_protocol->EnableNfc();
288 if (result == DriverResult::Success) { 302 if (result == DriverResult::Success) {
289 result = nfc_protocol->StartNFCPollingMode();
290 }
291 if (result == DriverResult::Success) {
292 disable_input_thread = false;
293 return result; 303 return result;
294 } 304 }
295 nfc_protocol->DisableNfc(); 305 nfc_protocol->DisableNfc();
296 LOG_ERROR(Input, "Error enabling NFC"); 306 LOG_ERROR(Input, "Error enabling NFC");
307 return result;
297 } 308 }
298 309
299 if (hidbus_enabled && supported_features.hidbus) { 310 if (hidbus_enabled && supported_features.hidbus) {
@@ -303,18 +314,17 @@ DriverResult JoyconDriver::SetPollingMode() {
303 } 314 }
304 if (result == DriverResult::Success) { 315 if (result == DriverResult::Success) {
305 ring_connected = true; 316 ring_connected = true;
306 disable_input_thread = false;
307 return result; 317 return result;
308 } 318 }
309 ring_connected = false; 319 ring_connected = false;
310 ring_protocol->DisableRingCon(); 320 ring_protocol->DisableRingCon();
311 LOG_ERROR(Input, "Error enabling Ringcon"); 321 LOG_ERROR(Input, "Error enabling Ringcon");
322 return result;
312 } 323 }
313 324
314 if (passive_enabled && supported_features.passive) { 325 if (passive_enabled && supported_features.passive) {
315 const auto result = generic_protocol->EnablePassiveMode(); 326 const auto result = generic_protocol->EnablePassiveMode();
316 if (result == DriverResult::Success) { 327 if (result == DriverResult::Success) {
317 disable_input_thread = false;
318 return result; 328 return result;
319 } 329 }
320 LOG_ERROR(Input, "Error enabling passive mode"); 330 LOG_ERROR(Input, "Error enabling passive mode");
@@ -328,7 +338,6 @@ DriverResult JoyconDriver::SetPollingMode() {
328 // Switch calls this function after enabling active mode 338 // Switch calls this function after enabling active mode
329 generic_protocol->TriggersElapsed(); 339 generic_protocol->TriggersElapsed();
330 340
331 disable_input_thread = false;
332 return result; 341 return result;
333} 342}
334 343
@@ -339,6 +348,10 @@ JoyconDriver::SupportedFeatures JoyconDriver::GetSupportedFeatures() {
339 .vibration = true, 348 .vibration = true,
340 }; 349 };
341 350
351 if (input_only_device) {
352 return features;
353 }
354
342 if (device_type == ControllerType::Right) { 355 if (device_type == ControllerType::Right) {
343 features.nfc = true; 356 features.nfc = true;
344 features.irs = true; 357 features.irs = true;
@@ -492,9 +505,68 @@ DriverResult JoyconDriver::SetRingConMode() {
492 return result; 505 return result;
493} 506}
494 507
495DriverResult JoyconDriver::WriteNfcData(std::span<const u8> data) { 508DriverResult JoyconDriver::StartNfcPolling() {
509 std::scoped_lock lock{mutex};
510
511 if (!supported_features.nfc) {
512 return DriverResult::NotSupported;
513 }
514 if (!nfc_protocol->IsEnabled()) {
515 return DriverResult::Disabled;
516 }
517
518 disable_input_thread = true;
519 const auto result = nfc_protocol->StartNFCPollingMode();
520 disable_input_thread = false;
521
522 return result;
523}
524
525DriverResult JoyconDriver::StopNfcPolling() {
526 std::scoped_lock lock{mutex};
527
528 if (!supported_features.nfc) {
529 return DriverResult::NotSupported;
530 }
531 if (!nfc_protocol->IsEnabled()) {
532 return DriverResult::Disabled;
533 }
534
535 disable_input_thread = true;
536 const auto result = nfc_protocol->StopNFCPollingMode();
537 disable_input_thread = false;
538
539 if (amiibo_detected) {
540 amiibo_detected = false;
541 joycon_poller->UpdateAmiibo({});
542 }
543
544 return result;
545}
546
547DriverResult JoyconDriver::ReadAmiiboData(std::vector<u8>& out_data) {
496 std::scoped_lock lock{mutex}; 548 std::scoped_lock lock{mutex};
549
550 if (!supported_features.nfc) {
551 return DriverResult::NotSupported;
552 }
553 if (!nfc_protocol->IsEnabled()) {
554 return DriverResult::Disabled;
555 }
556 if (!amiibo_detected) {
557 return DriverResult::ErrorWritingData;
558 }
559
560 out_data.resize(0x21C);
497 disable_input_thread = true; 561 disable_input_thread = true;
562 const auto result = nfc_protocol->ReadAmiibo(out_data);
563 disable_input_thread = false;
564
565 return result;
566}
567
568DriverResult JoyconDriver::WriteNfcData(std::span<const u8> data) {
569 std::scoped_lock lock{mutex};
498 570
499 if (!supported_features.nfc) { 571 if (!supported_features.nfc) {
500 return DriverResult::NotSupported; 572 return DriverResult::NotSupported;
@@ -506,9 +578,51 @@ DriverResult JoyconDriver::WriteNfcData(std::span<const u8> data) {
506 return DriverResult::ErrorWritingData; 578 return DriverResult::ErrorWritingData;
507 } 579 }
508 580
581 disable_input_thread = true;
509 const auto result = nfc_protocol->WriteAmiibo(data); 582 const auto result = nfc_protocol->WriteAmiibo(data);
583 disable_input_thread = false;
584
585 return result;
586}
587
588DriverResult JoyconDriver::ReadMifareData(std::span<const MifareReadChunk> data,
589 std::span<MifareReadData> out_data) {
590 std::scoped_lock lock{mutex};
591
592 if (!supported_features.nfc) {
593 return DriverResult::NotSupported;
594 }
595 if (!nfc_protocol->IsEnabled()) {
596 return DriverResult::Disabled;
597 }
598 if (!amiibo_detected) {
599 return DriverResult::ErrorWritingData;
600 }
601
602 disable_input_thread = true;
603 const auto result = nfc_protocol->ReadMifare(data, out_data);
604 disable_input_thread = false;
605
606 return result;
607}
608
609DriverResult JoyconDriver::WriteMifareData(std::span<const MifareWriteChunk> data) {
610 std::scoped_lock lock{mutex};
510 611
612 if (!supported_features.nfc) {
613 return DriverResult::NotSupported;
614 }
615 if (!nfc_protocol->IsEnabled()) {
616 return DriverResult::Disabled;
617 }
618 if (!amiibo_detected) {
619 return DriverResult::ErrorWritingData;
620 }
621
622 disable_input_thread = true;
623 const auto result = nfc_protocol->WriteMifare(data);
511 disable_input_thread = false; 624 disable_input_thread = false;
625
512 return result; 626 return result;
513} 627}
514 628