mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-30 02:32:46 +01:00
input_common: Address byte review
This commit is contained in:
parent
4a307a7b3a
commit
340f15d1fa
16 changed files with 224 additions and 247 deletions
|
@ -60,15 +60,12 @@ void Joycons::Setup() {
|
||||||
device = std::make_shared<Joycon::JoyconDriver>(port++);
|
device = std::make_shared<Joycon::JoyconDriver>(port++);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!scan_thread_running) {
|
scan_thread = std::jthread([this](std::stop_token stop_token) { ScanThread(stop_token); });
|
||||||
scan_thread = std::jthread([this](std::stop_token stop_token) { ScanThread(stop_token); });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Joycons::ScanThread(std::stop_token stop_token) {
|
void Joycons::ScanThread(std::stop_token stop_token) {
|
||||||
constexpr u16 nintendo_vendor_id = 0x057e;
|
constexpr u16 nintendo_vendor_id = 0x057e;
|
||||||
Common::SetCurrentThreadName("yuzu:input:JoyconScanThread");
|
Common::SetCurrentThreadName("JoyconScanThread");
|
||||||
scan_thread_running = true;
|
|
||||||
while (!stop_token.stop_requested()) {
|
while (!stop_token.stop_requested()) {
|
||||||
SDL_hid_device_info* devs = SDL_hid_enumerate(nintendo_vendor_id, 0x0);
|
SDL_hid_device_info* devs = SDL_hid_enumerate(nintendo_vendor_id, 0x0);
|
||||||
SDL_hid_device_info* cur_dev = devs;
|
SDL_hid_device_info* cur_dev = devs;
|
||||||
|
@ -82,9 +79,9 @@ void Joycons::ScanThread(std::stop_token stop_token) {
|
||||||
cur_dev = cur_dev->next;
|
cur_dev = cur_dev->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_hid_free_enumeration(devs);
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(5));
|
std::this_thread::sleep_for(std::chrono::seconds(5));
|
||||||
}
|
}
|
||||||
scan_thread_running = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Joycons::IsDeviceNew(SDL_hid_device_info* device_info) const {
|
bool Joycons::IsDeviceNew(SDL_hid_device_info* device_info) const {
|
||||||
|
@ -185,19 +182,19 @@ void Joycons::RegisterNewDevice(SDL_hid_device_info* device_info) {
|
||||||
|
|
||||||
std::shared_ptr<Joycon::JoyconDriver> Joycons::GetNextFreeHandle(
|
std::shared_ptr<Joycon::JoyconDriver> Joycons::GetNextFreeHandle(
|
||||||
Joycon::ControllerType type) const {
|
Joycon::ControllerType type) const {
|
||||||
|
|
||||||
if (type == Joycon::ControllerType::Left) {
|
if (type == Joycon::ControllerType::Left) {
|
||||||
for (const auto& device : left_joycons) {
|
const auto unconnected_device =
|
||||||
if (!device->IsConnected()) {
|
std::ranges::find_if(left_joycons, [](auto& device) { return !device->IsConnected(); });
|
||||||
return device;
|
if (unconnected_device != left_joycons.end()) {
|
||||||
}
|
return *unconnected_device;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type == Joycon::ControllerType::Right) {
|
if (type == Joycon::ControllerType::Right) {
|
||||||
for (const auto& device : right_joycons) {
|
const auto unconnected_device = std::ranges::find_if(
|
||||||
if (!device->IsConnected()) {
|
right_joycons, [](auto& device) { return !device->IsConnected(); });
|
||||||
return device;
|
|
||||||
}
|
if (unconnected_device != right_joycons.end()) {
|
||||||
|
return *unconnected_device;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -391,20 +388,25 @@ std::shared_ptr<Joycon::JoyconDriver> Joycons::GetHandle(PadIdentifier identifie
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
const auto type = static_cast<Joycon::ControllerType>(identifier.pad);
|
const auto type = static_cast<Joycon::ControllerType>(identifier.pad);
|
||||||
|
|
||||||
if (type == Joycon::ControllerType::Left) {
|
if (type == Joycon::ControllerType::Left) {
|
||||||
for (const auto& device : left_joycons) {
|
const auto matching_device = std::ranges::find_if(
|
||||||
if (is_handle_active(device)) {
|
left_joycons, [is_handle_active](auto& device) { return is_handle_active(device); });
|
||||||
return device;
|
|
||||||
}
|
if (matching_device != left_joycons.end()) {
|
||||||
|
return *matching_device;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == Joycon::ControllerType::Right) {
|
if (type == Joycon::ControllerType::Right) {
|
||||||
for (const auto& device : right_joycons) {
|
const auto matching_device = std::ranges::find_if(
|
||||||
if (is_handle_active(device)) {
|
right_joycons, [is_handle_active](auto& device) { return is_handle_active(device); });
|
||||||
return device;
|
|
||||||
}
|
if (matching_device != right_joycons.end()) {
|
||||||
|
return *matching_device;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -676,7 +678,7 @@ std::string Joycons::JoyconName(Joycon::ControllerType type) const {
|
||||||
case Joycon::ControllerType::Dual:
|
case Joycon::ControllerType::Dual:
|
||||||
return "Dual Joycon";
|
return "Dual Joycon";
|
||||||
default:
|
default:
|
||||||
return "Unknow Joycon";
|
return "Unknown Joycon";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace InputCommon
|
} // namespace InputCommon
|
||||||
|
|
|
@ -99,7 +99,6 @@ private:
|
||||||
std::string JoyconName(Joycon::ControllerType type) const;
|
std::string JoyconName(Joycon::ControllerType type) const;
|
||||||
|
|
||||||
std::jthread scan_thread;
|
std::jthread scan_thread;
|
||||||
bool scan_thread_running{};
|
|
||||||
|
|
||||||
// Joycon types are split by type to ease supporting dualjoycon configurations
|
// Joycon types are split by type to ease supporting dualjoycon configurations
|
||||||
std::array<std::shared_ptr<Joycon::JoyconDriver>, MaxSupportedControllers> left_joycons{};
|
std::array<std::shared_ptr<Joycon::JoyconDriver>, MaxSupportedControllers> left_joycons{};
|
||||||
|
|
|
@ -321,7 +321,7 @@ void SDLDriver::InitJoystick(int joystick_index) {
|
||||||
if (Settings::values.enable_joycon_driver) {
|
if (Settings::values.enable_joycon_driver) {
|
||||||
if (guid.uuid[5] == 0x05 && guid.uuid[4] == 0x7e &&
|
if (guid.uuid[5] == 0x05 && guid.uuid[4] == 0x7e &&
|
||||||
(guid.uuid[8] == 0x06 || guid.uuid[8] == 0x07)) {
|
(guid.uuid[8] == 0x06 || guid.uuid[8] == 0x07)) {
|
||||||
LOG_ERROR(Input, "Device black listed {}", joystick_index);
|
LOG_WARNING(Input, "Preferring joycon driver for device index {}", joystick_index);
|
||||||
SDL_JoystickClose(sdl_joystick);
|
SDL_JoystickClose(sdl_joystick);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,7 +123,7 @@ DriverResult JoyconDriver::InitializeDevice() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void JoyconDriver::InputThread(std::stop_token stop_token) {
|
void JoyconDriver::InputThread(std::stop_token stop_token) {
|
||||||
LOG_INFO(Input, "JC Adapter input thread started");
|
LOG_INFO(Input, "Joycon Adapter input thread started");
|
||||||
Common::SetCurrentThreadName("JoyconInput");
|
Common::SetCurrentThreadName("JoyconInput");
|
||||||
input_thread_running = true;
|
input_thread_running = true;
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ void JoyconDriver::InputThread(std::stop_token stop_token) {
|
||||||
|
|
||||||
is_connected = false;
|
is_connected = false;
|
||||||
input_thread_running = false;
|
input_thread_running = false;
|
||||||
LOG_INFO(Input, "JC Adapter input thread stopped");
|
LOG_INFO(Input, "Joycon Adapter input thread stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
void JoyconDriver::OnNewData(std::span<u8> buffer) {
|
void JoyconDriver::OnNewData(std::span<u8> buffer) {
|
||||||
|
@ -349,7 +349,7 @@ JoyconDriver::SupportedFeatures JoyconDriver::GetSupportedFeatures() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JoyconDriver::IsInputThreadValid() const {
|
bool JoyconDriver::IsInputThreadValid() const {
|
||||||
if (!is_connected) {
|
if (!is_connected.load()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (hidapi_handle->handle == nullptr) {
|
if (hidapi_handle->handle == nullptr) {
|
||||||
|
@ -491,7 +491,7 @@ DriverResult JoyconDriver::SetRingConMode() {
|
||||||
|
|
||||||
bool JoyconDriver::IsConnected() const {
|
bool JoyconDriver::IsConnected() const {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
return is_connected;
|
return is_connected.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JoyconDriver::IsVibrationEnabled() const {
|
bool JoyconDriver::IsVibrationEnabled() const {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <span>
|
#include <span>
|
||||||
|
@ -97,7 +98,7 @@ private:
|
||||||
std::unique_ptr<RumbleProtocol> rumble_protocol;
|
std::unique_ptr<RumbleProtocol> rumble_protocol;
|
||||||
|
|
||||||
// Connection status
|
// Connection status
|
||||||
bool is_connected{};
|
std::atomic<bool> is_connected{};
|
||||||
u64 delta_time;
|
u64 delta_time;
|
||||||
std::size_t error_counter{};
|
std::size_t error_counter{};
|
||||||
std::shared_ptr<JoyconHandle> hidapi_handle;
|
std::shared_ptr<JoyconHandle> hidapi_handle;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,7 +119,12 @@ DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const
|
||||||
return DriverResult::Success;
|
return DriverResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
DriverResult JoyconCommonProtocol::SendMcuCommand(SubCommand sc, std::span<const u8> buffer) {
|
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) {
|
||||||
std::vector<u8> local_buffer(MaxResponseSize);
|
std::vector<u8> local_buffer(MaxResponseSize);
|
||||||
|
|
||||||
local_buffer[0] = static_cast<u8>(OutputReport::MCU_DATA);
|
local_buffer[0] = static_cast<u8>(OutputReport::MCU_DATA);
|
||||||
|
@ -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);
|
||||||
|
|
|
@ -74,12 +74,19 @@ 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
|
||||||
* @param buffer data to be send
|
* @param buffer data to be send
|
||||||
*/
|
*/
|
||||||
DriverResult SendMcuCommand(SubCommand sc, std::span<const u8> buffer);
|
DriverResult SendMCUCommand(SubCommand sc, std::span<const u8> buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends vibration data to the joycon
|
* Sends vibration data to the joycon
|
||||||
|
@ -150,4 +157,17 @@ private:
|
||||||
std::shared_ptr<JoyconHandle> hidapi_handle;
|
std::shared_ptr<JoyconHandle> hidapi_handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ScopedSetBlocking {
|
||||||
|
public:
|
||||||
|
explicit ScopedSetBlocking(JoyconCommonProtocol* self) : m_self{self} {
|
||||||
|
m_self->SetBlocking();
|
||||||
|
}
|
||||||
|
|
||||||
|
~ScopedSetBlocking() {
|
||||||
|
m_self->SetNonBlocking();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
JoyconCommonProtocol* m_self{};
|
||||||
|
};
|
||||||
} // namespace InputCommon::Joycon
|
} // namespace InputCommon::Joycon
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
@ -208,7 +206,7 @@ DriverResult IrsProtocol::WriteRegistersStep1() {
|
||||||
|
|
||||||
// First time we need to set the report mode
|
// First time we need to set the report mode
|
||||||
if (result == DriverResult::Success && tries == 0) {
|
if (result == DriverResult::Success && tries == 0) {
|
||||||
result = SendMcuCommand(SubCommand::SET_REPORT_MODE, mcu_request);
|
result = SendMCUCommand(SubCommand::SET_REPORT_MODE, mcu_request);
|
||||||
}
|
}
|
||||||
if (result == DriverResult::Success && tries == 0) {
|
if (result == DriverResult::Success && tries == 0) {
|
||||||
GetSubCommandResponse(SubCommand::SET_MCU_CONFIG, output);
|
GetSubCommandResponse(SubCommand::SET_MCU_CONFIG, output);
|
||||||
|
@ -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 {
|
||||||
|
@ -272,7 +270,7 @@ DriverResult IrsProtocol::RequestFrame(u8 frame) {
|
||||||
mcu_request[3] = frame;
|
mcu_request[3] = frame;
|
||||||
mcu_request[36] = CalculateMCU_CRC8(mcu_request.data(), 36);
|
mcu_request[36] = CalculateMCU_CRC8(mcu_request.data(), 36);
|
||||||
mcu_request[37] = 0xFF;
|
mcu_request[37] = 0xFF;
|
||||||
return SendMcuCommand(SubCommand::SET_REPORT_MODE, mcu_request);
|
return SendMCUCommand(SubCommand::SET_REPORT_MODE, mcu_request);
|
||||||
}
|
}
|
||||||
|
|
||||||
DriverResult IrsProtocol::ResendFrame(u8 frame) {
|
DriverResult IrsProtocol::ResendFrame(u8 frame) {
|
||||||
|
@ -282,7 +280,7 @@ DriverResult IrsProtocol::ResendFrame(u8 frame) {
|
||||||
mcu_request[3] = 0x0;
|
mcu_request[3] = 0x0;
|
||||||
mcu_request[36] = CalculateMCU_CRC8(mcu_request.data(), 36);
|
mcu_request[36] = CalculateMCU_CRC8(mcu_request.data(), 36);
|
||||||
mcu_request[37] = 0xFF;
|
mcu_request[37] = 0xFF;
|
||||||
return SendMcuCommand(SubCommand::SET_REPORT_MODE, mcu_request);
|
return SendMCUCommand(SubCommand::SET_REPORT_MODE, mcu_request);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> IrsProtocol::GetImage() const {
|
std::vector<u8> IrsProtocol::GetImage() const {
|
||||||
|
|
|
@ -273,6 +273,18 @@ enum class NFCTagType : u8 {
|
||||||
Ntag215 = 0x01,
|
Ntag215 = 0x01,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class NFCPages {
|
||||||
|
Block0 = 0,
|
||||||
|
Block45 = 45,
|
||||||
|
Block135 = 135,
|
||||||
|
Block231 = 231,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class NFCStatus : u8 {
|
||||||
|
LastPackage = 0x04,
|
||||||
|
TagLost = 0x07,
|
||||||
|
};
|
||||||
|
|
||||||
enum class IrsMode : u8 {
|
enum class IrsMode : u8 {
|
||||||
None = 0x02,
|
None = 0x02,
|
||||||
Moment = 0x03,
|
Moment = 0x03,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,55 +164,53 @@ DriverResult NfcProtocol::ReadTag(const TagFoundData& data) {
|
||||||
LOG_INFO(Input, "Tag detected, type={}, uuid={}", data.type, uuid_string);
|
LOG_INFO(Input, "Tag detected, type={}, uuid={}", data.type, uuid_string);
|
||||||
|
|
||||||
tries = 0;
|
tries = 0;
|
||||||
std::size_t ntag_pages = 0;
|
NFCPages ntag_pages = NFCPages::Block0;
|
||||||
// Read Tag data
|
// Read Tag data
|
||||||
loop1:
|
|
||||||
while (true) {
|
while (true) {
|
||||||
auto result = SendReadAmiiboRequest(output, ntag_pages);
|
auto result = SendReadAmiiboRequest(output, ntag_pages);
|
||||||
|
const auto mcu_report = static_cast<MCUReport>(output[49]);
|
||||||
int attempt = 0;
|
const auto nfc_status = static_cast<NFCStatus>(output[56]);
|
||||||
while (1) {
|
|
||||||
if (attempt != 0) {
|
|
||||||
result = GetMCUDataResponse(ReportMode::NFC_IR_MODE_60HZ, output);
|
|
||||||
}
|
|
||||||
if ((output[49] == 0x3a || output[49] == 0x2a) && output[56] == 0x07) {
|
|
||||||
return DriverResult::ErrorReadingData;
|
|
||||||
}
|
|
||||||
if (output[49] == 0x3a && output[51] == 0x07 && output[52] == 0x01) {
|
|
||||||
if (data.type != 2) {
|
|
||||||
goto loop1;
|
|
||||||
}
|
|
||||||
switch (output[74]) {
|
|
||||||
case 0:
|
|
||||||
ntag_pages = 135;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
ntag_pages = 45;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
ntag_pages = 231;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return DriverResult::ErrorReadingData;
|
|
||||||
}
|
|
||||||
goto loop1;
|
|
||||||
}
|
|
||||||
if (output[49] == 0x2a && output[56] == 0x04) {
|
|
||||||
// finished
|
|
||||||
SendStopPollingRequest(output);
|
|
||||||
return DriverResult::Success;
|
|
||||||
}
|
|
||||||
if (output[49] == 0x2a) {
|
|
||||||
goto loop1;
|
|
||||||
}
|
|
||||||
if (attempt++ > 6) {
|
|
||||||
goto loop1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != DriverResult::Success) {
|
if (result != DriverResult::Success) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((mcu_report == MCUReport::NFCReadData || mcu_report == MCUReport::NFCState) &&
|
||||||
|
nfc_status == NFCStatus::TagLost) {
|
||||||
|
return DriverResult::ErrorReadingData;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mcu_report == MCUReport::NFCReadData && output[51] == 0x07 && output[52] == 0x01) {
|
||||||
|
if (data.type != 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (output[74]) {
|
||||||
|
case 0:
|
||||||
|
ntag_pages = NFCPages::Block135;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
ntag_pages = NFCPages::Block45;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
ntag_pages = NFCPages::Block231;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return DriverResult::ErrorReadingData;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) {
|
||||||
|
// finished
|
||||||
|
SendStopPollingRequest(output);
|
||||||
|
return DriverResult::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore other state reports
|
||||||
|
if (mcu_report == MCUReport::NFCState) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (tries++ > timeout_limit) {
|
if (tries++ > timeout_limit) {
|
||||||
return DriverResult::Timeout;
|
return DriverResult::Timeout;
|
||||||
}
|
}
|
||||||
|
@ -231,47 +224,44 @@ DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) {
|
||||||
std::vector<u8> output;
|
std::vector<u8> output;
|
||||||
std::size_t tries = 0;
|
std::size_t tries = 0;
|
||||||
|
|
||||||
std::size_t ntag_pages = 135;
|
NFCPages ntag_pages = NFCPages::Block135;
|
||||||
std::size_t ntag_buffer_pos = 0;
|
std::size_t ntag_buffer_pos = 0;
|
||||||
// Read Tag data
|
// Read Tag data
|
||||||
loop1:
|
|
||||||
while (true) {
|
while (true) {
|
||||||
auto result = SendReadAmiiboRequest(output, ntag_pages);
|
auto result = SendReadAmiiboRequest(output, ntag_pages);
|
||||||
|
const auto mcu_report = static_cast<MCUReport>(output[49]);
|
||||||
int attempt = 0;
|
const auto nfc_status = static_cast<NFCStatus>(output[56]);
|
||||||
while (1) {
|
|
||||||
if (attempt != 0) {
|
|
||||||
result = GetMCUDataResponse(ReportMode::NFC_IR_MODE_60HZ, output);
|
|
||||||
}
|
|
||||||
if ((output[49] == 0x3a || output[49] == 0x2a) && output[56] == 0x07) {
|
|
||||||
return DriverResult::ErrorReadingData;
|
|
||||||
}
|
|
||||||
if (output[49] == 0x3a && output[51] == 0x07) {
|
|
||||||
std::size_t payload_size = (output[54] << 8 | output[55]) & 0x7FF;
|
|
||||||
if (output[52] == 0x01) {
|
|
||||||
memcpy(ntag_data.data() + ntag_buffer_pos, output.data() + 116,
|
|
||||||
payload_size - 60);
|
|
||||||
ntag_buffer_pos += payload_size - 60;
|
|
||||||
} else {
|
|
||||||
memcpy(ntag_data.data() + ntag_buffer_pos, output.data() + 56, payload_size);
|
|
||||||
}
|
|
||||||
goto loop1;
|
|
||||||
}
|
|
||||||
if (output[49] == 0x2a && output[56] == 0x04) {
|
|
||||||
LOG_INFO(Input, "Finished reading amiibo");
|
|
||||||
return DriverResult::Success;
|
|
||||||
}
|
|
||||||
if (output[49] == 0x2a) {
|
|
||||||
goto loop1;
|
|
||||||
}
|
|
||||||
if (attempt++ > 4) {
|
|
||||||
goto loop1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != DriverResult::Success) {
|
if (result != DriverResult::Success) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((mcu_report == MCUReport::NFCReadData || mcu_report == MCUReport::NFCState) &&
|
||||||
|
nfc_status == NFCStatus::TagLost) {
|
||||||
|
return DriverResult::ErrorReadingData;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mcu_report == MCUReport::NFCReadData && output[51] == 0x07) {
|
||||||
|
std::size_t payload_size = (output[54] << 8 | output[55]) & 0x7FF;
|
||||||
|
if (output[52] == 0x01) {
|
||||||
|
memcpy(ntag_data.data() + ntag_buffer_pos, output.data() + 116, payload_size - 60);
|
||||||
|
ntag_buffer_pos += payload_size - 60;
|
||||||
|
} else {
|
||||||
|
memcpy(ntag_data.data() + ntag_buffer_pos, output.data() + 56, payload_size);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) {
|
||||||
|
LOG_INFO(Input, "Finished reading amiibo");
|
||||||
|
return DriverResult::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore other state reports
|
||||||
|
if (mcu_report == MCUReport::NFCState) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (tries++ > timeout_limit) {
|
if (tries++ > timeout_limit) {
|
||||||
return DriverResult::Timeout;
|
return DriverResult::Timeout;
|
||||||
}
|
}
|
||||||
|
@ -298,7 +288,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 +305,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);
|
||||||
|
@ -338,7 +328,7 @@ DriverResult NfcProtocol::SendStartWaitingRecieveRequest(std::vector<u8>& output
|
||||||
return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output);
|
return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
DriverResult NfcProtocol::SendReadAmiiboRequest(std::vector<u8>& output, std::size_t ntag_pages) {
|
DriverResult NfcProtocol::SendReadAmiiboRequest(std::vector<u8>& output, NFCPages ntag_pages) {
|
||||||
NFCRequestState request{
|
NFCRequestState request{
|
||||||
.sub_command = MCUSubCommand::ReadDeviceMode,
|
.sub_command = MCUSubCommand::ReadDeviceMode,
|
||||||
.command_argument = NFCReadCommand::Ntag,
|
.command_argument = NFCReadCommand::Ntag,
|
||||||
|
@ -357,20 +347,19 @@ 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(NFCPages pages) const {
|
||||||
if (pages == 0) {
|
switch (pages) {
|
||||||
|
case NFCPages::Block0:
|
||||||
return {
|
return {
|
||||||
.block_count = 1,
|
.block_count = 1,
|
||||||
};
|
};
|
||||||
}
|
case NFCPages::Block45:
|
||||||
|
|
||||||
if (pages == 45) {
|
|
||||||
return {
|
return {
|
||||||
.block_count = 1,
|
.block_count = 1,
|
||||||
.blocks =
|
.blocks =
|
||||||
|
@ -378,9 +367,7 @@ NFCReadBlockCommand NfcProtocol::GetReadBlockCommand(std::size_t pages) const {
|
||||||
NFCReadBlock{0x00, 0x2C},
|
NFCReadBlock{0x00, 0x2C},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
case NFCPages::Block135:
|
||||||
|
|
||||||
if (pages == 135) {
|
|
||||||
return {
|
return {
|
||||||
.block_count = 3,
|
.block_count = 3,
|
||||||
.blocks =
|
.blocks =
|
||||||
|
@ -390,9 +377,7 @@ NFCReadBlockCommand NfcProtocol::GetReadBlockCommand(std::size_t pages) const {
|
||||||
{0x78, 0x86},
|
{0x78, 0x86},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
case NFCPages::Block231:
|
||||||
|
|
||||||
if (pages == 231) {
|
|
||||||
return {
|
return {
|
||||||
.block_count = 4,
|
.block_count = 4,
|
||||||
.blocks =
|
.blocks =
|
||||||
|
@ -403,9 +388,9 @@ NFCReadBlockCommand NfcProtocol::GetReadBlockCommand(std::size_t pages) const {
|
||||||
{0xb4, 0xe6},
|
{0xb4, 0xe6},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
default:
|
||||||
|
return {};
|
||||||
return {};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NfcProtocol::IsEnabled() const {
|
bool NfcProtocol::IsEnabled() const {
|
||||||
|
|
|
@ -51,9 +51,9 @@ private:
|
||||||
|
|
||||||
DriverResult SendStartWaitingRecieveRequest(std::vector<u8>& output);
|
DriverResult SendStartWaitingRecieveRequest(std::vector<u8>& output);
|
||||||
|
|
||||||
DriverResult SendReadAmiiboRequest(std::vector<u8>& output, std::size_t ntag_pages);
|
DriverResult SendReadAmiiboRequest(std::vector<u8>& output, NFCPages ntag_pages);
|
||||||
|
|
||||||
NFCReadBlockCommand GetReadBlockCommand(std::size_t pages) const;
|
NFCReadBlockCommand GetReadBlockCommand(NFCPages pages) const;
|
||||||
|
|
||||||
bool is_enabled{};
|
bool is_enabled{};
|
||||||
};
|
};
|
||||||
|
|
|
@ -224,9 +224,9 @@ void JoyconPoller::UpdatePasiveLeftPadInput(const InputReportPassive& input) {
|
||||||
Joycon::PasivePadButton::StickL,
|
Joycon::PasivePadButton::StickL,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (std::size_t i = 0; i < left_buttons.size(); ++i) {
|
for (auto left_button : left_buttons) {
|
||||||
const bool button_status = (input.button_input & static_cast<u32>(left_buttons[i])) != 0;
|
const bool button_status = (input.button_input & static_cast<u32>(left_button)) != 0;
|
||||||
const int button = static_cast<int>(left_buttons[i]);
|
const int button = static_cast<int>(left_button);
|
||||||
callbacks.on_button_data(button, button_status);
|
callbacks.on_button_data(button, button_status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,9 +241,9 @@ void JoyconPoller::UpdatePasiveRightPadInput(const InputReportPassive& input) {
|
||||||
Joycon::PasivePadButton::StickR,
|
Joycon::PasivePadButton::StickR,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (std::size_t i = 0; i < right_buttons.size(); ++i) {
|
for (auto right_button : right_buttons) {
|
||||||
const bool button_status = (input.button_input & static_cast<u32>(right_buttons[i])) != 0;
|
const bool button_status = (input.button_input & static_cast<u32>(right_button)) != 0;
|
||||||
const int button = static_cast<int>(right_buttons[i]);
|
const int button = static_cast<int>(right_button);
|
||||||
callbacks.on_button_data(button, button_status);
|
callbacks.on_button_data(button, button_status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -259,9 +259,9 @@ void JoyconPoller::UpdatePasiveProPadInput(const InputReportPassive& input) {
|
||||||
Joycon::PasivePadButton::StickL, Joycon::PasivePadButton::StickR,
|
Joycon::PasivePadButton::StickL, Joycon::PasivePadButton::StickR,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (std::size_t i = 0; i < pro_buttons.size(); ++i) {
|
for (auto pro_button : pro_buttons) {
|
||||||
const bool button_status = (input.button_input & static_cast<u32>(pro_buttons[i])) != 0;
|
const bool button_status = (input.button_input & static_cast<u32>(pro_button)) != 0;
|
||||||
const int button = static_cast<int>(pro_buttons[i]);
|
const int button = static_cast<int>(pro_button);
|
||||||
callbacks.on_button_data(button, button_status);
|
callbacks.on_button_data(button, button_status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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) {
|
||||||
|
@ -66,9 +63,9 @@ u8 RumbleProtocol::EncodeLowFrequency(f32 frequency) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 RumbleProtocol::EncodeHighAmplitude(f32 amplitude) const {
|
u8 RumbleProtocol::EncodeHighAmplitude(f32 amplitude) const {
|
||||||
/* More information about these values can be found here:
|
// More information about these values can be found here:
|
||||||
* https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md
|
// https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md
|
||||||
*/
|
|
||||||
static constexpr std::array<std::pair<f32, int>, 101> high_fequency_amplitude{
|
static constexpr std::array<std::pair<f32, int>, 101> high_fequency_amplitude{
|
||||||
std::pair<f32, int>{0.0f, 0x0},
|
std::pair<f32, int>{0.0f, 0x0},
|
||||||
{0.01f, 0x2},
|
{0.01f, 0x2},
|
||||||
|
@ -183,9 +180,9 @@ u8 RumbleProtocol::EncodeHighAmplitude(f32 amplitude) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 RumbleProtocol::EncodeLowAmplitude(f32 amplitude) const {
|
u16 RumbleProtocol::EncodeLowAmplitude(f32 amplitude) const {
|
||||||
/* More information about these values can be found here:
|
// More information about these values can be found here:
|
||||||
* https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md
|
// https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md
|
||||||
*/
|
|
||||||
static constexpr std::array<std::pair<f32, int>, 101> high_fequency_amplitude{
|
static constexpr std::array<std::pair<f32, int>, 101> high_fequency_amplitude{
|
||||||
std::pair<f32, int>{0.0f, 0x0040},
|
std::pair<f32, int>{0.0f, 0x0040},
|
||||||
{0.01f, 0x8040},
|
{0.01f, 0x8040},
|
||||||
|
|
Loading…
Reference in a new issue