summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar german772023-01-13 23:29:05 -0600
committerGravatar Narr the Reg2023-01-20 00:51:45 -0600
commit340f15d1fa79594dbe12a6e19140ba012751b533 (patch)
tree7a9ef54a17f927e4b8cf98dd32dd6d41c0d75201 /src
parentcore: hid: Only set the polling mode to the correct side (diff)
downloadyuzu-340f15d1fa79594dbe12a6e19140ba012751b533.tar.gz
yuzu-340f15d1fa79594dbe12a6e19140ba012751b533.tar.xz
yuzu-340f15d1fa79594dbe12a6e19140ba012751b533.zip
input_common: Address byte review
Diffstat (limited to 'src')
-rw-r--r--src/input_common/drivers/joycon.cpp50
-rw-r--r--src/input_common/drivers/joycon.h1
-rw-r--r--src/input_common/drivers/sdl_driver.cpp2
-rw-r--r--src/input_common/helpers/joycon_driver.cpp8
-rw-r--r--src/input_common/helpers/joycon_driver.h3
-rw-r--r--src/input_common/helpers/joycon_protocol/calibration.cpp9
-rw-r--r--src/input_common/helpers/joycon_protocol/common_protocol.cpp24
-rw-r--r--src/input_common/helpers/joycon_protocol/common_protocol.h22
-rw-r--r--src/input_common/helpers/joycon_protocol/generic_functions.cpp54
-rw-r--r--src/input_common/helpers/joycon_protocol/irs.cpp18
-rw-r--r--src/input_common/helpers/joycon_protocol/joycon_types.h12
-rw-r--r--src/input_common/helpers/joycon_protocol/nfc.cpp183
-rw-r--r--src/input_common/helpers/joycon_protocol/nfc.h4
-rw-r--r--src/input_common/helpers/joycon_protocol/poller.cpp18
-rw-r--r--src/input_common/helpers/joycon_protocol/ringcon.cpp36
-rw-r--r--src/input_common/helpers/joycon_protocol/rumble.cpp19
16 files changed, 220 insertions, 243 deletions
diff --git a/src/input_common/drivers/joycon.cpp b/src/input_common/drivers/joycon.cpp
index fff886ca8..1582def13 100644
--- a/src/input_common/drivers/joycon.cpp
+++ b/src/input_common/drivers/joycon.cpp
@@ -60,15 +60,12 @@ void Joycons::Setup() {
60 device = std::make_shared<Joycon::JoyconDriver>(port++); 60 device = std::make_shared<Joycon::JoyconDriver>(port++);
61 } 61 }
62 62
63 if (!scan_thread_running) { 63 scan_thread = std::jthread([this](std::stop_token stop_token) { ScanThread(stop_token); });
64 scan_thread = std::jthread([this](std::stop_token stop_token) { ScanThread(stop_token); });
65 }
66} 64}
67 65
68void Joycons::ScanThread(std::stop_token stop_token) { 66void Joycons::ScanThread(std::stop_token stop_token) {
69 constexpr u16 nintendo_vendor_id = 0x057e; 67 constexpr u16 nintendo_vendor_id = 0x057e;
70 Common::SetCurrentThreadName("yuzu:input:JoyconScanThread"); 68 Common::SetCurrentThreadName("JoyconScanThread");
71 scan_thread_running = true;
72 while (!stop_token.stop_requested()) { 69 while (!stop_token.stop_requested()) {
73 SDL_hid_device_info* devs = SDL_hid_enumerate(nintendo_vendor_id, 0x0); 70 SDL_hid_device_info* devs = SDL_hid_enumerate(nintendo_vendor_id, 0x0);
74 SDL_hid_device_info* cur_dev = devs; 71 SDL_hid_device_info* cur_dev = devs;
@@ -82,9 +79,9 @@ void Joycons::ScanThread(std::stop_token stop_token) {
82 cur_dev = cur_dev->next; 79 cur_dev = cur_dev->next;
83 } 80 }
84 81
82 SDL_hid_free_enumeration(devs);
85 std::this_thread::sleep_for(std::chrono::seconds(5)); 83 std::this_thread::sleep_for(std::chrono::seconds(5));
86 } 84 }
87 scan_thread_running = false;
88} 85}
89 86
90bool Joycons::IsDeviceNew(SDL_hid_device_info* device_info) const { 87bool Joycons::IsDeviceNew(SDL_hid_device_info* device_info) const {
@@ -185,19 +182,19 @@ void Joycons::RegisterNewDevice(SDL_hid_device_info* device_info) {
185 182
186std::shared_ptr<Joycon::JoyconDriver> Joycons::GetNextFreeHandle( 183std::shared_ptr<Joycon::JoyconDriver> Joycons::GetNextFreeHandle(
187 Joycon::ControllerType type) const { 184 Joycon::ControllerType type) const {
188
189 if (type == Joycon::ControllerType::Left) { 185 if (type == Joycon::ControllerType::Left) {
190 for (const auto& device : left_joycons) { 186 const auto unconnected_device =
191 if (!device->IsConnected()) { 187 std::ranges::find_if(left_joycons, [](auto& device) { return !device->IsConnected(); });
192 return device; 188 if (unconnected_device != left_joycons.end()) {
193 } 189 return *unconnected_device;
194 } 190 }
195 } 191 }
196 if (type == Joycon::ControllerType::Right) { 192 if (type == Joycon::ControllerType::Right) {
197 for (const auto& device : right_joycons) { 193 const auto unconnected_device = std::ranges::find_if(
198 if (!device->IsConnected()) { 194 right_joycons, [](auto& device) { return !device->IsConnected(); });
199 return device; 195
200 } 196 if (unconnected_device != right_joycons.end()) {
197 return *unconnected_device;
201 } 198 }
202 } 199 }
203 return nullptr; 200 return nullptr;
@@ -391,20 +388,25 @@ std::shared_ptr<Joycon::JoyconDriver> Joycons::GetHandle(PadIdentifier identifie
391 return false; 388 return false;
392 }; 389 };
393 const auto type = static_cast<Joycon::ControllerType>(identifier.pad); 390 const auto type = static_cast<Joycon::ControllerType>(identifier.pad);
391
394 if (type == Joycon::ControllerType::Left) { 392 if (type == Joycon::ControllerType::Left) {
395 for (const auto& device : left_joycons) { 393 const auto matching_device = std::ranges::find_if(
396 if (is_handle_active(device)) { 394 left_joycons, [is_handle_active](auto& device) { return is_handle_active(device); });
397 return device; 395
398 } 396 if (matching_device != left_joycons.end()) {
397 return *matching_device;
399 } 398 }
400 } 399 }
400
401 if (type == Joycon::ControllerType::Right) { 401 if (type == Joycon::ControllerType::Right) {
402 for (const auto& device : right_joycons) { 402 const auto matching_device = std::ranges::find_if(
403 if (is_handle_active(device)) { 403 right_joycons, [is_handle_active](auto& device) { return is_handle_active(device); });
404 return device; 404
405 } 405 if (matching_device != right_joycons.end()) {
406 return *matching_device;
406 } 407 }
407 } 408 }
409
408 return nullptr; 410 return nullptr;
409} 411}
410 412
@@ -676,7 +678,7 @@ std::string Joycons::JoyconName(Joycon::ControllerType type) const {
676 case Joycon::ControllerType::Dual: 678 case Joycon::ControllerType::Dual:
677 return "Dual Joycon"; 679 return "Dual Joycon";
678 default: 680 default:
679 return "Unknow Joycon"; 681 return "Unknown Joycon";
680 } 682 }
681} 683}
682} // namespace InputCommon 684} // namespace InputCommon
diff --git a/src/input_common/drivers/joycon.h b/src/input_common/drivers/joycon.h
index f5cc787db..6d2e2ec78 100644
--- a/src/input_common/drivers/joycon.h
+++ b/src/input_common/drivers/joycon.h
@@ -99,7 +99,6 @@ private:
99 std::string JoyconName(Joycon::ControllerType type) const; 99 std::string JoyconName(Joycon::ControllerType type) const;
100 100
101 std::jthread scan_thread; 101 std::jthread scan_thread;
102 bool scan_thread_running{};
103 102
104 // Joycon types are split by type to ease supporting dualjoycon configurations 103 // Joycon types are split by type to ease supporting dualjoycon configurations
105 std::array<std::shared_ptr<Joycon::JoyconDriver>, MaxSupportedControllers> left_joycons{}; 104 std::array<std::shared_ptr<Joycon::JoyconDriver>, MaxSupportedControllers> left_joycons{};
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index e915ec090..a0103edde 100644
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -321,7 +321,7 @@ void SDLDriver::InitJoystick(int joystick_index) {
321 if (Settings::values.enable_joycon_driver) { 321 if (Settings::values.enable_joycon_driver) {
322 if (guid.uuid[5] == 0x05 && guid.uuid[4] == 0x7e && 322 if (guid.uuid[5] == 0x05 && guid.uuid[4] == 0x7e &&
323 (guid.uuid[8] == 0x06 || guid.uuid[8] == 0x07)) { 323 (guid.uuid[8] == 0x06 || guid.uuid[8] == 0x07)) {
324 LOG_ERROR(Input, "Device black listed {}", joystick_index); 324 LOG_WARNING(Input, "Preferring joycon driver for device index {}", joystick_index);
325 SDL_JoystickClose(sdl_joystick); 325 SDL_JoystickClose(sdl_joystick);
326 return; 326 return;
327 } 327 }
diff --git a/src/input_common/helpers/joycon_driver.cpp b/src/input_common/helpers/joycon_driver.cpp
index 552572343..4159e5717 100644
--- a/src/input_common/helpers/joycon_driver.cpp
+++ b/src/input_common/helpers/joycon_driver.cpp
@@ -123,7 +123,7 @@ DriverResult JoyconDriver::InitializeDevice() {
123} 123}
124 124
125void JoyconDriver::InputThread(std::stop_token stop_token) { 125void JoyconDriver::InputThread(std::stop_token stop_token) {
126 LOG_INFO(Input, "JC Adapter input thread started"); 126 LOG_INFO(Input, "Joycon Adapter input thread started");
127 Common::SetCurrentThreadName("JoyconInput"); 127 Common::SetCurrentThreadName("JoyconInput");
128 input_thread_running = true; 128 input_thread_running = true;
129 129
@@ -157,7 +157,7 @@ void JoyconDriver::InputThread(std::stop_token stop_token) {
157 157
158 is_connected = false; 158 is_connected = false;
159 input_thread_running = false; 159 input_thread_running = false;
160 LOG_INFO(Input, "JC Adapter input thread stopped"); 160 LOG_INFO(Input, "Joycon Adapter input thread stopped");
161} 161}
162 162
163void JoyconDriver::OnNewData(std::span<u8> buffer) { 163void JoyconDriver::OnNewData(std::span<u8> buffer) {
@@ -349,7 +349,7 @@ JoyconDriver::SupportedFeatures JoyconDriver::GetSupportedFeatures() {
349} 349}
350 350
351bool JoyconDriver::IsInputThreadValid() const { 351bool JoyconDriver::IsInputThreadValid() const {
352 if (!is_connected) { 352 if (!is_connected.load()) {
353 return false; 353 return false;
354 } 354 }
355 if (hidapi_handle->handle == nullptr) { 355 if (hidapi_handle->handle == nullptr) {
@@ -491,7 +491,7 @@ DriverResult JoyconDriver::SetRingConMode() {
491 491
492bool JoyconDriver::IsConnected() const { 492bool JoyconDriver::IsConnected() const {
493 std::scoped_lock lock{mutex}; 493 std::scoped_lock lock{mutex};
494 return is_connected; 494 return is_connected.load();
495} 495}
496 496
497bool JoyconDriver::IsVibrationEnabled() const { 497bool JoyconDriver::IsVibrationEnabled() const {
diff --git a/src/input_common/helpers/joycon_driver.h b/src/input_common/helpers/joycon_driver.h
index e8e65e133..c1e189fa5 100644
--- a/src/input_common/helpers/joycon_driver.h
+++ b/src/input_common/helpers/joycon_driver.h
@@ -3,6 +3,7 @@
3 3
4#pragma once 4#pragma once
5 5
6#include <atomic>
6#include <functional> 7#include <functional>
7#include <mutex> 8#include <mutex>
8#include <span> 9#include <span>
@@ -97,7 +98,7 @@ private:
97 std::unique_ptr<RumbleProtocol> rumble_protocol; 98 std::unique_ptr<RumbleProtocol> rumble_protocol;
98 99
99 // Connection status 100 // Connection status
100 bool is_connected{}; 101 std::atomic<bool> is_connected{};
101 u64 delta_time; 102 u64 delta_time;
102 std::size_t error_counter{}; 103 std::size_t error_counter{};
103 std::shared_ptr<JoyconHandle> hidapi_handle; 104 std::shared_ptr<JoyconHandle> hidapi_handle;
diff --git a/src/input_common/helpers/joycon_protocol/calibration.cpp b/src/input_common/helpers/joycon_protocol/calibration.cpp
index cd30ab869..f6e7e97d5 100644
--- a/src/input_common/helpers/joycon_protocol/calibration.cpp
+++ b/src/input_common/helpers/joycon_protocol/calibration.cpp
@@ -12,10 +12,10 @@ CalibrationProtocol::CalibrationProtocol(std::shared_ptr<JoyconHandle> handle)
12 : JoyconCommonProtocol(std::move(handle)) {} 12 : JoyconCommonProtocol(std::move(handle)) {}
13 13
14DriverResult CalibrationProtocol::GetLeftJoyStickCalibration(JoyStickCalibration& calibration) { 14DriverResult CalibrationProtocol::GetLeftJoyStickCalibration(JoyStickCalibration& calibration) {
15 ScopedSetBlocking sb(this);
15 std::vector<u8> buffer; 16 std::vector<u8> buffer;
16 DriverResult result{DriverResult::Success}; 17 DriverResult result{DriverResult::Success};
17 calibration = {}; 18 calibration = {};
18 SetBlocking();
19 19
20 result = ReadSPI(CalAddr::USER_LEFT_MAGIC, sizeof(u16), buffer); 20 result = ReadSPI(CalAddr::USER_LEFT_MAGIC, sizeof(u16), buffer);
21 21
@@ -44,15 +44,14 @@ DriverResult CalibrationProtocol::GetLeftJoyStickCalibration(JoyStickCalibration
44 // Set a valid default calibration if data is missing 44 // Set a valid default calibration if data is missing
45 ValidateCalibration(calibration); 45 ValidateCalibration(calibration);
46 46
47 SetNonBlocking();
48 return result; 47 return result;
49} 48}
50 49
51DriverResult CalibrationProtocol::GetRightJoyStickCalibration(JoyStickCalibration& calibration) { 50DriverResult CalibrationProtocol::GetRightJoyStickCalibration(JoyStickCalibration& calibration) {
51 ScopedSetBlocking sb(this);
52 std::vector<u8> buffer; 52 std::vector<u8> buffer;
53 DriverResult result{DriverResult::Success}; 53 DriverResult result{DriverResult::Success};
54 calibration = {}; 54 calibration = {};
55 SetBlocking();
56 55
57 result = ReadSPI(CalAddr::USER_RIGHT_MAGIC, sizeof(u16), buffer); 56 result = ReadSPI(CalAddr::USER_RIGHT_MAGIC, sizeof(u16), buffer);
58 57
@@ -81,15 +80,14 @@ DriverResult CalibrationProtocol::GetRightJoyStickCalibration(JoyStickCalibratio
81 // Set a valid default calibration if data is missing 80 // Set a valid default calibration if data is missing
82 ValidateCalibration(calibration); 81 ValidateCalibration(calibration);
83 82
84 SetNonBlocking();
85 return result; 83 return result;
86} 84}
87 85
88DriverResult CalibrationProtocol::GetImuCalibration(MotionCalibration& calibration) { 86DriverResult CalibrationProtocol::GetImuCalibration(MotionCalibration& calibration) {
87 ScopedSetBlocking sb(this);
89 std::vector<u8> buffer; 88 std::vector<u8> buffer;
90 DriverResult result{DriverResult::Success}; 89 DriverResult result{DriverResult::Success};
91 calibration = {}; 90 calibration = {};
92 SetBlocking();
93 91
94 result = ReadSPI(CalAddr::USER_IMU_MAGIC, sizeof(u16), buffer); 92 result = ReadSPI(CalAddr::USER_IMU_MAGIC, sizeof(u16), buffer);
95 93
@@ -124,7 +122,6 @@ DriverResult CalibrationProtocol::GetImuCalibration(MotionCalibration& calibrati
124 122
125 ValidateCalibration(calibration); 123 ValidateCalibration(calibration);
126 124
127 SetNonBlocking();
128 return result; 125 return result;
129} 126}
130 127
diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.cpp b/src/input_common/helpers/joycon_protocol/common_protocol.cpp
index 153a3908c..417d0dcc5 100644
--- a/src/input_common/helpers/joycon_protocol/common_protocol.cpp
+++ b/src/input_common/helpers/joycon_protocol/common_protocol.cpp
@@ -58,9 +58,8 @@ DriverResult JoyconCommonProtocol::CheckDeviceAccess(SDL_hid_device_info* device
58} 58}
59 59
60DriverResult JoyconCommonProtocol::SetReportMode(ReportMode report_mode) { 60DriverResult JoyconCommonProtocol::SetReportMode(ReportMode report_mode) {
61 const std::vector<u8> buffer{static_cast<u8>(report_mode)}; 61 const std::array<u8, 1> buffer{static_cast<u8>(report_mode)};
62 std::vector<u8> output; 62 return SendSubCommand(SubCommand::SET_REPORT_MODE, buffer);
63 return SendSubCommand(SubCommand::SET_REPORT_MODE, buffer, output);
64} 63}
65 64
66DriverResult JoyconCommonProtocol::SendData(std::span<const u8> buffer) { 65DriverResult JoyconCommonProtocol::SendData(std::span<const u8> buffer) {
@@ -120,7 +119,12 @@ DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const
120 return DriverResult::Success; 119 return DriverResult::Success;
121} 120}
122 121
123DriverResult JoyconCommonProtocol::SendMcuCommand(SubCommand sc, std::span<const u8> buffer) { 122DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const u8> buffer) {
123 std::vector<u8> output;
124 return SendSubCommand(sc, buffer, output);
125}
126
127DriverResult JoyconCommonProtocol::SendMCUCommand(SubCommand sc, std::span<const u8> buffer) {
124 std::vector<u8> local_buffer(MaxResponseSize); 128 std::vector<u8> local_buffer(MaxResponseSize);
125 129
126 local_buffer[0] = static_cast<u8>(OutputReport::MCU_DATA); 130 local_buffer[0] = static_cast<u8>(OutputReport::MCU_DATA);
@@ -147,7 +151,7 @@ DriverResult JoyconCommonProtocol::SendVibrationReport(std::span<const u8> buffe
147DriverResult JoyconCommonProtocol::ReadSPI(CalAddr addr, u8 size, std::vector<u8>& output) { 151DriverResult JoyconCommonProtocol::ReadSPI(CalAddr addr, u8 size, std::vector<u8>& output) {
148 constexpr std::size_t MaxTries = 10; 152 constexpr std::size_t MaxTries = 10;
149 std::size_t tries = 0; 153 std::size_t tries = 0;
150 std::vector<u8> buffer = {0x00, 0x00, 0x00, 0x00, size}; 154 std::array<u8, 5> buffer = {0x00, 0x00, 0x00, 0x00, size};
151 std::vector<u8> local_buffer(size + 20); 155 std::vector<u8> local_buffer(size + 20);
152 156
153 buffer[0] = static_cast<u8>(static_cast<u16>(addr) & 0x00FF); 157 buffer[0] = static_cast<u8>(static_cast<u16>(addr) & 0x00FF);
@@ -169,10 +173,8 @@ DriverResult JoyconCommonProtocol::ReadSPI(CalAddr addr, u8 size, std::vector<u8
169} 173}
170 174
171DriverResult JoyconCommonProtocol::EnableMCU(bool enable) { 175DriverResult JoyconCommonProtocol::EnableMCU(bool enable) {
172 std::vector<u8> output; 176 const std::array<u8, 1> mcu_state{static_cast<u8>(enable ? 1 : 0)};
173 177 const auto result = SendSubCommand(SubCommand::SET_MCU_STATE, mcu_state);
174 const std::vector<u8> mcu_state{static_cast<u8>(enable ? 1 : 0)};
175 const auto result = SendSubCommand(SubCommand::SET_MCU_STATE, mcu_state, output);
176 178
177 if (result != DriverResult::Success) { 179 if (result != DriverResult::Success) {
178 LOG_ERROR(Input, "SendMCUData failed with error {}", result); 180 LOG_ERROR(Input, "SendMCUData failed with error {}", result);
@@ -183,13 +185,11 @@ DriverResult JoyconCommonProtocol::EnableMCU(bool enable) {
183 185
184DriverResult JoyconCommonProtocol::ConfigureMCU(const MCUConfig& config) { 186DriverResult JoyconCommonProtocol::ConfigureMCU(const MCUConfig& config) {
185 LOG_DEBUG(Input, "ConfigureMCU"); 187 LOG_DEBUG(Input, "ConfigureMCU");
186 std::vector<u8> output;
187
188 std::array<u8, sizeof(MCUConfig)> config_buffer; 188 std::array<u8, sizeof(MCUConfig)> config_buffer;
189 memcpy(config_buffer.data(), &config, sizeof(MCUConfig)); 189 memcpy(config_buffer.data(), &config, sizeof(MCUConfig));
190 config_buffer[37] = CalculateMCU_CRC8(config_buffer.data() + 1, 36); 190 config_buffer[37] = CalculateMCU_CRC8(config_buffer.data() + 1, 36);
191 191
192 const auto result = SendSubCommand(SubCommand::SET_MCU_CONFIG, config_buffer, output); 192 const auto result = SendSubCommand(SubCommand::SET_MCU_CONFIG, config_buffer);
193 193
194 if (result != DriverResult::Success) { 194 if (result != DriverResult::Success) {
195 LOG_ERROR(Input, "Set MCU config failed with error {}", result); 195 LOG_ERROR(Input, "Set MCU config failed with error {}", result);
diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.h b/src/input_common/helpers/joycon_protocol/common_protocol.h
index 2a3feaf59..903bcf402 100644
--- a/src/input_common/helpers/joycon_protocol/common_protocol.h
+++ b/src/input_common/helpers/joycon_protocol/common_protocol.h
@@ -75,11 +75,18 @@ public:
75 DriverResult SendSubCommand(SubCommand sc, std::span<const u8> buffer, std::vector<u8>& output); 75 DriverResult SendSubCommand(SubCommand sc, std::span<const u8> buffer, std::vector<u8>& output);
76 76
77 /** 77 /**
78 * Sends a sub command to the device and waits for it's reply and ignores the output
79 * @param sc sub command to be send
80 * @param buffer data to be send
81 */
82 DriverResult SendSubCommand(SubCommand sc, std::span<const u8> buffer);
83
84 /**
78 * Sends a mcu command to the device 85 * Sends a mcu command to the device
79 * @param sc sub command to be send 86 * @param sc sub command to be send
80 * @param buffer data to be send 87 * @param buffer data to be send
81 */ 88 */
82 DriverResult SendMcuCommand(SubCommand sc, std::span<const u8> buffer); 89 DriverResult SendMCUCommand(SubCommand sc, std::span<const u8> buffer);
83 90
84 /** 91 /**
85 * Sends vibration data to the joycon 92 * Sends vibration data to the joycon
@@ -150,4 +157,17 @@ private:
150 std::shared_ptr<JoyconHandle> hidapi_handle; 157 std::shared_ptr<JoyconHandle> hidapi_handle;
151}; 158};
152 159
160class ScopedSetBlocking {
161public:
162 explicit ScopedSetBlocking(JoyconCommonProtocol* self) : m_self{self} {
163 m_self->SetBlocking();
164 }
165
166 ~ScopedSetBlocking() {
167 m_self->SetNonBlocking();
168 }
169
170private:
171 JoyconCommonProtocol* m_self{};
172};
153} // namespace InputCommon::Joycon 173} // namespace InputCommon::Joycon
diff --git a/src/input_common/helpers/joycon_protocol/generic_functions.cpp b/src/input_common/helpers/joycon_protocol/generic_functions.cpp
index cbd9ff4f8..52bb8b61a 100644
--- a/src/input_common/helpers/joycon_protocol/generic_functions.cpp
+++ b/src/input_common/helpers/joycon_protocol/generic_functions.cpp
@@ -10,22 +10,18 @@ GenericProtocol::GenericProtocol(std::shared_ptr<JoyconHandle> handle)
10 : JoyconCommonProtocol(std::move(handle)) {} 10 : JoyconCommonProtocol(std::move(handle)) {}
11 11
12DriverResult GenericProtocol::EnablePassiveMode() { 12DriverResult GenericProtocol::EnablePassiveMode() {
13 SetBlocking(); 13 ScopedSetBlocking sb(this);
14 const auto result = SetReportMode(ReportMode::SIMPLE_HID_MODE); 14 return SetReportMode(ReportMode::SIMPLE_HID_MODE);
15 SetNonBlocking();
16 return result;
17} 15}
18 16
19DriverResult GenericProtocol::EnableActiveMode() { 17DriverResult GenericProtocol::EnableActiveMode() {
20 SetBlocking(); 18 ScopedSetBlocking sb(this);
21 const auto result = SetReportMode(ReportMode::STANDARD_FULL_60HZ); 19 return SetReportMode(ReportMode::STANDARD_FULL_60HZ);
22 SetNonBlocking();
23 return result;
24} 20}
25 21
26DriverResult GenericProtocol::GetDeviceInfo(DeviceInfo& device_info) { 22DriverResult GenericProtocol::GetDeviceInfo(DeviceInfo& device_info) {
23 ScopedSetBlocking sb(this);
27 std::vector<u8> output; 24 std::vector<u8> output;
28 SetBlocking();
29 25
30 const auto result = SendSubCommand(SubCommand::REQ_DEV_INFO, {}, output); 26 const auto result = SendSubCommand(SubCommand::REQ_DEV_INFO, {}, output);
31 27
@@ -34,7 +30,6 @@ DriverResult GenericProtocol::GetDeviceInfo(DeviceInfo& device_info) {
34 memcpy(&device_info, output.data(), sizeof(DeviceInfo)); 30 memcpy(&device_info, output.data(), sizeof(DeviceInfo));
35 } 31 }
36 32
37 SetNonBlocking();
38 return result; 33 return result;
39} 34}
40 35
@@ -43,36 +38,30 @@ DriverResult GenericProtocol::GetControllerType(ControllerType& controller_type)
43} 38}
44 39
45DriverResult GenericProtocol::EnableImu(bool enable) { 40DriverResult GenericProtocol::EnableImu(bool enable) {
41 ScopedSetBlocking sb(this);
46 const std::array<u8, 1> buffer{static_cast<u8>(enable ? 1 : 0)}; 42 const std::array<u8, 1> buffer{static_cast<u8>(enable ? 1 : 0)};
47 std::vector<u8> output; 43 return SendSubCommand(SubCommand::ENABLE_IMU, buffer);
48 SetBlocking();
49 const auto result = SendSubCommand(SubCommand::ENABLE_IMU, buffer, output);
50 SetNonBlocking();
51 return result;
52} 44}
53 45
54DriverResult GenericProtocol::SetImuConfig(GyroSensitivity gsen, GyroPerformance gfrec, 46DriverResult GenericProtocol::SetImuConfig(GyroSensitivity gsen, GyroPerformance gfrec,
55 AccelerometerSensitivity asen, 47 AccelerometerSensitivity asen,
56 AccelerometerPerformance afrec) { 48 AccelerometerPerformance afrec) {
49 ScopedSetBlocking sb(this);
57 const std::array<u8, 4> buffer{static_cast<u8>(gsen), static_cast<u8>(asen), 50 const std::array<u8, 4> buffer{static_cast<u8>(gsen), static_cast<u8>(asen),
58 static_cast<u8>(gfrec), static_cast<u8>(afrec)}; 51 static_cast<u8>(gfrec), static_cast<u8>(afrec)};
59 std::vector<u8> output; 52 return SendSubCommand(SubCommand::SET_IMU_SENSITIVITY, buffer);
60 SetBlocking();
61 const auto result = SendSubCommand(SubCommand::SET_IMU_SENSITIVITY, buffer, output);
62 SetNonBlocking();
63 return result;
64} 53}
65 54
66DriverResult GenericProtocol::GetBattery(u32& battery_level) { 55DriverResult GenericProtocol::GetBattery(u32& battery_level) {
56 // This function is meant to request the high resolution battery status
67 battery_level = 0; 57 battery_level = 0;
68 return DriverResult::NotSupported; 58 return DriverResult::NotSupported;
69} 59}
70 60
71DriverResult GenericProtocol::GetColor(Color& color) { 61DriverResult GenericProtocol::GetColor(Color& color) {
62 ScopedSetBlocking sb(this);
72 std::vector<u8> buffer; 63 std::vector<u8> buffer;
73 SetBlocking();
74 const auto result = ReadSPI(CalAddr::COLOR_DATA, 12, buffer); 64 const auto result = ReadSPI(CalAddr::COLOR_DATA, 12, buffer);
75 SetNonBlocking();
76 65
77 color = {}; 66 color = {};
78 if (result == DriverResult::Success) { 67 if (result == DriverResult::Success) {
@@ -86,10 +75,9 @@ DriverResult GenericProtocol::GetColor(Color& color) {
86} 75}
87 76
88DriverResult GenericProtocol::GetSerialNumber(SerialNumber& serial_number) { 77DriverResult GenericProtocol::GetSerialNumber(SerialNumber& serial_number) {
78 ScopedSetBlocking sb(this);
89 std::vector<u8> buffer; 79 std::vector<u8> buffer;
90 SetBlocking();
91 const auto result = ReadSPI(CalAddr::SERIAL_NUMBER, 16, buffer); 80 const auto result = ReadSPI(CalAddr::SERIAL_NUMBER, 16, buffer);
92 SetNonBlocking();
93 81
94 serial_number = {}; 82 serial_number = {};
95 if (result == DriverResult::Success) { 83 if (result == DriverResult::Success) {
@@ -115,14 +103,9 @@ DriverResult GenericProtocol::GetVersionNumber(FirmwareVersion& version) {
115} 103}
116 104
117DriverResult GenericProtocol::SetHomeLight() { 105DriverResult GenericProtocol::SetHomeLight() {
106 ScopedSetBlocking sb(this);
118 static constexpr std::array<u8, 3> buffer{0x0f, 0xf0, 0x00}; 107 static constexpr std::array<u8, 3> buffer{0x0f, 0xf0, 0x00};
119 std::vector<u8> output; 108 return SendSubCommand(SubCommand::SET_HOME_LIGHT, buffer);
120 SetBlocking();
121
122 const auto result = SendSubCommand(SubCommand::SET_HOME_LIGHT, buffer, output);
123
124 SetNonBlocking();
125 return result;
126} 109}
127 110
128DriverResult GenericProtocol::SetLedBusy() { 111DriverResult GenericProtocol::SetLedBusy() {
@@ -130,14 +113,9 @@ DriverResult GenericProtocol::SetLedBusy() {
130} 113}
131 114
132DriverResult GenericProtocol::SetLedPattern(u8 leds) { 115DriverResult GenericProtocol::SetLedPattern(u8 leds) {
116 ScopedSetBlocking sb(this);
133 const std::array<u8, 1> buffer{leds}; 117 const std::array<u8, 1> buffer{leds};
134 std::vector<u8> output; 118 return SendSubCommand(SubCommand::SET_PLAYER_LIGHTS, buffer);
135 SetBlocking();
136
137 const auto result = SendSubCommand(SubCommand::SET_PLAYER_LIGHTS, buffer, output);
138
139 SetNonBlocking();
140 return result;
141} 119}
142 120
143DriverResult GenericProtocol::SetLedBlinkPattern(u8 leds) { 121DriverResult GenericProtocol::SetLedBlinkPattern(u8 leds) {
diff --git a/src/input_common/helpers/joycon_protocol/irs.cpp b/src/input_common/helpers/joycon_protocol/irs.cpp
index 9dfa503c2..09e17bc5b 100644
--- a/src/input_common/helpers/joycon_protocol/irs.cpp
+++ b/src/input_common/helpers/joycon_protocol/irs.cpp
@@ -12,8 +12,8 @@ IrsProtocol::IrsProtocol(std::shared_ptr<JoyconHandle> handle)
12 12
13DriverResult IrsProtocol::EnableIrs() { 13DriverResult IrsProtocol::EnableIrs() {
14 LOG_INFO(Input, "Enable IRS"); 14 LOG_INFO(Input, "Enable IRS");
15 ScopedSetBlocking sb(this);
15 DriverResult result{DriverResult::Success}; 16 DriverResult result{DriverResult::Success};
16 SetBlocking();
17 17
18 if (result == DriverResult::Success) { 18 if (result == DriverResult::Success) {
19 result = SetReportMode(ReportMode::NFC_IR_MODE_60HZ); 19 result = SetReportMode(ReportMode::NFC_IR_MODE_60HZ);
@@ -49,14 +49,13 @@ DriverResult IrsProtocol::EnableIrs() {
49 49
50 is_enabled = true; 50 is_enabled = true;
51 51
52 SetNonBlocking();
53 return result; 52 return result;
54} 53}
55 54
56DriverResult IrsProtocol::DisableIrs() { 55DriverResult IrsProtocol::DisableIrs() {
57 LOG_DEBUG(Input, "Disable IRS"); 56 LOG_DEBUG(Input, "Disable IRS");
57 ScopedSetBlocking sb(this);
58 DriverResult result{DriverResult::Success}; 58 DriverResult result{DriverResult::Success};
59 SetBlocking();
60 59
61 if (result == DriverResult::Success) { 60 if (result == DriverResult::Success) {
62 result = EnableMCU(false); 61 result = EnableMCU(false);
@@ -64,7 +63,6 @@ DriverResult IrsProtocol::DisableIrs() {
64 63
65 is_enabled = false; 64 is_enabled = false;
66 65
67 SetNonBlocking();
68 return result; 66 return result;
69} 67}
70 68
@@ -148,7 +146,7 @@ DriverResult IrsProtocol::ConfigureIrs() {
148 }; 146 };
149 buf_image.resize((static_cast<u8>(fragments) + 1) * 300); 147 buf_image.resize((static_cast<u8>(fragments) + 1) * 300);
150 148
151 std::vector<u8> request_data(sizeof(IrsConfigure)); 149 std::array<u8, sizeof(IrsConfigure)> request_data{};
152 memcpy(request_data.data(), &irs_configuration, sizeof(IrsConfigure)); 150 memcpy(request_data.data(), &irs_configuration, sizeof(IrsConfigure));
153 request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); 151 request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
154 do { 152 do {
@@ -191,7 +189,7 @@ DriverResult IrsProtocol::WriteRegistersStep1() {
191 .crc = {}, 189 .crc = {},
192 }; 190 };
193 191
194 std::vector<u8> request_data(sizeof(IrsWriteRegisters)); 192 std::array<u8, sizeof(IrsWriteRegisters)> request_data{};
195 memcpy(request_data.data(), &irs_registers, sizeof(IrsWriteRegisters)); 193 memcpy(request_data.data(), &irs_registers, sizeof(IrsWriteRegisters));
196 request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); 194 request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
197 195
@@ -208,7 +206,7 @@ DriverResult IrsProtocol::WriteRegistersStep1() {
208 206
209 // First time we need to set the report mode 207 // First time we need to set the report mode
210 if (result == DriverResult::Success && tries == 0) { 208 if (result == DriverResult::Success && tries == 0) {
211 result = SendMcuCommand(SubCommand::SET_REPORT_MODE, mcu_request); 209 result = SendMCUCommand(SubCommand::SET_REPORT_MODE, mcu_request);
212 } 210 }
213 if (result == DriverResult::Success && tries == 0) { 211 if (result == DriverResult::Success && tries == 0) {
214 GetSubCommandResponse(SubCommand::SET_MCU_CONFIG, output); 212 GetSubCommandResponse(SubCommand::SET_MCU_CONFIG, output);
@@ -250,7 +248,7 @@ DriverResult IrsProtocol::WriteRegistersStep2() {
250 .crc = {}, 248 .crc = {},
251 }; 249 };
252 250
253 std::vector<u8> request_data(sizeof(IrsWriteRegisters)); 251 std::array<u8, sizeof(IrsWriteRegisters)> request_data{};
254 memcpy(request_data.data(), &irs_registers, sizeof(IrsWriteRegisters)); 252 memcpy(request_data.data(), &irs_registers, sizeof(IrsWriteRegisters));
255 request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); 253 request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
256 do { 254 do {
@@ -272,7 +270,7 @@ DriverResult IrsProtocol::RequestFrame(u8 frame) {
272 mcu_request[3] = frame; 270 mcu_request[3] = frame;
273 mcu_request[36] = CalculateMCU_CRC8(mcu_request.data(), 36); 271 mcu_request[36] = CalculateMCU_CRC8(mcu_request.data(), 36);
274 mcu_request[37] = 0xFF; 272 mcu_request[37] = 0xFF;
275 return SendMcuCommand(SubCommand::SET_REPORT_MODE, mcu_request); 273 return SendMCUCommand(SubCommand::SET_REPORT_MODE, mcu_request);
276} 274}
277 275
278DriverResult IrsProtocol::ResendFrame(u8 frame) { 276DriverResult IrsProtocol::ResendFrame(u8 frame) {
@@ -282,7 +280,7 @@ DriverResult IrsProtocol::ResendFrame(u8 frame) {
282 mcu_request[3] = 0x0; 280 mcu_request[3] = 0x0;
283 mcu_request[36] = CalculateMCU_CRC8(mcu_request.data(), 36); 281 mcu_request[36] = CalculateMCU_CRC8(mcu_request.data(), 36);
284 mcu_request[37] = 0xFF; 282 mcu_request[37] = 0xFF;
285 return SendMcuCommand(SubCommand::SET_REPORT_MODE, mcu_request); 283 return SendMCUCommand(SubCommand::SET_REPORT_MODE, mcu_request);
286} 284}
287 285
288std::vector<u8> IrsProtocol::GetImage() const { 286std::vector<u8> IrsProtocol::GetImage() const {
diff --git a/src/input_common/helpers/joycon_protocol/joycon_types.h b/src/input_common/helpers/joycon_protocol/joycon_types.h
index 273c8d07d..e2d47349f 100644
--- a/src/input_common/helpers/joycon_protocol/joycon_types.h
+++ b/src/input_common/helpers/joycon_protocol/joycon_types.h
@@ -273,6 +273,18 @@ enum class NFCTagType : u8 {
273 Ntag215 = 0x01, 273 Ntag215 = 0x01,
274}; 274};
275 275
276enum class NFCPages {
277 Block0 = 0,
278 Block45 = 45,
279 Block135 = 135,
280 Block231 = 231,
281};
282
283enum class NFCStatus : u8 {
284 LastPackage = 0x04,
285 TagLost = 0x07,
286};
287
276enum class IrsMode : u8 { 288enum class IrsMode : u8 {
277 None = 0x02, 289 None = 0x02,
278 Moment = 0x03, 290 Moment = 0x03,
diff --git a/src/input_common/helpers/joycon_protocol/nfc.cpp b/src/input_common/helpers/joycon_protocol/nfc.cpp
index 8755e310b..5c0f71722 100644
--- a/src/input_common/helpers/joycon_protocol/nfc.cpp
+++ b/src/input_common/helpers/joycon_protocol/nfc.cpp
@@ -12,8 +12,8 @@ NfcProtocol::NfcProtocol(std::shared_ptr<JoyconHandle> handle)
12 12
13DriverResult NfcProtocol::EnableNfc() { 13DriverResult NfcProtocol::EnableNfc() {
14 LOG_INFO(Input, "Enable NFC"); 14 LOG_INFO(Input, "Enable NFC");
15 ScopedSetBlocking sb(this);
15 DriverResult result{DriverResult::Success}; 16 DriverResult result{DriverResult::Success};
16 SetBlocking();
17 17
18 if (result == DriverResult::Success) { 18 if (result == DriverResult::Success) {
19 result = SetReportMode(ReportMode::NFC_IR_MODE_60HZ); 19 result = SetReportMode(ReportMode::NFC_IR_MODE_60HZ);
@@ -35,14 +35,13 @@ DriverResult NfcProtocol::EnableNfc() {
35 result = ConfigureMCU(config); 35 result = ConfigureMCU(config);
36 } 36 }
37 37
38 SetNonBlocking();
39 return result; 38 return result;
40} 39}
41 40
42DriverResult NfcProtocol::DisableNfc() { 41DriverResult NfcProtocol::DisableNfc() {
43 LOG_DEBUG(Input, "Disable NFC"); 42 LOG_DEBUG(Input, "Disable NFC");
43 ScopedSetBlocking sb(this);
44 DriverResult result{DriverResult::Success}; 44 DriverResult result{DriverResult::Success};
45 SetBlocking();
46 45
47 if (result == DriverResult::Success) { 46 if (result == DriverResult::Success) {
48 result = EnableMCU(false); 47 result = EnableMCU(false);
@@ -50,15 +49,14 @@ DriverResult NfcProtocol::DisableNfc() {
50 49
51 is_enabled = false; 50 is_enabled = false;
52 51
53 SetNonBlocking();
54 return result; 52 return result;
55} 53}
56 54
57DriverResult NfcProtocol::StartNFCPollingMode() { 55DriverResult NfcProtocol::StartNFCPollingMode() {
58 LOG_DEBUG(Input, "Start NFC pooling Mode"); 56 LOG_DEBUG(Input, "Start NFC pooling Mode");
57 ScopedSetBlocking sb(this);
59 DriverResult result{DriverResult::Success}; 58 DriverResult result{DriverResult::Success};
60 TagFoundData tag_data{}; 59 TagFoundData tag_data{};
61 SetBlocking();
62 60
63 if (result == DriverResult::Success) { 61 if (result == DriverResult::Success) {
64 result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::NFC); 62 result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::NFC);
@@ -70,15 +68,14 @@ DriverResult NfcProtocol::StartNFCPollingMode() {
70 is_enabled = true; 68 is_enabled = true;
71 } 69 }
72 70
73 SetNonBlocking();
74 return result; 71 return result;
75} 72}
76 73
77DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) { 74DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) {
78 LOG_DEBUG(Input, "Start NFC pooling Mode"); 75 LOG_DEBUG(Input, "Start NFC pooling Mode");
76 ScopedSetBlocking sb(this);
79 DriverResult result{DriverResult::Success}; 77 DriverResult result{DriverResult::Success};
80 TagFoundData tag_data{}; 78 TagFoundData tag_data{};
81 SetBlocking();
82 79
83 if (result == DriverResult::Success) { 80 if (result == DriverResult::Success) {
84 result = StartPolling(tag_data); 81 result = StartPolling(tag_data);
@@ -96,20 +93,18 @@ DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) {
96 result = GetAmiiboData(data); 93 result = GetAmiiboData(data);
97 } 94 }
98 95
99 SetNonBlocking();
100 return result; 96 return result;
101} 97}
102 98
103bool NfcProtocol::HasAmiibo() { 99bool NfcProtocol::HasAmiibo() {
100 ScopedSetBlocking sb(this);
104 DriverResult result{DriverResult::Success}; 101 DriverResult result{DriverResult::Success};
105 TagFoundData tag_data{}; 102 TagFoundData tag_data{};
106 SetBlocking();
107 103
108 if (result == DriverResult::Success) { 104 if (result == DriverResult::Success) {
109 result = StartPolling(tag_data); 105 result = StartPolling(tag_data);
110 } 106 }
111 107
112 SetNonBlocking();
113 return result == DriverResult::Success; 108 return result == DriverResult::Success;
114} 109}
115 110
@@ -169,55 +164,53 @@ DriverResult NfcProtocol::ReadTag(const TagFoundData& data) {
169 LOG_INFO(Input, "Tag detected, type={}, uuid={}", data.type, uuid_string); 164 LOG_INFO(Input, "Tag detected, type={}, uuid={}", data.type, uuid_string);
170 165
171 tries = 0; 166 tries = 0;
172 std::size_t ntag_pages = 0; 167 NFCPages ntag_pages = NFCPages::Block0;
173 // Read Tag data 168 // Read Tag data
174loop1:
175 while (true) { 169 while (true) {
176 auto result = SendReadAmiiboRequest(output, ntag_pages); 170 auto result = SendReadAmiiboRequest(output, ntag_pages);
171 const auto mcu_report = static_cast<MCUReport>(output[49]);
172 const auto nfc_status = static_cast<NFCStatus>(output[56]);
177 173
178 int attempt = 0; 174 if (result != DriverResult::Success) {
179 while (1) { 175 return result;
180 if (attempt != 0) { 176 }
181 result = GetMCUDataResponse(ReportMode::NFC_IR_MODE_60HZ, output); 177
178 if ((mcu_report == MCUReport::NFCReadData || mcu_report == MCUReport::NFCState) &&
179 nfc_status == NFCStatus::TagLost) {
180 return DriverResult::ErrorReadingData;
181 }
182
183 if (mcu_report == MCUReport::NFCReadData && output[51] == 0x07 && output[52] == 0x01) {
184 if (data.type != 2) {
185 continue;
182 } 186 }
183 if ((output[49] == 0x3a || output[49] == 0x2a) && output[56] == 0x07) { 187 switch (output[74]) {
188 case 0:
189 ntag_pages = NFCPages::Block135;
190 break;
191 case 3:
192 ntag_pages = NFCPages::Block45;
193 break;
194 case 4:
195 ntag_pages = NFCPages::Block231;
196 break;
197 default:
184 return DriverResult::ErrorReadingData; 198 return DriverResult::ErrorReadingData;
185 } 199 }
186 if (output[49] == 0x3a && output[51] == 0x07 && output[52] == 0x01) { 200 continue;
187 if (data.type != 2) {
188 goto loop1;
189 }
190 switch (output[74]) {
191 case 0:
192 ntag_pages = 135;
193 break;
194 case 3:
195 ntag_pages = 45;
196 break;
197 case 4:
198 ntag_pages = 231;
199 break;
200 default:
201 return DriverResult::ErrorReadingData;
202 }
203 goto loop1;
204 }
205 if (output[49] == 0x2a && output[56] == 0x04) {
206 // finished
207 SendStopPollingRequest(output);
208 return DriverResult::Success;
209 }
210 if (output[49] == 0x2a) {
211 goto loop1;
212 }
213 if (attempt++ > 6) {
214 goto loop1;
215 }
216 } 201 }
217 202
218 if (result != DriverResult::Success) { 203 if (mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) {
219 return result; 204 // finished
205 SendStopPollingRequest(output);
206 return DriverResult::Success;
207 }
208
209 // Ignore other state reports
210 if (mcu_report == MCUReport::NFCState) {
211 continue;
220 } 212 }
213
221 if (tries++ > timeout_limit) { 214 if (tries++ > timeout_limit) {
222 return DriverResult::Timeout; 215 return DriverResult::Timeout;
223 } 216 }
@@ -231,47 +224,44 @@ DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) {
231 std::vector<u8> output; 224 std::vector<u8> output;
232 std::size_t tries = 0; 225 std::size_t tries = 0;
233 226
234 std::size_t ntag_pages = 135; 227 NFCPages ntag_pages = NFCPages::Block135;
235 std::size_t ntag_buffer_pos = 0; 228 std::size_t ntag_buffer_pos = 0;
236 // Read Tag data 229 // Read Tag data
237loop1:
238 while (true) { 230 while (true) {
239 auto result = SendReadAmiiboRequest(output, ntag_pages); 231 auto result = SendReadAmiiboRequest(output, ntag_pages);
232 const auto mcu_report = static_cast<MCUReport>(output[49]);
233 const auto nfc_status = static_cast<NFCStatus>(output[56]);
240 234
241 int attempt = 0; 235 if (result != DriverResult::Success) {
242 while (1) { 236 return result;
243 if (attempt != 0) { 237 }
244 result = GetMCUDataResponse(ReportMode::NFC_IR_MODE_60HZ, output); 238
245 } 239 if ((mcu_report == MCUReport::NFCReadData || mcu_report == MCUReport::NFCState) &&
246 if ((output[49] == 0x3a || output[49] == 0x2a) && output[56] == 0x07) { 240 nfc_status == NFCStatus::TagLost) {
247 return DriverResult::ErrorReadingData; 241 return DriverResult::ErrorReadingData;
248 } 242 }
249 if (output[49] == 0x3a && output[51] == 0x07) { 243
250 std::size_t payload_size = (output[54] << 8 | output[55]) & 0x7FF; 244 if (mcu_report == MCUReport::NFCReadData && output[51] == 0x07) {
251 if (output[52] == 0x01) { 245 std::size_t payload_size = (output[54] << 8 | output[55]) & 0x7FF;
252 memcpy(ntag_data.data() + ntag_buffer_pos, output.data() + 116, 246 if (output[52] == 0x01) {
253 payload_size - 60); 247 memcpy(ntag_data.data() + ntag_buffer_pos, output.data() + 116, payload_size - 60);
254 ntag_buffer_pos += payload_size - 60; 248 ntag_buffer_pos += payload_size - 60;
255 } else { 249 } else {
256 memcpy(ntag_data.data() + ntag_buffer_pos, output.data() + 56, payload_size); 250 memcpy(ntag_data.data() + ntag_buffer_pos, output.data() + 56, payload_size);
257 }
258 goto loop1;
259 }
260 if (output[49] == 0x2a && output[56] == 0x04) {
261 LOG_INFO(Input, "Finished reading amiibo");
262 return DriverResult::Success;
263 }
264 if (output[49] == 0x2a) {
265 goto loop1;
266 }
267 if (attempt++ > 4) {
268 goto loop1;
269 } 251 }
252 continue;
270 } 253 }
271 254
272 if (result != DriverResult::Success) { 255 if (mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) {
273 return result; 256 LOG_INFO(Input, "Finished reading amiibo");
257 return DriverResult::Success;
258 }
259
260 // Ignore other state reports
261 if (mcu_report == MCUReport::NFCState) {
262 continue;
274 } 263 }
264
275 if (tries++ > timeout_limit) { 265 if (tries++ > timeout_limit) {
276 return DriverResult::Timeout; 266 return DriverResult::Timeout;
277 } 267 }
@@ -298,7 +288,7 @@ DriverResult NfcProtocol::SendStartPollingRequest(std::vector<u8>& output) {
298 .crc = {}, 288 .crc = {},
299 }; 289 };
300 290
301 std::vector<u8> request_data(sizeof(NFCRequestState)); 291 std::array<u8, sizeof(NFCRequestState)> request_data{};
302 memcpy(request_data.data(), &request, sizeof(NFCRequestState)); 292 memcpy(request_data.data(), &request, sizeof(NFCRequestState));
303 request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); 293 request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
304 return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); 294 return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output);
@@ -315,7 +305,7 @@ DriverResult NfcProtocol::SendStopPollingRequest(std::vector<u8>& output) {
315 .crc = {}, 305 .crc = {},
316 }; 306 };
317 307
318 std::vector<u8> request_data(sizeof(NFCRequestState)); 308 std::array<u8, sizeof(NFCRequestState)> request_data{};
319 memcpy(request_data.data(), &request, sizeof(NFCRequestState)); 309 memcpy(request_data.data(), &request, sizeof(NFCRequestState));
320 request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); 310 request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
321 return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); 311 return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output);
@@ -338,7 +328,7 @@ DriverResult NfcProtocol::SendStartWaitingRecieveRequest(std::vector<u8>& output
338 return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); 328 return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output);
339} 329}
340 330
341DriverResult NfcProtocol::SendReadAmiiboRequest(std::vector<u8>& output, std::size_t ntag_pages) { 331DriverResult NfcProtocol::SendReadAmiiboRequest(std::vector<u8>& output, NFCPages ntag_pages) {
342 NFCRequestState request{ 332 NFCRequestState request{
343 .sub_command = MCUSubCommand::ReadDeviceMode, 333 .sub_command = MCUSubCommand::ReadDeviceMode,
344 .command_argument = NFCReadCommand::Ntag, 334 .command_argument = NFCReadCommand::Ntag,
@@ -357,20 +347,19 @@ DriverResult NfcProtocol::SendReadAmiiboRequest(std::vector<u8>& output, std::si
357 .crc = {}, 347 .crc = {},
358 }; 348 };
359 349
360 std::vector<u8> request_data(sizeof(NFCRequestState)); 350 std::array<u8, sizeof(NFCRequestState)> request_data{};
361 memcpy(request_data.data(), &request, sizeof(NFCRequestState)); 351 memcpy(request_data.data(), &request, sizeof(NFCRequestState));
362 request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); 352 request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
363 return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); 353 return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output);
364} 354}
365 355
366NFCReadBlockCommand NfcProtocol::GetReadBlockCommand(std::size_t pages) const { 356NFCReadBlockCommand NfcProtocol::GetReadBlockCommand(NFCPages pages) const {
367 if (pages == 0) { 357 switch (pages) {
358 case NFCPages::Block0:
368 return { 359 return {
369 .block_count = 1, 360 .block_count = 1,
370 }; 361 };
371 } 362 case NFCPages::Block45:
372
373 if (pages == 45) {
374 return { 363 return {
375 .block_count = 1, 364 .block_count = 1,
376 .blocks = 365 .blocks =
@@ -378,9 +367,7 @@ NFCReadBlockCommand NfcProtocol::GetReadBlockCommand(std::size_t pages) const {
378 NFCReadBlock{0x00, 0x2C}, 367 NFCReadBlock{0x00, 0x2C},
379 }, 368 },
380 }; 369 };
381 } 370 case NFCPages::Block135:
382
383 if (pages == 135) {
384 return { 371 return {
385 .block_count = 3, 372 .block_count = 3,
386 .blocks = 373 .blocks =
@@ -390,9 +377,7 @@ NFCReadBlockCommand NfcProtocol::GetReadBlockCommand(std::size_t pages) const {
390 {0x78, 0x86}, 377 {0x78, 0x86},
391 }, 378 },
392 }; 379 };
393 } 380 case NFCPages::Block231:
394
395 if (pages == 231) {
396 return { 381 return {
397 .block_count = 4, 382 .block_count = 4,
398 .blocks = 383 .blocks =
@@ -403,9 +388,9 @@ NFCReadBlockCommand NfcProtocol::GetReadBlockCommand(std::size_t pages) const {
403 {0xb4, 0xe6}, 388 {0xb4, 0xe6},
404 }, 389 },
405 }; 390 };
406 } 391 default:
407 392 return {};
408 return {}; 393 };
409} 394}
410 395
411bool NfcProtocol::IsEnabled() const { 396bool NfcProtocol::IsEnabled() const {
diff --git a/src/input_common/helpers/joycon_protocol/nfc.h b/src/input_common/helpers/joycon_protocol/nfc.h
index 5cb0e5a65..e63665aa9 100644
--- a/src/input_common/helpers/joycon_protocol/nfc.h
+++ b/src/input_common/helpers/joycon_protocol/nfc.h
@@ -51,9 +51,9 @@ private:
51 51
52 DriverResult SendStartWaitingRecieveRequest(std::vector<u8>& output); 52 DriverResult SendStartWaitingRecieveRequest(std::vector<u8>& output);
53 53
54 DriverResult SendReadAmiiboRequest(std::vector<u8>& output, std::size_t ntag_pages); 54 DriverResult SendReadAmiiboRequest(std::vector<u8>& output, NFCPages ntag_pages);
55 55
56 NFCReadBlockCommand GetReadBlockCommand(std::size_t pages) const; 56 NFCReadBlockCommand GetReadBlockCommand(NFCPages pages) const;
57 57
58 bool is_enabled{}; 58 bool is_enabled{};
59}; 59};
diff --git a/src/input_common/helpers/joycon_protocol/poller.cpp b/src/input_common/helpers/joycon_protocol/poller.cpp
index 940b20b7f..7f8e093fa 100644
--- a/src/input_common/helpers/joycon_protocol/poller.cpp
+++ b/src/input_common/helpers/joycon_protocol/poller.cpp
@@ -224,9 +224,9 @@ void JoyconPoller::UpdatePasiveLeftPadInput(const InputReportPassive& input) {
224 Joycon::PasivePadButton::StickL, 224 Joycon::PasivePadButton::StickL,
225 }; 225 };
226 226
227 for (std::size_t i = 0; i < left_buttons.size(); ++i) { 227 for (auto left_button : left_buttons) {
228 const bool button_status = (input.button_input & static_cast<u32>(left_buttons[i])) != 0; 228 const bool button_status = (input.button_input & static_cast<u32>(left_button)) != 0;
229 const int button = static_cast<int>(left_buttons[i]); 229 const int button = static_cast<int>(left_button);
230 callbacks.on_button_data(button, button_status); 230 callbacks.on_button_data(button, button_status);
231 } 231 }
232} 232}
@@ -241,9 +241,9 @@ void JoyconPoller::UpdatePasiveRightPadInput(const InputReportPassive& input) {
241 Joycon::PasivePadButton::StickR, 241 Joycon::PasivePadButton::StickR,
242 }; 242 };
243 243
244 for (std::size_t i = 0; i < right_buttons.size(); ++i) { 244 for (auto right_button : right_buttons) {
245 const bool button_status = (input.button_input & static_cast<u32>(right_buttons[i])) != 0; 245 const bool button_status = (input.button_input & static_cast<u32>(right_button)) != 0;
246 const int button = static_cast<int>(right_buttons[i]); 246 const int button = static_cast<int>(right_button);
247 callbacks.on_button_data(button, button_status); 247 callbacks.on_button_data(button, button_status);
248 } 248 }
249} 249}
@@ -259,9 +259,9 @@ void JoyconPoller::UpdatePasiveProPadInput(const InputReportPassive& input) {
259 Joycon::PasivePadButton::StickL, Joycon::PasivePadButton::StickR, 259 Joycon::PasivePadButton::StickL, Joycon::PasivePadButton::StickR,
260 }; 260 };
261 261
262 for (std::size_t i = 0; i < pro_buttons.size(); ++i) { 262 for (auto pro_button : pro_buttons) {
263 const bool button_status = (input.button_input & static_cast<u32>(pro_buttons[i])) != 0; 263 const bool button_status = (input.button_input & static_cast<u32>(pro_button)) != 0;
264 const int button = static_cast<int>(pro_buttons[i]); 264 const int button = static_cast<int>(pro_button);
265 callbacks.on_button_data(button, button_status); 265 callbacks.on_button_data(button, button_status);
266 } 266 }
267} 267}
diff --git a/src/input_common/helpers/joycon_protocol/ringcon.cpp b/src/input_common/helpers/joycon_protocol/ringcon.cpp
index 8adad57dd..12f81309e 100644
--- a/src/input_common/helpers/joycon_protocol/ringcon.cpp
+++ b/src/input_common/helpers/joycon_protocol/ringcon.cpp
@@ -11,8 +11,8 @@ RingConProtocol::RingConProtocol(std::shared_ptr<JoyconHandle> handle)
11 11
12DriverResult RingConProtocol::EnableRingCon() { 12DriverResult RingConProtocol::EnableRingCon() {
13 LOG_DEBUG(Input, "Enable Ringcon"); 13 LOG_DEBUG(Input, "Enable Ringcon");
14 ScopedSetBlocking sb(this);
14 DriverResult result{DriverResult::Success}; 15 DriverResult result{DriverResult::Success};
15 SetBlocking();
16 16
17 if (result == DriverResult::Success) { 17 if (result == DriverResult::Success) {
18 result = SetReportMode(ReportMode::STANDARD_FULL_60HZ); 18 result = SetReportMode(ReportMode::STANDARD_FULL_60HZ);
@@ -30,14 +30,13 @@ DriverResult RingConProtocol::EnableRingCon() {
30 result = ConfigureMCU(config); 30 result = ConfigureMCU(config);
31 } 31 }
32 32
33 SetNonBlocking();
34 return result; 33 return result;
35} 34}
36 35
37DriverResult RingConProtocol::DisableRingCon() { 36DriverResult RingConProtocol::DisableRingCon() {
38 LOG_DEBUG(Input, "Disable RingCon"); 37 LOG_DEBUG(Input, "Disable RingCon");
38 ScopedSetBlocking sb(this);
39 DriverResult result{DriverResult::Success}; 39 DriverResult result{DriverResult::Success};
40 SetBlocking();
41 40
42 if (result == DriverResult::Success) { 41 if (result == DriverResult::Success) {
43 result = EnableMCU(false); 42 result = EnableMCU(false);
@@ -45,15 +44,14 @@ DriverResult RingConProtocol::DisableRingCon() {
45 44
46 is_enabled = false; 45 is_enabled = false;
47 46
48 SetNonBlocking();
49 return result; 47 return result;
50} 48}
51 49
52DriverResult RingConProtocol::StartRingconPolling() { 50DriverResult RingConProtocol::StartRingconPolling() {
53 LOG_DEBUG(Input, "Enable Ringcon"); 51 LOG_DEBUG(Input, "Enable Ringcon");
54 bool is_connected = false; 52 ScopedSetBlocking sb(this);
55 DriverResult result{DriverResult::Success}; 53 DriverResult result{DriverResult::Success};
56 SetBlocking(); 54 bool is_connected = false;
57 55
58 if (result == DriverResult::Success) { 56 if (result == DriverResult::Success) {
59 result = IsRingConnected(is_connected); 57 result = IsRingConnected(is_connected);
@@ -66,13 +64,13 @@ DriverResult RingConProtocol::StartRingconPolling() {
66 is_enabled = true; 64 is_enabled = true;
67 } 65 }
68 66
69 SetNonBlocking();
70 return result; 67 return result;
71} 68}
72 69
73DriverResult RingConProtocol::IsRingConnected(bool& is_connected) { 70DriverResult RingConProtocol::IsRingConnected(bool& is_connected) {
74 LOG_DEBUG(Input, "IsRingConnected"); 71 LOG_DEBUG(Input, "IsRingConnected");
75 constexpr std::size_t max_tries = 28; 72 constexpr std::size_t max_tries = 28;
73 constexpr u8 ring_controller_id = 0x20;
76 std::vector<u8> output; 74 std::vector<u8> output;
77 std::size_t tries = 0; 75 std::size_t tries = 0;
78 is_connected = false; 76 is_connected = false;
@@ -88,7 +86,7 @@ DriverResult RingConProtocol::IsRingConnected(bool& is_connected) {
88 if (tries++ >= max_tries) { 86 if (tries++ >= max_tries) {
89 return DriverResult::NoDeviceDetected; 87 return DriverResult::NoDeviceDetected;
90 } 88 }
91 } while (output[14] != 0x59 || output[16] != 0x20); 89 } while (output[16] != ring_controller_id);
92 90
93 is_connected = true; 91 is_connected = true;
94 return DriverResult::Success; 92 return DriverResult::Success;
@@ -96,30 +94,20 @@ DriverResult RingConProtocol::IsRingConnected(bool& is_connected) {
96 94
97DriverResult RingConProtocol::ConfigureRing() { 95DriverResult RingConProtocol::ConfigureRing() {
98 LOG_DEBUG(Input, "ConfigureRing"); 96 LOG_DEBUG(Input, "ConfigureRing");
99 constexpr std::size_t max_tries = 28;
100 DriverResult result{DriverResult::Success};
101 std::vector<u8> output;
102 std::size_t tries = 0;
103 97
104 static constexpr std::array<u8, 37> ring_config{ 98 static constexpr std::array<u8, 37> ring_config{
105 0x06, 0x03, 0x25, 0x06, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x16, 0xED, 0x34, 0x36, 99 0x06, 0x03, 0x25, 0x06, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x16, 0xED, 0x34, 0x36,
106 0x00, 0x00, 0x00, 0x0A, 0x64, 0x0B, 0xE6, 0xA9, 0x22, 0x00, 0x00, 0x04, 0x00, 100 0x00, 0x00, 0x00, 0x0A, 0x64, 0x0B, 0xE6, 0xA9, 0x22, 0x00, 0x00, 0x04, 0x00,
107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xA8, 0xE1, 0x34, 0x36}; 101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xA8, 0xE1, 0x34, 0x36};
108 do {
109 result = SendSubCommand(SubCommand::UNKNOWN_RINGCON3, ring_config, output);
110 102
111 if (result != DriverResult::Success) { 103 const DriverResult result = SendSubCommand(SubCommand::UNKNOWN_RINGCON3, ring_config);
112 return result;
113 }
114 if (tries++ >= max_tries) {
115 return DriverResult::NoDeviceDetected;
116 }
117 } while (output[14] != 0x5C);
118 104
119 static constexpr std::array<u8, 4> ringcon_data{0x04, 0x01, 0x01, 0x02}; 105 if (result != DriverResult::Success) {
120 result = SendSubCommand(SubCommand::UNKNOWN_RINGCON2, ringcon_data, output); 106 return result;
107 }
121 108
122 return result; 109 static constexpr std::array<u8, 4> ringcon_data{0x04, 0x01, 0x01, 0x02};
110 return SendSubCommand(SubCommand::UNKNOWN_RINGCON2, ringcon_data);
123} 111}
124 112
125bool RingConProtocol::IsEnabled() const { 113bool RingConProtocol::IsEnabled() const {
diff --git a/src/input_common/helpers/joycon_protocol/rumble.cpp b/src/input_common/helpers/joycon_protocol/rumble.cpp
index fad67a94b..63b60c946 100644
--- a/src/input_common/helpers/joycon_protocol/rumble.cpp
+++ b/src/input_common/helpers/joycon_protocol/rumble.cpp
@@ -14,12 +14,9 @@ RumbleProtocol::RumbleProtocol(std::shared_ptr<JoyconHandle> handle)
14 14
15DriverResult RumbleProtocol::EnableRumble(bool is_enabled) { 15DriverResult RumbleProtocol::EnableRumble(bool is_enabled) {
16 LOG_DEBUG(Input, "Enable Rumble"); 16 LOG_DEBUG(Input, "Enable Rumble");
17 ScopedSetBlocking sb(this);
17 const std::array<u8, 1> buffer{static_cast<u8>(is_enabled ? 1 : 0)}; 18 const std::array<u8, 1> buffer{static_cast<u8>(is_enabled ? 1 : 0)};
18 std::vector<u8> output; 19 return SendSubCommand(SubCommand::ENABLE_VIBRATION, buffer);
19 SetBlocking();
20 const auto result = SendSubCommand(SubCommand::ENABLE_VIBRATION, buffer, output);
21 SetNonBlocking();
22 return result;
23} 20}
24 21
25DriverResult RumbleProtocol::SendVibration(const VibrationValue& vibration) { 22DriverResult RumbleProtocol::SendVibration(const VibrationValue& vibration) {
@@ -66,9 +63,9 @@ u8 RumbleProtocol::EncodeLowFrequency(f32 frequency) const {
66} 63}
67 64
68u8 RumbleProtocol::EncodeHighAmplitude(f32 amplitude) const { 65u8 RumbleProtocol::EncodeHighAmplitude(f32 amplitude) const {
69 /* More information about these values can be found here: 66 // More information about these values can be found here:
70 * https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md 67 // https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md
71 */ 68
72 static constexpr std::array<std::pair<f32, int>, 101> high_fequency_amplitude{ 69 static constexpr std::array<std::pair<f32, int>, 101> high_fequency_amplitude{
73 std::pair<f32, int>{0.0f, 0x0}, 70 std::pair<f32, int>{0.0f, 0x0},
74 {0.01f, 0x2}, 71 {0.01f, 0x2},
@@ -183,9 +180,9 @@ u8 RumbleProtocol::EncodeHighAmplitude(f32 amplitude) const {
183} 180}
184 181
185u16 RumbleProtocol::EncodeLowAmplitude(f32 amplitude) const { 182u16 RumbleProtocol::EncodeLowAmplitude(f32 amplitude) const {
186 /* More information about these values can be found here: 183 // More information about these values can be found here:
187 * https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md 184 // https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md
188 */ 185
189 static constexpr std::array<std::pair<f32, int>, 101> high_fequency_amplitude{ 186 static constexpr std::array<std::pair<f32, int>, 101> high_fequency_amplitude{
190 std::pair<f32, int>{0.0f, 0x0040}, 187 std::pair<f32, int>{0.0f, 0x0040},
191 {0.01f, 0x8040}, 188 {0.01f, 0x8040},