early-access version 3319

This commit is contained in:
pineappleEA 2023-01-20 05:15:18 +01:00
parent 63ca092a91
commit e3c75c4723
12 changed files with 181 additions and 237 deletions

View file

@ -1,7 +1,7 @@
yuzu emulator early access yuzu emulator early access
============= =============
This is the source code for early-access 3317. This is the source code for early-access 3319.
## Legal Notice ## Legal Notice

View file

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm> #include <algorithm>
#include <common/scope_exit.h>
#include "common/polyfill_ranges.h" #include "common/polyfill_ranges.h"
#include "common/thread.h" #include "common/thread.h"
@ -834,17 +835,21 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback,
if (index >= controller.stick_values.size()) { if (index >= controller.stick_values.size()) {
return; return;
} }
std::unique_lock lock{mutex}; auto trigger_guard =
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Stick, !is_configuring); });
std::scoped_lock lock{mutex};
const auto stick_value = TransformToStick(callback); const auto stick_value = TransformToStick(callback);
// Only read stick values that have the same uuid or are over the threshold to avoid flapping // Only read stick values that have the same uuid or are over the threshold to avoid flapping
if (controller.stick_values[index].uuid != uuid) { if (controller.stick_values[index].uuid != uuid) {
const bool is_tas = uuid == TAS_UUID; const bool is_tas = uuid == TAS_UUID;
if (is_tas && stick_value.x.value == 0 && stick_value.y.value == 0) { if (is_tas && stick_value.x.value == 0 && stick_value.y.value == 0) {
trigger_guard.Cancel();
return; return;
} }
if (!is_tas && !stick_value.down && !stick_value.up && !stick_value.left && if (!is_tas && !stick_value.down && !stick_value.up && !stick_value.left &&
!stick_value.right) { !stick_value.right) {
trigger_guard.Cancel();
return; return;
} }
} }
@ -855,8 +860,6 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback,
if (is_configuring) { if (is_configuring) {
controller.analog_stick_state.left = {}; controller.analog_stick_state.left = {};
controller.analog_stick_state.right = {}; controller.analog_stick_state.right = {};
lock.unlock();
TriggerOnChange(ControllerTriggerType::Stick, false);
return; return;
} }
@ -881,9 +884,6 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback,
controller.npad_button_state.stick_r_down.Assign(controller.stick_values[index].down); controller.npad_button_state.stick_r_down.Assign(controller.stick_values[index].down);
break; break;
} }
lock.unlock();
TriggerOnChange(ControllerTriggerType::Stick, true);
} }
void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callback, void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callback,
@ -891,7 +891,9 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac
if (index >= controller.trigger_values.size()) { if (index >= controller.trigger_values.size()) {
return; return;
} }
std::unique_lock lock{mutex}; auto trigger_guard =
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Trigger, !is_configuring); });
std::scoped_lock lock{mutex};
const auto trigger_value = TransformToTrigger(callback); const auto trigger_value = TransformToTrigger(callback);
// Only read trigger values that have the same uuid or are pressed once // Only read trigger values that have the same uuid or are pressed once
@ -907,13 +909,12 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac
if (is_configuring) { if (is_configuring) {
controller.gc_trigger_state.left = 0; controller.gc_trigger_state.left = 0;
controller.gc_trigger_state.right = 0; controller.gc_trigger_state.right = 0;
lock.unlock();
TriggerOnChange(ControllerTriggerType::Trigger, false);
return; return;
} }
// Only GC controllers have analog triggers // Only GC controllers have analog triggers
if (npad_type != NpadStyleIndex::GameCube) { if (npad_type != NpadStyleIndex::GameCube) {
trigger_guard.Cancel();
return; return;
} }
@ -930,9 +931,6 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac
controller.npad_button_state.zr.Assign(trigger.pressed.value); controller.npad_button_state.zr.Assign(trigger.pressed.value);
break; break;
} }
lock.unlock();
TriggerOnChange(ControllerTriggerType::Trigger, true);
} }
void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback, void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback,
@ -940,7 +938,8 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback
if (index >= controller.motion_values.size()) { if (index >= controller.motion_values.size()) {
return; return;
} }
std::unique_lock lock{mutex}; SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Motion, !is_configuring); });
std::scoped_lock lock{mutex};
auto& raw_status = controller.motion_values[index].raw_status; auto& raw_status = controller.motion_values[index].raw_status;
auto& emulated = controller.motion_values[index].emulated; auto& emulated = controller.motion_values[index].emulated;
@ -961,8 +960,6 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback
force_update_motion = raw_status.force_update; force_update_motion = raw_status.force_update;
if (is_configuring) { if (is_configuring) {
lock.unlock();
TriggerOnChange(ControllerTriggerType::Motion, false);
return; return;
} }
@ -972,9 +969,6 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback
motion.rotation = emulated.GetRotations(); motion.rotation = emulated.GetRotations();
motion.orientation = emulated.GetOrientation(); motion.orientation = emulated.GetOrientation();
motion.is_at_rest = !emulated.IsMoving(motion_sensitivity); motion.is_at_rest = !emulated.IsMoving(motion_sensitivity);
lock.unlock();
TriggerOnChange(ControllerTriggerType::Motion, true);
} }
void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback, void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback,
@ -982,16 +976,17 @@ void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback
if (index >= controller.color_values.size()) { if (index >= controller.color_values.size()) {
return; return;
} }
std::unique_lock lock{mutex}; auto trigger_guard =
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Color, !is_configuring); });
std::scoped_lock lock{mutex};
controller.color_values[index] = TransformToColor(callback); controller.color_values[index] = TransformToColor(callback);
if (is_configuring) { if (is_configuring) {
lock.unlock();
TriggerOnChange(ControllerTriggerType::Color, false);
return; return;
} }
if (controller.color_values[index].body == 0) { if (controller.color_values[index].body == 0) {
trigger_guard.Cancel();
return; return;
} }
@ -1024,9 +1019,6 @@ void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback
break; break;
} }
} }
lock.unlock();
TriggerOnChange(ControllerTriggerType::Color, true);
} }
void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callback, void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callback,
@ -1034,12 +1026,11 @@ void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callbac
if (index >= controller.battery_values.size()) { if (index >= controller.battery_values.size()) {
return; return;
} }
std::unique_lock lock{mutex}; SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Battery, !is_configuring); });
std::scoped_lock lock{mutex};
controller.battery_values[index] = TransformToBattery(callback); controller.battery_values[index] = TransformToBattery(callback);
if (is_configuring) { if (is_configuring) {
lock.unlock();
TriggerOnChange(ControllerTriggerType::Battery, false);
return; return;
} }
@ -1095,18 +1086,14 @@ void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callbac
}; };
break; break;
} }
lock.unlock();
TriggerOnChange(ControllerTriggerType::Battery, true);
} }
void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback) { void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback) {
std::unique_lock lock{mutex}; SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::IrSensor, !is_configuring); });
std::scoped_lock lock{mutex};
controller.camera_values = TransformToCamera(callback); controller.camera_values = TransformToCamera(callback);
if (is_configuring) { if (is_configuring) {
lock.unlock();
TriggerOnChange(ControllerTriggerType::IrSensor, false);
return; return;
} }
@ -1114,36 +1101,28 @@ void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback
controller.camera_state.format = controller.camera_state.format =
static_cast<Core::IrSensor::ImageTransferProcessorFormat>(controller.camera_values.format); static_cast<Core::IrSensor::ImageTransferProcessorFormat>(controller.camera_values.format);
controller.camera_state.data = controller.camera_values.data; controller.camera_state.data = controller.camera_values.data;
lock.unlock();
TriggerOnChange(ControllerTriggerType::IrSensor, true);
} }
void EmulatedController::SetRingAnalog(const Common::Input::CallbackStatus& callback) { void EmulatedController::SetRingAnalog(const Common::Input::CallbackStatus& callback) {
std::unique_lock lock{mutex}; SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::RingController, !is_configuring); });
std::scoped_lock lock{mutex};
const auto force_value = TransformToStick(callback); const auto force_value = TransformToStick(callback);
controller.ring_analog_value = force_value.x; controller.ring_analog_value = force_value.x;
if (is_configuring) { if (is_configuring) {
lock.unlock();
TriggerOnChange(ControllerTriggerType::RingController, false);
return; return;
} }
controller.ring_analog_state.force = force_value.x.value; controller.ring_analog_state.force = force_value.x.value;
lock.unlock();
TriggerOnChange(ControllerTriggerType::RingController, true);
} }
void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) { void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) {
std::unique_lock lock{mutex}; SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Nfc, !is_configuring); });
std::scoped_lock lock{mutex};
controller.nfc_values = TransformToNfc(callback); controller.nfc_values = TransformToNfc(callback);
if (is_configuring) { if (is_configuring) {
lock.unlock();
TriggerOnChange(ControllerTriggerType::Nfc, false);
return; return;
} }
@ -1151,9 +1130,6 @@ void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) {
controller.nfc_values.state, controller.nfc_values.state,
controller.nfc_values.data, controller.nfc_values.data,
}; };
lock.unlock();
TriggerOnChange(ControllerTriggerType::Nfc, true);
} }
bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) { bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) {
@ -1412,39 +1388,35 @@ void EmulatedController::Connect(bool use_temporary_value) {
return; return;
} }
std::unique_lock lock{mutex}; auto trigger_guard =
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Connected, !is_configuring); });
std::scoped_lock lock{mutex};
if (is_configuring) { if (is_configuring) {
tmp_is_connected = true; tmp_is_connected = true;
lock.unlock();
TriggerOnChange(ControllerTriggerType::Connected, false);
return; return;
} }
if (is_connected) { if (is_connected) {
trigger_guard.Cancel();
return; return;
} }
is_connected = true; is_connected = true;
lock.unlock();
TriggerOnChange(ControllerTriggerType::Connected, true);
} }
void EmulatedController::Disconnect() { void EmulatedController::Disconnect() {
std::unique_lock lock{mutex}; auto trigger_guard =
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Disconnected, !is_configuring); });
std::scoped_lock lock{mutex};
if (is_configuring) { if (is_configuring) {
tmp_is_connected = false; tmp_is_connected = false;
lock.unlock();
TriggerOnChange(ControllerTriggerType::Disconnected, false);
return; return;
} }
if (!is_connected) { if (!is_connected) {
trigger_guard.Cancel();
return; return;
} }
is_connected = false; is_connected = false;
lock.unlock();
TriggerOnChange(ControllerTriggerType::Disconnected, true);
} }
bool EmulatedController::IsConnected(bool get_temporary_value) const { bool EmulatedController::IsConnected(bool get_temporary_value) const {
@ -1469,19 +1441,21 @@ NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) c
} }
void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) { void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) {
std::unique_lock lock{mutex}; auto trigger_guard =
SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Type, !is_configuring); });
std::scoped_lock lock{mutex};
if (is_configuring) { if (is_configuring) {
if (tmp_npad_type == npad_type_) { if (tmp_npad_type == npad_type_) {
trigger_guard.Cancel();
return; return;
} }
tmp_npad_type = npad_type_; tmp_npad_type = npad_type_;
lock.unlock();
TriggerOnChange(ControllerTriggerType::Type, false);
return; return;
} }
if (npad_type == npad_type_) { if (npad_type == npad_type_) {
trigger_guard.Cancel();
return; return;
} }
if (is_connected) { if (is_connected) {
@ -1489,9 +1463,6 @@ void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) {
NpadIdTypeToIndex(npad_id_type)); NpadIdTypeToIndex(npad_id_type));
} }
npad_type = npad_type_; npad_type = npad_type_;
lock.unlock();
TriggerOnChange(ControllerTriggerType::Type, true);
} }
LedPattern EmulatedController::GetLedPattern() const { LedPattern EmulatedController::GetLedPattern() const {
@ -1589,7 +1560,7 @@ DebugPadButton EmulatedController::GetDebugPadButtons() const {
} }
AnalogSticks EmulatedController::GetSticks() const { AnalogSticks EmulatedController::GetSticks() const {
std::unique_lock lock{mutex}; std::scoped_lock lock{mutex};
if (is_configuring) { if (is_configuring) {
return {}; return {};

View file

@ -40,25 +40,26 @@ public:
} }
void EnableMotion() { void EnableMotion() {
if (sdl_controller) { if (!sdl_controller) {
SDL_GameController* controller = sdl_controller.get(); return;
has_accel = SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL) == SDL_TRUE; }
has_gyro = SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO) == SDL_TRUE; SDL_GameController* controller = sdl_controller.get();
if (has_accel) { if (HasMotion()) {
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE); SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_FALSE);
} SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_FALSE);
if (has_gyro) { }
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE); has_accel = SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL) == SDL_TRUE;
} has_gyro = SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO) == SDL_TRUE;
if (has_accel) {
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE);
}
if (has_gyro) {
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE);
} }
} }
bool HasGyro() const { bool HasMotion() const {
return has_gyro; return has_gyro || has_accel;
}
bool HasAccel() const {
return has_accel;
} }
bool UpdateMotion(SDL_ControllerSensorEvent event) { bool UpdateMotion(SDL_ControllerSensorEvent event) {
@ -85,6 +86,20 @@ public:
if (time_difference == 0) { if (time_difference == 0) {
return false; return false;
} }
// Motion data is invalid
if (motion.accel_x == 0 && motion.gyro_x == 0 && motion.accel_y == 0 &&
motion.gyro_y == 0 && motion.accel_z == 0 && motion.gyro_z == 0) {
if (motion_error_count++ < 200) {
return false;
}
// Try restarting the sensor
motion_error_count = 0;
EnableMotion();
return false;
}
motion_error_count = 0;
motion.delta_timestamp = time_difference * 1000; motion.delta_timestamp = time_difference * 1000;
return true; return true;
} }
@ -250,6 +265,7 @@ private:
mutable std::mutex mutex; mutable std::mutex mutex;
u64 last_motion_update{}; u64 last_motion_update{};
std::size_t motion_error_count{};
bool has_gyro{false}; bool has_gyro{false};
bool has_accel{false}; bool has_accel{false};
bool has_vibration{false}; bool has_vibration{false};
@ -955,18 +971,18 @@ MotionMapping SDLDriver::GetMotionMappingForDevice(const Common::ParamPackage& p
MotionMapping mapping = {}; MotionMapping mapping = {};
joystick->EnableMotion(); joystick->EnableMotion();
if (joystick->HasGyro() || joystick->HasAccel()) { if (joystick->HasMotion()) {
mapping.insert_or_assign(Settings::NativeMotion::MotionRight, mapping.insert_or_assign(Settings::NativeMotion::MotionRight,
BuildMotionParam(joystick->GetPort(), joystick->GetGUID())); BuildMotionParam(joystick->GetPort(), joystick->GetGUID()));
} }
if (params.Has("guid2")) { if (params.Has("guid2")) {
joystick2->EnableMotion(); joystick2->EnableMotion();
if (joystick2->HasGyro() || joystick2->HasAccel()) { if (joystick2->HasMotion()) {
mapping.insert_or_assign(Settings::NativeMotion::MotionLeft, mapping.insert_or_assign(Settings::NativeMotion::MotionLeft,
BuildMotionParam(joystick2->GetPort(), joystick2->GetGUID())); BuildMotionParam(joystick2->GetPort(), joystick2->GetGUID()));
} }
} else { } else {
if (joystick->HasGyro() || joystick->HasAccel()) { if (joystick->HasMotion()) {
mapping.insert_or_assign(Settings::NativeMotion::MotionLeft, mapping.insert_or_assign(Settings::NativeMotion::MotionLeft,
BuildMotionParam(joystick->GetPort(), joystick->GetGUID())); BuildMotionParam(joystick->GetPort(), joystick->GetGUID()));
} }

View file

@ -12,10 +12,10 @@ CalibrationProtocol::CalibrationProtocol(std::shared_ptr<JoyconHandle> handle)
: JoyconCommonProtocol(std::move(handle)) {} : JoyconCommonProtocol(std::move(handle)) {}
DriverResult CalibrationProtocol::GetLeftJoyStickCalibration(JoyStickCalibration& calibration) { DriverResult CalibrationProtocol::GetLeftJoyStickCalibration(JoyStickCalibration& calibration) {
ScopedSetBlocking sb(this);
std::vector<u8> buffer; std::vector<u8> buffer;
DriverResult result{DriverResult::Success}; DriverResult result{DriverResult::Success};
calibration = {}; calibration = {};
SetBlocking();
result = ReadSPI(CalAddr::USER_LEFT_MAGIC, sizeof(u16), buffer); result = ReadSPI(CalAddr::USER_LEFT_MAGIC, sizeof(u16), buffer);
@ -44,15 +44,14 @@ DriverResult CalibrationProtocol::GetLeftJoyStickCalibration(JoyStickCalibration
// Set a valid default calibration if data is missing // Set a valid default calibration if data is missing
ValidateCalibration(calibration); ValidateCalibration(calibration);
SetNonBlocking();
return result; return result;
} }
DriverResult CalibrationProtocol::GetRightJoyStickCalibration(JoyStickCalibration& calibration) { DriverResult CalibrationProtocol::GetRightJoyStickCalibration(JoyStickCalibration& calibration) {
ScopedSetBlocking sb(this);
std::vector<u8> buffer; std::vector<u8> buffer;
DriverResult result{DriverResult::Success}; DriverResult result{DriverResult::Success};
calibration = {}; calibration = {};
SetBlocking();
result = ReadSPI(CalAddr::USER_RIGHT_MAGIC, sizeof(u16), buffer); result = ReadSPI(CalAddr::USER_RIGHT_MAGIC, sizeof(u16), buffer);
@ -81,15 +80,14 @@ DriverResult CalibrationProtocol::GetRightJoyStickCalibration(JoyStickCalibratio
// Set a valid default calibration if data is missing // Set a valid default calibration if data is missing
ValidateCalibration(calibration); ValidateCalibration(calibration);
SetNonBlocking();
return result; return result;
} }
DriverResult CalibrationProtocol::GetImuCalibration(MotionCalibration& calibration) { DriverResult CalibrationProtocol::GetImuCalibration(MotionCalibration& calibration) {
ScopedSetBlocking sb(this);
std::vector<u8> buffer; std::vector<u8> buffer;
DriverResult result{DriverResult::Success}; DriverResult result{DriverResult::Success};
calibration = {}; calibration = {};
SetBlocking();
result = ReadSPI(CalAddr::USER_IMU_MAGIC, sizeof(u16), buffer); result = ReadSPI(CalAddr::USER_IMU_MAGIC, sizeof(u16), buffer);
@ -124,7 +122,6 @@ DriverResult CalibrationProtocol::GetImuCalibration(MotionCalibration& calibrati
ValidateCalibration(calibration); ValidateCalibration(calibration);
SetNonBlocking();
return result; return result;
} }

View file

@ -58,9 +58,8 @@ DriverResult JoyconCommonProtocol::CheckDeviceAccess(SDL_hid_device_info* device
} }
DriverResult JoyconCommonProtocol::SetReportMode(ReportMode report_mode) { DriverResult JoyconCommonProtocol::SetReportMode(ReportMode report_mode) {
const std::vector<u8> buffer{static_cast<u8>(report_mode)}; const std::array<u8, 1> buffer{static_cast<u8>(report_mode)};
std::vector<u8> output; return SendSubCommand(SubCommand::SET_REPORT_MODE, buffer);
return SendSubCommand(SubCommand::SET_REPORT_MODE, buffer, output);
} }
DriverResult JoyconCommonProtocol::SendData(std::span<const u8> buffer) { DriverResult JoyconCommonProtocol::SendData(std::span<const u8> buffer) {
@ -120,6 +119,11 @@ DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const
return DriverResult::Success; return DriverResult::Success;
} }
DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const u8> buffer) {
std::vector<u8> output;
return SendSubCommand(sc, buffer, output);
}
DriverResult JoyconCommonProtocol::SendMCUCommand(SubCommand sc, std::span<const u8> buffer) { DriverResult JoyconCommonProtocol::SendMCUCommand(SubCommand sc, std::span<const u8> buffer) {
std::vector<u8> local_buffer(MaxResponseSize); std::vector<u8> local_buffer(MaxResponseSize);
@ -147,7 +151,7 @@ DriverResult JoyconCommonProtocol::SendVibrationReport(std::span<const u8> buffe
DriverResult JoyconCommonProtocol::ReadSPI(CalAddr addr, u8 size, std::vector<u8>& output) { DriverResult JoyconCommonProtocol::ReadSPI(CalAddr addr, u8 size, std::vector<u8>& output) {
constexpr std::size_t MaxTries = 10; constexpr std::size_t MaxTries = 10;
std::size_t tries = 0; std::size_t tries = 0;
std::vector<u8> buffer = {0x00, 0x00, 0x00, 0x00, size}; std::array<u8, 5> buffer = {0x00, 0x00, 0x00, 0x00, size};
std::vector<u8> local_buffer(size + 20); std::vector<u8> local_buffer(size + 20);
buffer[0] = static_cast<u8>(static_cast<u16>(addr) & 0x00FF); buffer[0] = static_cast<u8>(static_cast<u16>(addr) & 0x00FF);
@ -169,10 +173,8 @@ DriverResult JoyconCommonProtocol::ReadSPI(CalAddr addr, u8 size, std::vector<u8
} }
DriverResult JoyconCommonProtocol::EnableMCU(bool enable) { DriverResult JoyconCommonProtocol::EnableMCU(bool enable) {
std::vector<u8> output; const std::array<u8, 1> mcu_state{static_cast<u8>(enable ? 1 : 0)};
const auto result = SendSubCommand(SubCommand::SET_MCU_STATE, mcu_state);
const std::vector<u8> mcu_state{static_cast<u8>(enable ? 1 : 0)};
const auto result = SendSubCommand(SubCommand::SET_MCU_STATE, mcu_state, output);
if (result != DriverResult::Success) { if (result != DriverResult::Success) {
LOG_ERROR(Input, "SendMCUData failed with error {}", result); LOG_ERROR(Input, "SendMCUData failed with error {}", result);
@ -183,13 +185,11 @@ DriverResult JoyconCommonProtocol::EnableMCU(bool enable) {
DriverResult JoyconCommonProtocol::ConfigureMCU(const MCUConfig& config) { DriverResult JoyconCommonProtocol::ConfigureMCU(const MCUConfig& config) {
LOG_DEBUG(Input, "ConfigureMCU"); LOG_DEBUG(Input, "ConfigureMCU");
std::vector<u8> output;
std::array<u8, sizeof(MCUConfig)> config_buffer; std::array<u8, sizeof(MCUConfig)> config_buffer;
memcpy(config_buffer.data(), &config, sizeof(MCUConfig)); memcpy(config_buffer.data(), &config, sizeof(MCUConfig));
config_buffer[37] = CalculateMCU_CRC8(config_buffer.data() + 1, 36); config_buffer[37] = CalculateMCU_CRC8(config_buffer.data() + 1, 36);
const auto result = SendSubCommand(SubCommand::SET_MCU_CONFIG, config_buffer, output); const auto result = SendSubCommand(SubCommand::SET_MCU_CONFIG, config_buffer);
if (result != DriverResult::Success) { if (result != DriverResult::Success) {
LOG_ERROR(Input, "Set MCU config failed with error {}", result); LOG_ERROR(Input, "Set MCU config failed with error {}", result);

View file

@ -74,6 +74,13 @@ public:
*/ */
DriverResult SendSubCommand(SubCommand sc, std::span<const u8> buffer, std::vector<u8>& output); DriverResult SendSubCommand(SubCommand sc, std::span<const u8> buffer, std::vector<u8>& output);
/**
* Sends a sub command to the device and waits for it's reply and ignores the output
* @param sc sub command to be send
* @param buffer data to be send
*/
DriverResult SendSubCommand(SubCommand sc, std::span<const u8> buffer);
/** /**
* Sends a mcu command to the device * Sends a mcu command to the device
* @param sc sub command to be send * @param sc sub command to be send

View file

@ -10,22 +10,18 @@ GenericProtocol::GenericProtocol(std::shared_ptr<JoyconHandle> handle)
: JoyconCommonProtocol(std::move(handle)) {} : JoyconCommonProtocol(std::move(handle)) {}
DriverResult GenericProtocol::EnablePassiveMode() { DriverResult GenericProtocol::EnablePassiveMode() {
SetBlocking(); ScopedSetBlocking sb(this);
const auto result = SetReportMode(ReportMode::SIMPLE_HID_MODE); return SetReportMode(ReportMode::SIMPLE_HID_MODE);
SetNonBlocking();
return result;
} }
DriverResult GenericProtocol::EnableActiveMode() { DriverResult GenericProtocol::EnableActiveMode() {
SetBlocking(); ScopedSetBlocking sb(this);
const auto result = SetReportMode(ReportMode::STANDARD_FULL_60HZ); return SetReportMode(ReportMode::STANDARD_FULL_60HZ);
SetNonBlocking();
return result;
} }
DriverResult GenericProtocol::GetDeviceInfo(DeviceInfo& device_info) { DriverResult GenericProtocol::GetDeviceInfo(DeviceInfo& device_info) {
ScopedSetBlocking sb(this);
std::vector<u8> output; std::vector<u8> output;
SetBlocking();
const auto result = SendSubCommand(SubCommand::REQ_DEV_INFO, {}, output); const auto result = SendSubCommand(SubCommand::REQ_DEV_INFO, {}, output);
@ -34,7 +30,6 @@ DriverResult GenericProtocol::GetDeviceInfo(DeviceInfo& device_info) {
memcpy(&device_info, output.data(), sizeof(DeviceInfo)); memcpy(&device_info, output.data(), sizeof(DeviceInfo));
} }
SetNonBlocking();
return result; return result;
} }
@ -43,36 +38,30 @@ DriverResult GenericProtocol::GetControllerType(ControllerType& controller_type)
} }
DriverResult GenericProtocol::EnableImu(bool enable) { DriverResult GenericProtocol::EnableImu(bool enable) {
ScopedSetBlocking sb(this);
const std::array<u8, 1> buffer{static_cast<u8>(enable ? 1 : 0)}; const std::array<u8, 1> buffer{static_cast<u8>(enable ? 1 : 0)};
std::vector<u8> output; return SendSubCommand(SubCommand::ENABLE_IMU, buffer);
SetBlocking();
const auto result = SendSubCommand(SubCommand::ENABLE_IMU, buffer, output);
SetNonBlocking();
return result;
} }
DriverResult GenericProtocol::SetImuConfig(GyroSensitivity gsen, GyroPerformance gfrec, DriverResult GenericProtocol::SetImuConfig(GyroSensitivity gsen, GyroPerformance gfrec,
AccelerometerSensitivity asen, AccelerometerSensitivity asen,
AccelerometerPerformance afrec) { AccelerometerPerformance afrec) {
ScopedSetBlocking sb(this);
const std::array<u8, 4> buffer{static_cast<u8>(gsen), static_cast<u8>(asen), const std::array<u8, 4> buffer{static_cast<u8>(gsen), static_cast<u8>(asen),
static_cast<u8>(gfrec), static_cast<u8>(afrec)}; static_cast<u8>(gfrec), static_cast<u8>(afrec)};
std::vector<u8> output; return SendSubCommand(SubCommand::SET_IMU_SENSITIVITY, buffer);
SetBlocking();
const auto result = SendSubCommand(SubCommand::SET_IMU_SENSITIVITY, buffer, output);
SetNonBlocking();
return result;
} }
DriverResult GenericProtocol::GetBattery(u32& battery_level) { DriverResult GenericProtocol::GetBattery(u32& battery_level) {
// This function is meant to request the high resolution battery status
battery_level = 0; battery_level = 0;
return DriverResult::NotSupported; return DriverResult::NotSupported;
} }
DriverResult GenericProtocol::GetColor(Color& color) { DriverResult GenericProtocol::GetColor(Color& color) {
ScopedSetBlocking sb(this);
std::vector<u8> buffer; std::vector<u8> buffer;
SetBlocking();
const auto result = ReadSPI(CalAddr::COLOR_DATA, 12, buffer); const auto result = ReadSPI(CalAddr::COLOR_DATA, 12, buffer);
SetNonBlocking();
color = {}; color = {};
if (result == DriverResult::Success) { if (result == DriverResult::Success) {
@ -86,10 +75,9 @@ DriverResult GenericProtocol::GetColor(Color& color) {
} }
DriverResult GenericProtocol::GetSerialNumber(SerialNumber& serial_number) { DriverResult GenericProtocol::GetSerialNumber(SerialNumber& serial_number) {
ScopedSetBlocking sb(this);
std::vector<u8> buffer; std::vector<u8> buffer;
SetBlocking();
const auto result = ReadSPI(CalAddr::SERIAL_NUMBER, 16, buffer); const auto result = ReadSPI(CalAddr::SERIAL_NUMBER, 16, buffer);
SetNonBlocking();
serial_number = {}; serial_number = {};
if (result == DriverResult::Success) { if (result == DriverResult::Success) {
@ -115,14 +103,9 @@ DriverResult GenericProtocol::GetVersionNumber(FirmwareVersion& version) {
} }
DriverResult GenericProtocol::SetHomeLight() { DriverResult GenericProtocol::SetHomeLight() {
ScopedSetBlocking sb(this);
static constexpr std::array<u8, 3> buffer{0x0f, 0xf0, 0x00}; static constexpr std::array<u8, 3> buffer{0x0f, 0xf0, 0x00};
std::vector<u8> output; return SendSubCommand(SubCommand::SET_HOME_LIGHT, buffer);
SetBlocking();
const auto result = SendSubCommand(SubCommand::SET_HOME_LIGHT, buffer, output);
SetNonBlocking();
return result;
} }
DriverResult GenericProtocol::SetLedBusy() { DriverResult GenericProtocol::SetLedBusy() {
@ -130,14 +113,9 @@ DriverResult GenericProtocol::SetLedBusy() {
} }
DriverResult GenericProtocol::SetLedPattern(u8 leds) { DriverResult GenericProtocol::SetLedPattern(u8 leds) {
ScopedSetBlocking sb(this);
const std::array<u8, 1> buffer{leds}; const std::array<u8, 1> buffer{leds};
std::vector<u8> output; return SendSubCommand(SubCommand::SET_PLAYER_LIGHTS, buffer);
SetBlocking();
const auto result = SendSubCommand(SubCommand::SET_PLAYER_LIGHTS, buffer, output);
SetNonBlocking();
return result;
} }
DriverResult GenericProtocol::SetLedBlinkPattern(u8 leds) { DriverResult GenericProtocol::SetLedBlinkPattern(u8 leds) {

View file

@ -12,8 +12,8 @@ IrsProtocol::IrsProtocol(std::shared_ptr<JoyconHandle> handle)
DriverResult IrsProtocol::EnableIrs() { DriverResult IrsProtocol::EnableIrs() {
LOG_INFO(Input, "Enable IRS"); LOG_INFO(Input, "Enable IRS");
ScopedSetBlocking sb(this);
DriverResult result{DriverResult::Success}; DriverResult result{DriverResult::Success};
SetBlocking();
if (result == DriverResult::Success) { if (result == DriverResult::Success) {
result = SetReportMode(ReportMode::NFC_IR_MODE_60HZ); result = SetReportMode(ReportMode::NFC_IR_MODE_60HZ);
@ -49,14 +49,13 @@ DriverResult IrsProtocol::EnableIrs() {
is_enabled = true; is_enabled = true;
SetNonBlocking();
return result; return result;
} }
DriverResult IrsProtocol::DisableIrs() { DriverResult IrsProtocol::DisableIrs() {
LOG_DEBUG(Input, "Disable IRS"); LOG_DEBUG(Input, "Disable IRS");
ScopedSetBlocking sb(this);
DriverResult result{DriverResult::Success}; DriverResult result{DriverResult::Success};
SetBlocking();
if (result == DriverResult::Success) { if (result == DriverResult::Success) {
result = EnableMCU(false); result = EnableMCU(false);
@ -64,7 +63,6 @@ DriverResult IrsProtocol::DisableIrs() {
is_enabled = false; is_enabled = false;
SetNonBlocking();
return result; return result;
} }
@ -148,7 +146,7 @@ DriverResult IrsProtocol::ConfigureIrs() {
}; };
buf_image.resize((static_cast<u8>(fragments) + 1) * 300); buf_image.resize((static_cast<u8>(fragments) + 1) * 300);
std::vector<u8> request_data(sizeof(IrsConfigure)); std::array<u8, sizeof(IrsConfigure)> request_data{};
memcpy(request_data.data(), &irs_configuration, sizeof(IrsConfigure)); memcpy(request_data.data(), &irs_configuration, sizeof(IrsConfigure));
request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
do { do {
@ -191,7 +189,7 @@ DriverResult IrsProtocol::WriteRegistersStep1() {
.crc = {}, .crc = {},
}; };
std::vector<u8> request_data(sizeof(IrsWriteRegisters)); std::array<u8, sizeof(IrsWriteRegisters)> request_data{};
memcpy(request_data.data(), &irs_registers, sizeof(IrsWriteRegisters)); memcpy(request_data.data(), &irs_registers, sizeof(IrsWriteRegisters));
request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
@ -250,7 +248,7 @@ DriverResult IrsProtocol::WriteRegistersStep2() {
.crc = {}, .crc = {},
}; };
std::vector<u8> request_data(sizeof(IrsWriteRegisters)); std::array<u8, sizeof(IrsWriteRegisters)> request_data{};
memcpy(request_data.data(), &irs_registers, sizeof(IrsWriteRegisters)); memcpy(request_data.data(), &irs_registers, sizeof(IrsWriteRegisters));
request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
do { do {

View file

@ -347,6 +347,13 @@ enum class IrRegistersAddress : u16 {
DenoiseColor = 0x6901, DenoiseColor = 0x6901,
}; };
enum class NFCBlock {
Block0 = 0,
Block45 = 45,
Block135 = 135,
Block231 = 231,
};
enum class DriverResult { enum class DriverResult {
Success, Success,
WrongReply, WrongReply,

View file

@ -12,8 +12,8 @@ NfcProtocol::NfcProtocol(std::shared_ptr<JoyconHandle> handle)
DriverResult NfcProtocol::EnableNfc() { DriverResult NfcProtocol::EnableNfc() {
LOG_INFO(Input, "Enable NFC"); LOG_INFO(Input, "Enable NFC");
ScopedSetBlocking sb(this);
DriverResult result{DriverResult::Success}; DriverResult result{DriverResult::Success};
SetBlocking();
if (result == DriverResult::Success) { if (result == DriverResult::Success) {
result = SetReportMode(ReportMode::NFC_IR_MODE_60HZ); result = SetReportMode(ReportMode::NFC_IR_MODE_60HZ);
@ -35,14 +35,13 @@ DriverResult NfcProtocol::EnableNfc() {
result = ConfigureMCU(config); result = ConfigureMCU(config);
} }
SetNonBlocking();
return result; return result;
} }
DriverResult NfcProtocol::DisableNfc() { DriverResult NfcProtocol::DisableNfc() {
LOG_DEBUG(Input, "Disable NFC"); LOG_DEBUG(Input, "Disable NFC");
ScopedSetBlocking sb(this);
DriverResult result{DriverResult::Success}; DriverResult result{DriverResult::Success};
SetBlocking();
if (result == DriverResult::Success) { if (result == DriverResult::Success) {
result = EnableMCU(false); result = EnableMCU(false);
@ -50,15 +49,14 @@ DriverResult NfcProtocol::DisableNfc() {
is_enabled = false; is_enabled = false;
SetNonBlocking();
return result; return result;
} }
DriverResult NfcProtocol::StartNFCPollingMode() { DriverResult NfcProtocol::StartNFCPollingMode() {
LOG_DEBUG(Input, "Start NFC pooling Mode"); LOG_DEBUG(Input, "Start NFC pooling Mode");
ScopedSetBlocking sb(this);
DriverResult result{DriverResult::Success}; DriverResult result{DriverResult::Success};
TagFoundData tag_data{}; TagFoundData tag_data{};
SetBlocking();
if (result == DriverResult::Success) { if (result == DriverResult::Success) {
result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::NFC); result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::NFC);
@ -70,15 +68,14 @@ DriverResult NfcProtocol::StartNFCPollingMode() {
is_enabled = true; is_enabled = true;
} }
SetNonBlocking();
return result; return result;
} }
DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) { DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) {
LOG_DEBUG(Input, "Start NFC pooling Mode"); LOG_DEBUG(Input, "Start NFC pooling Mode");
ScopedSetBlocking sb(this);
DriverResult result{DriverResult::Success}; DriverResult result{DriverResult::Success};
TagFoundData tag_data{}; TagFoundData tag_data{};
SetBlocking();
if (result == DriverResult::Success) { if (result == DriverResult::Success) {
result = StartPolling(tag_data); result = StartPolling(tag_data);
@ -96,20 +93,18 @@ DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) {
result = GetAmiiboData(data); result = GetAmiiboData(data);
} }
SetNonBlocking();
return result; return result;
} }
bool NfcProtocol::HasAmiibo() { bool NfcProtocol::HasAmiibo() {
ScopedSetBlocking sb(this);
DriverResult result{DriverResult::Success}; DriverResult result{DriverResult::Success};
TagFoundData tag_data{}; TagFoundData tag_data{};
SetBlocking();
if (result == DriverResult::Success) { if (result == DriverResult::Success) {
result = StartPolling(tag_data); result = StartPolling(tag_data);
} }
SetNonBlocking();
return result == DriverResult::Success; return result == DriverResult::Success;
} }
@ -298,7 +293,7 @@ DriverResult NfcProtocol::SendStartPollingRequest(std::vector<u8>& output) {
.crc = {}, .crc = {},
}; };
std::vector<u8> request_data(sizeof(NFCRequestState)); std::array<u8, sizeof(NFCRequestState)> request_data{};
memcpy(request_data.data(), &request, sizeof(NFCRequestState)); memcpy(request_data.data(), &request, sizeof(NFCRequestState));
request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output);
@ -315,7 +310,7 @@ DriverResult NfcProtocol::SendStopPollingRequest(std::vector<u8>& output) {
.crc = {}, .crc = {},
}; };
std::vector<u8> request_data(sizeof(NFCRequestState)); std::array<u8, sizeof(NFCRequestState)> request_data{};
memcpy(request_data.data(), &request, sizeof(NFCRequestState)); memcpy(request_data.data(), &request, sizeof(NFCRequestState));
request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output);
@ -357,60 +352,50 @@ DriverResult NfcProtocol::SendReadAmiiboRequest(std::vector<u8>& output, std::si
.crc = {}, .crc = {},
}; };
std::vector<u8> request_data(sizeof(NFCRequestState)); std::array<u8, sizeof(NFCRequestState)> request_data{};
memcpy(request_data.data(), &request, sizeof(NFCRequestState)); memcpy(request_data.data(), &request, sizeof(NFCRequestState));
request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output);
} }
NFCReadBlockCommand NfcProtocol::GetReadBlockCommand(std::size_t pages) const { NFCReadBlockCommand NfcProtocol::GetReadBlockCommand(std::size_t pages) const {
constexpr NFCReadBlockCommand block0{ switch (static_cast<NFCBlock>(pages)) {
.block_count = 1, case NFCBlock::Block0:
return {
.block_count = 1,
};
case NFCBlock::Block45:
return {
.block_count = 1,
.blocks =
{
NFCReadBlock{0x00, 0x2C},
},
};
case NFCBlock::Block135:
return {
.block_count = 3,
.blocks =
{
NFCReadBlock{0x00, 0x3b},
{0x3c, 0x77},
{0x78, 0x86},
},
};
case NFCBlock::Block231:
return {
.block_count = 4,
.blocks =
{
NFCReadBlock{0x00, 0x3b},
{0x3c, 0x77},
{0x78, 0x83},
{0xb4, 0xe6},
},
};
default:
return {};
}; };
constexpr NFCReadBlockCommand block45{
.block_count = 1,
.blocks =
{
NFCReadBlock{0x00, 0x2C},
},
};
constexpr NFCReadBlockCommand block135{
.block_count = 3,
.blocks =
{
NFCReadBlock{0x00, 0x3b},
{0x3c, 0x77},
{0x78, 0x86},
},
};
constexpr NFCReadBlockCommand block231{
.block_count = 4,
.blocks =
{
NFCReadBlock{0x00, 0x3b},
{0x3c, 0x77},
{0x78, 0x83},
{0xb4, 0xe6},
},
};
if (pages == 0) {
return block0;
}
if (pages == 45) {
return block45;
}
if (pages == 135) {
return block135;
}
if (pages == 231) {
return block231;
}
return {};
} }
bool NfcProtocol::IsEnabled() const { bool NfcProtocol::IsEnabled() const {

View file

@ -11,8 +11,8 @@ RingConProtocol::RingConProtocol(std::shared_ptr<JoyconHandle> handle)
DriverResult RingConProtocol::EnableRingCon() { DriverResult RingConProtocol::EnableRingCon() {
LOG_DEBUG(Input, "Enable Ringcon"); LOG_DEBUG(Input, "Enable Ringcon");
ScopedSetBlocking sb(this);
DriverResult result{DriverResult::Success}; DriverResult result{DriverResult::Success};
SetBlocking();
if (result == DriverResult::Success) { if (result == DriverResult::Success) {
result = SetReportMode(ReportMode::STANDARD_FULL_60HZ); result = SetReportMode(ReportMode::STANDARD_FULL_60HZ);
@ -30,14 +30,13 @@ DriverResult RingConProtocol::EnableRingCon() {
result = ConfigureMCU(config); result = ConfigureMCU(config);
} }
SetNonBlocking();
return result; return result;
} }
DriverResult RingConProtocol::DisableRingCon() { DriverResult RingConProtocol::DisableRingCon() {
LOG_DEBUG(Input, "Disable RingCon"); LOG_DEBUG(Input, "Disable RingCon");
ScopedSetBlocking sb(this);
DriverResult result{DriverResult::Success}; DriverResult result{DriverResult::Success};
SetBlocking();
if (result == DriverResult::Success) { if (result == DriverResult::Success) {
result = EnableMCU(false); result = EnableMCU(false);
@ -45,15 +44,14 @@ DriverResult RingConProtocol::DisableRingCon() {
is_enabled = false; is_enabled = false;
SetNonBlocking();
return result; return result;
} }
DriverResult RingConProtocol::StartRingconPolling() { DriverResult RingConProtocol::StartRingconPolling() {
LOG_DEBUG(Input, "Enable Ringcon"); LOG_DEBUG(Input, "Enable Ringcon");
bool is_connected = false; ScopedSetBlocking sb(this);
DriverResult result{DriverResult::Success}; DriverResult result{DriverResult::Success};
SetBlocking(); bool is_connected = false;
if (result == DriverResult::Success) { if (result == DriverResult::Success) {
result = IsRingConnected(is_connected); result = IsRingConnected(is_connected);
@ -66,13 +64,13 @@ DriverResult RingConProtocol::StartRingconPolling() {
is_enabled = true; is_enabled = true;
} }
SetNonBlocking();
return result; return result;
} }
DriverResult RingConProtocol::IsRingConnected(bool& is_connected) { DriverResult RingConProtocol::IsRingConnected(bool& is_connected) {
LOG_DEBUG(Input, "IsRingConnected"); LOG_DEBUG(Input, "IsRingConnected");
constexpr std::size_t max_tries = 28; constexpr std::size_t max_tries = 28;
constexpr u8 ring_controller_id = 0x20;
std::vector<u8> output; std::vector<u8> output;
std::size_t tries = 0; std::size_t tries = 0;
is_connected = false; is_connected = false;
@ -88,7 +86,7 @@ DriverResult RingConProtocol::IsRingConnected(bool& is_connected) {
if (tries++ >= max_tries) { if (tries++ >= max_tries) {
return DriverResult::NoDeviceDetected; return DriverResult::NoDeviceDetected;
} }
} while (output[14] != 0x59 || output[16] != 0x20); } while (output[16] != ring_controller_id);
is_connected = true; is_connected = true;
return DriverResult::Success; return DriverResult::Success;
@ -96,30 +94,20 @@ DriverResult RingConProtocol::IsRingConnected(bool& is_connected) {
DriverResult RingConProtocol::ConfigureRing() { DriverResult RingConProtocol::ConfigureRing() {
LOG_DEBUG(Input, "ConfigureRing"); LOG_DEBUG(Input, "ConfigureRing");
constexpr std::size_t max_tries = 28;
DriverResult result{DriverResult::Success};
std::vector<u8> output;
std::size_t tries = 0;
static constexpr std::array<u8, 37> ring_config{ static constexpr std::array<u8, 37> ring_config{
0x06, 0x03, 0x25, 0x06, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x16, 0xED, 0x34, 0x36, 0x06, 0x03, 0x25, 0x06, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x16, 0xED, 0x34, 0x36,
0x00, 0x00, 0x00, 0x0A, 0x64, 0x0B, 0xE6, 0xA9, 0x22, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x64, 0x0B, 0xE6, 0xA9, 0x22, 0x00, 0x00, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xA8, 0xE1, 0x34, 0x36}; 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xA8, 0xE1, 0x34, 0x36};
do {
result = SendSubCommand(SubCommand::UNKNOWN_RINGCON3, ring_config, output);
if (result != DriverResult::Success) { const DriverResult result = SendSubCommand(SubCommand::UNKNOWN_RINGCON3, ring_config);
return result;
} if (result != DriverResult::Success) {
if (tries++ >= max_tries) { return result;
return DriverResult::NoDeviceDetected; }
}
} while (output[14] != 0x5C);
static constexpr std::array<u8, 4> ringcon_data{0x04, 0x01, 0x01, 0x02}; static constexpr std::array<u8, 4> ringcon_data{0x04, 0x01, 0x01, 0x02};
result = SendSubCommand(SubCommand::UNKNOWN_RINGCON2, ringcon_data, output); return SendSubCommand(SubCommand::UNKNOWN_RINGCON2, ringcon_data);
return result;
} }
bool RingConProtocol::IsEnabled() const { bool RingConProtocol::IsEnabled() const {

View file

@ -14,12 +14,9 @@ RumbleProtocol::RumbleProtocol(std::shared_ptr<JoyconHandle> handle)
DriverResult RumbleProtocol::EnableRumble(bool is_enabled) { DriverResult RumbleProtocol::EnableRumble(bool is_enabled) {
LOG_DEBUG(Input, "Enable Rumble"); LOG_DEBUG(Input, "Enable Rumble");
ScopedSetBlocking sb(this);
const std::array<u8, 1> buffer{static_cast<u8>(is_enabled ? 1 : 0)}; const std::array<u8, 1> buffer{static_cast<u8>(is_enabled ? 1 : 0)};
std::vector<u8> output; return SendSubCommand(SubCommand::ENABLE_VIBRATION, buffer);
SetBlocking();
const auto result = SendSubCommand(SubCommand::ENABLE_VIBRATION, buffer, output);
SetNonBlocking();
return result;
} }
DriverResult RumbleProtocol::SendVibration(const VibrationValue& vibration) { DriverResult RumbleProtocol::SendVibration(const VibrationValue& vibration) {