From 5aa208e26417a455abced9c067f75e1b81f2cb80 Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sat, 24 Jun 2023 18:48:45 -0600
Subject: [PATCH 1/2] input_common: Dont try to read/write data from 3rd party
 controllers

---
 src/core/hid/emulated_controller.cpp          |  5 +++
 src/input_common/helpers/joycon_driver.cpp    | 42 +++++++++++++++----
 src/input_common/helpers/joycon_driver.h      |  1 +
 .../joycon_protocol/common_protocol.cpp       |  8 ++--
 4 files changed, 42 insertions(+), 14 deletions(-)

diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index c937495f9..190f7c906 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -1250,6 +1250,11 @@ Common::Input::DriverResult EmulatedController::SetPollingMode(
         const auto virtual_nfc_result = nfc_output_device->SetPollingMode(polling_mode);
         const auto mapped_nfc_result = right_output_device->SetPollingMode(polling_mode);
 
+        // Restore previous state
+        if (mapped_nfc_result != Common::Input::DriverResult::Success) {
+            right_output_device->SetPollingMode(Common::Input::PollingMode::Active);
+        }
+
         if (virtual_nfc_result == Common::Input::DriverResult::Success) {
             return virtual_nfc_result;
         }
diff --git a/src/input_common/helpers/joycon_driver.cpp b/src/input_common/helpers/joycon_driver.cpp
index 2c8c66951..ec984a647 100644
--- a/src/input_common/helpers/joycon_driver.cpp
+++ b/src/input_common/helpers/joycon_driver.cpp
@@ -72,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;
@@ -86,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
@@ -261,6 +269,10 @@ DriverResult JoyconDriver::SetPollingMode() {
         generic_protocol->EnableImu(false);
     }
 
+    if (input_only_device) {
+        return DriverResult::NotSupported;
+    }
+
     if (irs_protocol->IsEnabled()) {
         irs_protocol->DisableIrs();
     }
@@ -282,6 +294,7 @@ DriverResult JoyconDriver::SetPollingMode() {
         }
         irs_protocol->DisableIrs();
         LOG_ERROR(Input, "Error enabling IRS");
+        return result;
     }
 
     if (nfc_enabled && supported_features.nfc) {
@@ -291,6 +304,7 @@ DriverResult JoyconDriver::SetPollingMode() {
         }
         nfc_protocol->DisableNfc();
         LOG_ERROR(Input, "Error enabling NFC");
+        return result;
     }
 
     if (hidbus_enabled && supported_features.hidbus) {
@@ -305,6 +319,7 @@ DriverResult JoyconDriver::SetPollingMode() {
         ring_connected = false;
         ring_protocol->DisableRingCon();
         LOG_ERROR(Input, "Error enabling Ringcon");
+        return result;
     }
 
     if (passive_enabled && supported_features.passive) {
@@ -333,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;
@@ -517,6 +536,11 @@ DriverResult JoyconDriver::StopNfcPolling() {
     const auto result = nfc_protocol->StopNFCPollingMode();
     disable_input_thread = false;
 
+    if (amiibo_detected) {
+        amiibo_detected = false;
+        joycon_poller->UpdateAmiibo({});
+    }
+
     return result;
 }
 
diff --git a/src/input_common/helpers/joycon_driver.h b/src/input_common/helpers/joycon_driver.h
index bc7025a21..45b32d2f8 100644
--- a/src/input_common/helpers/joycon_driver.h
+++ b/src/input_common/helpers/joycon_driver.h
@@ -120,6 +120,7 @@ private:
     // Hardware configuration
     u8 leds{};
     ReportMode mode{};
+    bool input_only_device{};
     bool passive_enabled{};   // Low power mode, Ideal for multiple controllers at the same time
     bool hidbus_enabled{};    // External device support
     bool irs_enabled{};       // Infrared camera input
diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.cpp b/src/input_common/helpers/joycon_protocol/common_protocol.cpp
index 51669261a..88f4cec1c 100644
--- a/src/input_common/helpers/joycon_protocol/common_protocol.cpp
+++ b/src/input_common/helpers/joycon_protocol/common_protocol.cpp
@@ -73,7 +73,7 @@ DriverResult JoyconCommonProtocol::SendRawData(std::span<const u8> buffer) {
 DriverResult JoyconCommonProtocol::GetSubCommandResponse(SubCommand sc,
                                                          SubCommandResponse& output) {
     constexpr int timeout_mili = 66;
-    constexpr int MaxTries = 15;
+    constexpr int MaxTries = 3;
     int tries = 0;
 
     do {
@@ -113,9 +113,7 @@ DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const
         return result;
     }
 
-    result = GetSubCommandResponse(sc, output);
-
-    return DriverResult::Success;
+    return GetSubCommandResponse(sc, output);
 }
 
 DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const u8> buffer) {
@@ -158,7 +156,7 @@ DriverResult JoyconCommonProtocol::SendVibrationReport(std::span<const u8> buffe
 
 DriverResult JoyconCommonProtocol::ReadRawSPI(SpiAddress addr, std::span<u8> output) {
     constexpr std::size_t HeaderSize = 5;
-    constexpr std::size_t MaxTries = 10;
+    constexpr std::size_t MaxTries = 5;
     std::size_t tries = 0;
     SubCommandResponse response{};
     std::array<u8, sizeof(ReadSpiPacket)> buffer{};

From bf641e2964d513e9b9e3495c7d68d1c18c5b806e Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Sat, 24 Jun 2023 18:59:40 -0600
Subject: [PATCH 2/2] core: hid: Allow to read bin files while switch
 controller is available

---
 src/core/hid/emulated_controller.cpp | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 190f7c906..1ebc32c1e 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -1334,16 +1334,22 @@ bool EmulatedController::StartNfcPolling() {
     auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
     auto& nfc_virtual_output_device = output_devices[3];
 
-    return nfc_output_device->StartNfcPolling() == Common::Input::NfcState::Success ||
-           nfc_virtual_output_device->StartNfcPolling() == Common::Input::NfcState::Success;
+    const auto device_result = nfc_output_device->StartNfcPolling();
+    const auto virtual_device_result = nfc_virtual_output_device->StartNfcPolling();
+
+    return device_result == Common::Input::NfcState::Success ||
+           virtual_device_result == Common::Input::NfcState::Success;
 }
 
 bool EmulatedController::StopNfcPolling() {
     auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
     auto& nfc_virtual_output_device = output_devices[3];
 
-    return nfc_output_device->StopNfcPolling() == Common::Input::NfcState::Success ||
-           nfc_virtual_output_device->StopNfcPolling() == Common::Input::NfcState::Success;
+    const auto device_result = nfc_output_device->StopNfcPolling();
+    const auto virtual_device_result = nfc_virtual_output_device->StopNfcPolling();
+
+    return device_result == Common::Input::NfcState::Success ||
+           virtual_device_result == Common::Input::NfcState::Success;
 }
 
 bool EmulatedController::ReadAmiiboData(std::vector<u8>& data) {