summaryrefslogtreecommitdiffstats
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 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/logging/log.h"
+#include "common/scope_exit.h"
#include "common/swap.h"
#include "common/thread.h"
#include "input_common/helpers/joycon_driver.h"
@@ -71,6 +72,7 @@ DriverResult JoyconDriver::InitializeDevice() {
nfc_enabled = false;
passive_enabled = false;
irs_enabled = false;
+ input_only_device = false;
gyro_sensitivity = Joycon::GyroSensitivity::DPS2000;
gyro_performance = Joycon::GyroPerformance::HZ833;
accelerometer_sensitivity = Joycon::AccelerometerSensitivity::G8;
@@ -85,16 +87,23 @@ DriverResult JoyconDriver::InitializeDevice() {
rumble_protocol = std::make_unique<RumbleProtocol>(hidapi_handle);
// Get fixed joycon info
- generic_protocol->GetVersionNumber(version);
- generic_protocol->SetLowPowerMode(false);
- generic_protocol->GetColor(color);
- if (handle_device_type == ControllerType::Pro) {
- // Some 3rd party controllers aren't pro controllers
- generic_protocol->GetControllerType(device_type);
- } else {
- device_type = handle_device_type;
+ if (generic_protocol->GetVersionNumber(version) != DriverResult::Success) {
+ // If this command fails the device doesn't accept configuration commands
+ input_only_device = true;
}
- generic_protocol->GetSerialNumber(serial_number);
+
+ if (!input_only_device) {
+ generic_protocol->SetLowPowerMode(false);
+ generic_protocol->GetColor(color);
+ if (handle_device_type == ControllerType::Pro) {
+ // Some 3rd party controllers aren't pro controllers
+ generic_protocol->GetControllerType(device_type);
+ } else {
+ device_type = handle_device_type;
+ }
+ generic_protocol->GetSerialNumber(serial_number);
+ }
+
supported_features = GetSupportedFeatures();
// Get Calibration data
@@ -112,7 +121,7 @@ DriverResult JoyconDriver::InitializeDevice() {
joycon_poller = std::make_unique<JoyconPoller>(device_type, left_stick_calibration,
right_stick_calibration, motion_calibration);
- // Start pooling for data
+ // Start polling for data
is_connected = true;
if (!input_thread_running) {
input_thread =
@@ -208,7 +217,7 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) {
joycon_poller->UpdateCamera(irs_protocol->GetImage(), irs_protocol->GetIrsFormat());
}
- if (nfc_protocol->IsEnabled()) {
+ if (nfc_protocol->IsPolling()) {
if (amiibo_detected) {
if (!nfc_protocol->HasAmiibo()) {
joycon_poller->UpdateAmiibo({});
@@ -218,10 +227,10 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) {
}
if (!amiibo_detected) {
- std::vector<u8> data(0x21C);
- const auto result = nfc_protocol->ScanAmiibo(data);
+ Joycon::TagInfo tag_info;
+ const auto result = nfc_protocol->GetTagInfo(tag_info);
if (result == DriverResult::Success) {
- joycon_poller->UpdateAmiibo(data);
+ joycon_poller->UpdateAmiibo(tag_info);
amiibo_detected = true;
}
}
@@ -247,6 +256,7 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) {
}
DriverResult JoyconDriver::SetPollingMode() {
+ SCOPE_EXIT({ disable_input_thread = false; });
disable_input_thread = true;
rumble_protocol->EnableRumble(vibration_enabled && supported_features.vibration);
@@ -259,6 +269,10 @@ DriverResult JoyconDriver::SetPollingMode() {
generic_protocol->EnableImu(false);
}
+ if (input_only_device) {
+ return DriverResult::NotSupported;
+ }
+
if (irs_protocol->IsEnabled()) {
irs_protocol->DisableIrs();
}
@@ -276,24 +290,21 @@ DriverResult JoyconDriver::SetPollingMode() {
if (irs_enabled && supported_features.irs) {
auto result = irs_protocol->EnableIrs();
if (result == DriverResult::Success) {
- disable_input_thread = false;
return result;
}
irs_protocol->DisableIrs();
LOG_ERROR(Input, "Error enabling IRS");
+ return result;
}
if (nfc_enabled && supported_features.nfc) {
auto result = nfc_protocol->EnableNfc();
if (result == DriverResult::Success) {
- result = nfc_protocol->StartNFCPollingMode();
- }
- if (result == DriverResult::Success) {
- disable_input_thread = false;
return result;
}
nfc_protocol->DisableNfc();
LOG_ERROR(Input, "Error enabling NFC");
+ return result;
}
if (hidbus_enabled && supported_features.hidbus) {
@@ -303,18 +314,17 @@ DriverResult JoyconDriver::SetPollingMode() {
}
if (result == DriverResult::Success) {
ring_connected = true;
- disable_input_thread = false;
return result;
}
ring_connected = false;
ring_protocol->DisableRingCon();
LOG_ERROR(Input, "Error enabling Ringcon");
+ return result;
}
if (passive_enabled && supported_features.passive) {
const auto result = generic_protocol->EnablePassiveMode();
if (result == DriverResult::Success) {
- disable_input_thread = false;
return result;
}
LOG_ERROR(Input, "Error enabling passive mode");
@@ -328,7 +338,6 @@ DriverResult JoyconDriver::SetPollingMode() {
// Switch calls this function after enabling active mode
generic_protocol->TriggersElapsed();
- disable_input_thread = false;
return result;
}
@@ -339,6 +348,10 @@ JoyconDriver::SupportedFeatures JoyconDriver::GetSupportedFeatures() {
.vibration = true,
};
+ if (input_only_device) {
+ return features;
+ }
+
if (device_type == ControllerType::Right) {
features.nfc = true;
features.irs = true;
@@ -492,9 +505,68 @@ DriverResult JoyconDriver::SetRingConMode() {
return result;
}
-DriverResult JoyconDriver::WriteNfcData(std::span<const u8> data) {
+DriverResult JoyconDriver::StartNfcPolling() {
+ std::scoped_lock lock{mutex};
+
+ if (!supported_features.nfc) {
+ return DriverResult::NotSupported;
+ }
+ if (!nfc_protocol->IsEnabled()) {
+ return DriverResult::Disabled;
+ }
+
+ disable_input_thread = true;
+ const auto result = nfc_protocol->StartNFCPollingMode();
+ disable_input_thread = false;
+
+ return result;
+}
+
+DriverResult JoyconDriver::StopNfcPolling() {
+ std::scoped_lock lock{mutex};
+
+ if (!supported_features.nfc) {
+ return DriverResult::NotSupported;
+ }
+ if (!nfc_protocol->IsEnabled()) {
+ return DriverResult::Disabled;
+ }
+
+ disable_input_thread = true;
+ const auto result = nfc_protocol->StopNFCPollingMode();
+ disable_input_thread = false;
+
+ if (amiibo_detected) {
+ amiibo_detected = false;
+ joycon_poller->UpdateAmiibo({});
+ }
+
+ return result;
+}
+
+DriverResult JoyconDriver::ReadAmiiboData(std::vector<u8>& out_data) {
std::scoped_lock lock{mutex};
+
+ if (!supported_features.nfc) {
+ return DriverResult::NotSupported;
+ }
+ if (!nfc_protocol->IsEnabled()) {
+ return DriverResult::Disabled;
+ }
+ if (!amiibo_detected) {
+ return DriverResult::ErrorWritingData;
+ }
+
+ out_data.resize(0x21C);
disable_input_thread = true;
+ const auto result = nfc_protocol->ReadAmiibo(out_data);
+ disable_input_thread = false;
+
+ return result;
+}
+
+DriverResult JoyconDriver::WriteNfcData(std::span<const u8> data) {
+ std::scoped_lock lock{mutex};
if (!supported_features.nfc) {
return DriverResult::NotSupported;
@@ -506,9 +578,51 @@ DriverResult JoyconDriver::WriteNfcData(std::span<const u8> data) {
return DriverResult::ErrorWritingData;
}
+ disable_input_thread = true;
const auto result = nfc_protocol->WriteAmiibo(data);
+ disable_input_thread = false;
+
+ return result;
+}
+
+DriverResult JoyconDriver::ReadMifareData(std::span<const MifareReadChunk> data,
+ std::span<MifareReadData> out_data) {
+ std::scoped_lock lock{mutex};
+
+ if (!supported_features.nfc) {
+ return DriverResult::NotSupported;
+ }
+ if (!nfc_protocol->IsEnabled()) {
+ return DriverResult::Disabled;
+ }
+ if (!amiibo_detected) {
+ return DriverResult::ErrorWritingData;
+ }
+
+ disable_input_thread = true;
+ const auto result = nfc_protocol->ReadMifare(data, out_data);
+ disable_input_thread = false;
+
+ return result;
+}
+
+DriverResult JoyconDriver::WriteMifareData(std::span<const MifareWriteChunk> data) {
+ std::scoped_lock lock{mutex};
+ if (!supported_features.nfc) {
+ return DriverResult::NotSupported;
+ }
+ if (!nfc_protocol->IsEnabled()) {
+ return DriverResult::Disabled;
+ }
+ if (!amiibo_detected) {
+ return DriverResult::ErrorWritingData;
+ }
+
+ disable_input_thread = true;
+ const auto result = nfc_protocol->WriteMifare(data);
disable_input_thread = false;
+
return result;
}