Add error handling
This commit is contained in:
@@ -104,6 +104,7 @@ bool Joycons::IsPayloadCorrect(int status, std::span<const u8> buffer) {
|
|||||||
input_error_counter = 0;
|
input_error_counter = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Joycons::Setup() {
|
void Joycons::Setup() {
|
||||||
// Initialize all controllers as unplugged
|
// Initialize all controllers as unplugged
|
||||||
for (std::size_t port = 0; port < joycon_data.size(); ++port) {
|
for (std::size_t port = 0; port < joycon_data.size(); ++port) {
|
||||||
@@ -123,35 +124,39 @@ void Joycons::ScanThread(std::stop_token stop_token) {
|
|||||||
Common::SetCurrentThreadName("yuzu:input:JoyconScanThread");
|
Common::SetCurrentThreadName("yuzu:input:JoyconScanThread");
|
||||||
scan_thread_running = true;
|
scan_thread_running = true;
|
||||||
std::size_t port = 0;
|
std::size_t port = 0;
|
||||||
while (!stop_token.stop_requested()) {
|
// while (!stop_token.stop_requested()) {
|
||||||
LOG_INFO(Input, "Scanning for devices");
|
LOG_INFO(Input, "Scanning for devices");
|
||||||
SDL_hid_device_info* devs = SDL_hid_enumerate(0x057e, 0x0);
|
SDL_hid_device_info* devs = SDL_hid_enumerate(0x057e, 0x0);
|
||||||
SDL_hid_device_info* cur_dev = devs;
|
SDL_hid_device_info* cur_dev = devs;
|
||||||
|
|
||||||
while (cur_dev) {
|
while (cur_dev) {
|
||||||
LOG_WARNING(Input, "Device Found");
|
LOG_WARNING(Input, "Device Found");
|
||||||
LOG_WARNING(Input, "type : {:04X} {:04X}", cur_dev->vendor_id, cur_dev->product_id);
|
LOG_WARNING(Input, "type : {:04X} {:04X}", cur_dev->vendor_id, cur_dev->product_id);
|
||||||
bool skip_device = false;
|
bool skip_device = false;
|
||||||
|
|
||||||
for (std::size_t i = 0; i < joycon_data.size(); ++i) {
|
for (std::size_t i = 0; i < joycon_data.size(); ++i) {
|
||||||
if (Joycon::GetDeviceType(cur_dev) == joycon_data[i].type) {
|
Joycon::ControllerType type{};
|
||||||
LOG_WARNING(Input, "Device already exist");
|
const auto result = Joycon::GetDeviceType(cur_dev, type);
|
||||||
skip_device = true;
|
|
||||||
break;
|
if (result != Joycon::ErrorCode::Success || type == joycon_data[i].type) {
|
||||||
}
|
LOG_WARNING(Input, "Device already exist, result = {}, type = {}", result, type);
|
||||||
|
skip_device = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (!skip_device) {
|
|
||||||
if (Joycon::CheckDeviceAccess(joycon_data[port].joycon_handle, cur_dev)) {
|
|
||||||
LOG_WARNING(Input, "Device verified and accessible");
|
|
||||||
++port;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cur_dev = cur_dev->next;
|
|
||||||
}
|
}
|
||||||
GetJCEndpoint();
|
if (!skip_device) {
|
||||||
|
const auto result = Joycon::CheckDeviceAccess(joycon_data[port].joycon_handle, cur_dev);
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
if (result == Joycon::ErrorCode::Success) {
|
||||||
|
LOG_WARNING(Input, "Device verified and accessible");
|
||||||
|
++port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cur_dev = cur_dev->next;
|
||||||
}
|
}
|
||||||
|
GetJCEndpoint();
|
||||||
|
|
||||||
|
// std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||||
|
//}
|
||||||
scan_thread_running = false;
|
scan_thread_running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,12 +186,12 @@ void Joycons::GetJCEndpoint() {
|
|||||||
}
|
}
|
||||||
LOG_INFO(Input, "Initializing device {}", port);
|
LOG_INFO(Input, "Initializing device {}", port);
|
||||||
|
|
||||||
joycon.type = Joycon::GetDeviceType(handle);
|
Joycon::GetDeviceType(handle, joycon.type);
|
||||||
// joycon_data[port].mac= Joycon::GetMac();
|
// joycon_data[port].mac= Joycon::GetMac();
|
||||||
// SetSerialNumber(joycon_data[port]);
|
// SetSerialNumber(joycon_data[port]);
|
||||||
// SetVersionNumber(joycon_data[port]);
|
// SetVersionNumber(joycon_data[port]);
|
||||||
// SetDeviceType(joycon_data[port]);
|
// SetDeviceType(joycon_data[port]);
|
||||||
joycon.calibration = Joycon::GetFactoryCalibrationData(handle, joycon.type);
|
Joycon::GetFactoryCalibrationData(handle, joycon.calibration, joycon.type);
|
||||||
// GetColor(joycon_data[port]);
|
// GetColor(joycon_data[port]);
|
||||||
|
|
||||||
joycon.rumble_enabled = true;
|
joycon.rumble_enabled = true;
|
||||||
@@ -401,7 +406,7 @@ BasicMotion Joycons::GetMotionInput(std::span<const u8> buffer, Joycon::ImuCalib
|
|||||||
}
|
}
|
||||||
|
|
||||||
Common::Input::VibrationError Joycons::SetRumble(const PadIdentifier& identifier,
|
Common::Input::VibrationError Joycons::SetRumble(const PadIdentifier& identifier,
|
||||||
const Common::Input::VibrationStatus vibration) {
|
const Common::Input::VibrationStatus& vibration) {
|
||||||
const Joycon::VibrationValue native_vibration{
|
const Joycon::VibrationValue native_vibration{
|
||||||
.low_amplitude = vibration.low_amplitude,
|
.low_amplitude = vibration.low_amplitude,
|
||||||
.low_frequency = vibration.low_frequency,
|
.low_frequency = vibration.low_frequency,
|
||||||
@@ -418,7 +423,7 @@ Joycon::JoyconHandle& Joycons::GetHandle(PadIdentifier identifier) {
|
|||||||
|
|
||||||
PadIdentifier Joycons::GetIdentifier(std::size_t port) const {
|
PadIdentifier Joycons::GetIdentifier(std::size_t port) const {
|
||||||
return {
|
return {
|
||||||
.guid = Common::UUID{Common::INVALID_UUID},
|
.guid = Common::UUID{Common::InvalidUUID},
|
||||||
.port = port,
|
.port = port,
|
||||||
.pad = 0,
|
.pad = 0,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public:
|
|||||||
Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override;
|
Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override;
|
||||||
|
|
||||||
Common::Input::VibrationError SetRumble(
|
Common::Input::VibrationError SetRumble(
|
||||||
const PadIdentifier& identifier, const Common::Input::VibrationStatus vibration) override;
|
const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class PadAxes {
|
enum class PadAxes {
|
||||||
|
|||||||
@@ -14,9 +14,11 @@ u8 GetCounter(JoyconHandle& joycon_handle) {
|
|||||||
return joycon_handle.packet_counter;
|
return joycon_handle.packet_counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckDeviceAccess(JoyconHandle& joycon_handle, SDL_hid_device_info* device_info) {
|
ErrorCode CheckDeviceAccess(JoyconHandle& joycon_handle, SDL_hid_device_info* device_info) {
|
||||||
if (GetDeviceType(device_info) == ControllerType::None) {
|
ControllerType controller_type{ControllerType::None};
|
||||||
return false;
|
const auto result = GetDeviceType(device_info, controller_type);
|
||||||
|
if (result != ErrorCode::Success || controller_type == ControllerType::None) {
|
||||||
|
return ErrorCode::UnsupportedControllerType;
|
||||||
}
|
}
|
||||||
|
|
||||||
joycon_handle.handle =
|
joycon_handle.handle =
|
||||||
@@ -24,10 +26,10 @@ bool CheckDeviceAccess(JoyconHandle& joycon_handle, SDL_hid_device_info* device_
|
|||||||
if (!joycon_handle.handle) {
|
if (!joycon_handle.handle) {
|
||||||
LOG_ERROR(Input, "Yuzu can't gain access to this device: ID {:04X}:{:04X}.",
|
LOG_ERROR(Input, "Yuzu can't gain access to this device: ID {:04X}:{:04X}.",
|
||||||
device_info->vendor_id, device_info->product_id);
|
device_info->vendor_id, device_info->product_id);
|
||||||
return false;
|
return ErrorCode::HandleInUse;
|
||||||
}
|
}
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
||||||
return true;
|
return ErrorCode::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
f32 EncodeRumbleAmplification(f32 amplification) {
|
f32 EncodeRumbleAmplification(f32 amplification) {
|
||||||
@@ -41,7 +43,7 @@ f32 EncodeRumbleAmplification(f32 amplification) {
|
|||||||
return roundf((log2f(amplification) * 64) + 200);
|
return roundf((log2f(amplification) * 64) + 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetVibration(JoyconHandle& joycon_handle, VibrationValue vibration) {
|
ErrorCode SetVibration(JoyconHandle& joycon_handle, VibrationValue vibration) {
|
||||||
std::vector<u8> buffer(Joycon::max_resp_size);
|
std::vector<u8> buffer(Joycon::max_resp_size);
|
||||||
|
|
||||||
buffer[0] = static_cast<u8>(Joycon::OutputReport::RUMBLE_ONLY);
|
buffer[0] = static_cast<u8>(Joycon::OutputReport::RUMBLE_ONLY);
|
||||||
@@ -51,8 +53,7 @@ void SetVibration(JoyconHandle& joycon_handle, VibrationValue vibration) {
|
|||||||
for (std::size_t i = 0; i < Joycon::default_buffer.size(); ++i) {
|
for (std::size_t i = 0; i < Joycon::default_buffer.size(); ++i) {
|
||||||
buffer[2 + i] = Joycon::default_buffer[i];
|
buffer[2 + i] = Joycon::default_buffer[i];
|
||||||
}
|
}
|
||||||
SendData(joycon_handle, buffer, max_resp_size);
|
return SendData(joycon_handle, buffer, max_resp_size);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const u16 encoded_hf =
|
const u16 encoded_hf =
|
||||||
@@ -79,252 +80,354 @@ void SetVibration(JoyconHandle& joycon_handle, VibrationValue vibration) {
|
|||||||
buffer[5 + offset] = static_cast<u8>(encoded_amp);
|
buffer[5 + offset] = static_cast<u8>(encoded_amp);
|
||||||
}
|
}
|
||||||
|
|
||||||
SendData(joycon_handle, buffer, max_resp_size);
|
return SendData(joycon_handle, buffer, max_resp_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetImuConfig(JoyconHandle& joycon_handle, GyroSensitivity gsen, GyroPerformance gfrec,
|
ErrorCode SetImuConfig(JoyconHandle& joycon_handle, GyroSensitivity gsen, GyroPerformance gfrec,
|
||||||
AccelerometerSensitivity asen, AccelerometerPerformance afrec) {
|
AccelerometerSensitivity asen, AccelerometerPerformance afrec) {
|
||||||
const std::vector<u8> buffer{static_cast<u8>(gsen), static_cast<u8>(asen),
|
const std::vector<u8> 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;
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
||||||
SendSubCommand(joycon_handle, SubCommand::SET_IMU_SENSITIVITY, buffer, buffer.size());
|
const auto result = SendSubCommand(joycon_handle, SubCommand::SET_IMU_SENSITIVITY, buffer,
|
||||||
|
buffer.size(), output);
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetLedConfig(JoyconHandle& joycon_handle, u8 leds) {
|
ErrorCode SetLedConfig(JoyconHandle& joycon_handle, u8 leds) {
|
||||||
const std::vector<u8> buffer{leds};
|
const std::vector<u8> buffer{leds};
|
||||||
|
std::vector<u8> output;
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
||||||
SendSubCommand(joycon_handle, SubCommand::SET_PLAYER_LIGHTS, buffer, buffer.size());
|
const auto result =
|
||||||
|
SendSubCommand(joycon_handle, SubCommand::SET_PLAYER_LIGHTS, buffer, buffer.size(), output);
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetReportMode(JoyconHandle& joycon_handle, ReportMode report_mode) {
|
ErrorCode SetReportMode(JoyconHandle& joycon_handle, ReportMode report_mode) {
|
||||||
const std::vector<u8> buffer{static_cast<u8>(report_mode)};
|
const std::vector<u8> buffer{static_cast<u8>(report_mode)};
|
||||||
|
std::vector<u8> output;
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
||||||
SendSubCommand(joycon_handle, SubCommand::SET_REPORT_MODE, buffer, buffer.size());
|
const auto result =
|
||||||
|
SendSubCommand(joycon_handle, SubCommand::SET_REPORT_MODE, buffer, buffer.size(), output);
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color GetColor(JoyconHandle& joycon_handle) {
|
ErrorCode GetColor(JoyconHandle& joycon_handle, Color& color) {
|
||||||
Color joycon_color;
|
|
||||||
std::vector<u8> buffer;
|
std::vector<u8> buffer;
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
||||||
buffer = ReadSPI(joycon_handle, Joycon::CalAddr::COLOR_DATA, 12);
|
const auto result = ReadSPI(joycon_handle, Joycon::CalAddr::COLOR_DATA, buffer, 12);
|
||||||
joycon_color.body = static_cast<u32>((buffer[2] << 16) | (buffer[1] << 8) | buffer[0]);
|
|
||||||
joycon_color.buttons = static_cast<u32>((buffer[5] << 16) | (buffer[4] << 8) | buffer[3]);
|
|
||||||
joycon_color.left_grip = static_cast<u32>((buffer[8] << 16) | (buffer[7] << 8) | buffer[6]);
|
|
||||||
joycon_color.right_grip = static_cast<u32>((buffer[11] << 16) | (buffer[10] << 8) | buffer[9]);
|
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
||||||
return joycon_color;
|
if (result != ErrorCode::Success) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
color.body = static_cast<u32>((buffer[2] << 16) | (buffer[1] << 8) | buffer[0]);
|
||||||
|
color.buttons = static_cast<u32>((buffer[5] << 16) | (buffer[4] << 8) | buffer[3]);
|
||||||
|
color.left_grip = static_cast<u32>((buffer[8] << 16) | (buffer[7] << 8) | buffer[6]);
|
||||||
|
color.right_grip = static_cast<u32>((buffer[11] << 16) | (buffer[10] << 8) | buffer[9]);
|
||||||
|
return ErrorCode::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<u8, 6> GetMacAddress(JoyconHandle& joycon_handle) {
|
ErrorCode GetMacAddress(JoyconHandle& joycon_handle, MacAddress& mac_address) {
|
||||||
std::array<u8, 6> mac_address{};
|
|
||||||
wchar_t buffer[255];
|
wchar_t buffer[255];
|
||||||
const auto result =
|
const auto result =
|
||||||
SDL_hid_get_serial_number_string(joycon_handle.handle, buffer, std::size(buffer));
|
SDL_hid_get_serial_number_string(joycon_handle.handle, buffer, std::size(buffer));
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
LOG_ERROR(Input, "Unable to get mac address");
|
LOG_ERROR(Input, "Unable to get mac address {}", result);
|
||||||
return mac_address;
|
return ErrorCode::ErrorReadingData;
|
||||||
}
|
}
|
||||||
for (std::size_t i = 0; i < mac_address.size(); ++i) {
|
for (std::size_t i = 0; i < mac_address.size(); ++i) {
|
||||||
wchar_t value[3] = {buffer[i * 2], buffer[(i * 2) + 1]};
|
wchar_t value[3] = {buffer[i * 2], buffer[(i * 2) + 1]};
|
||||||
mac_address[i] = static_cast<u8>(std::stoi(value, 0, 16));
|
mac_address[i] = static_cast<u8>(std::stoi(value, 0, 16));
|
||||||
}
|
}
|
||||||
return mac_address;
|
return ErrorCode::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<u8, 15> GetSerialNumber(JoyconHandle& joycon_handle) {
|
ErrorCode GetSerialNumber(JoyconHandle& joycon_handle, SerialNumber& serial_number) {
|
||||||
std::array<u8, 15> serial_number;
|
std::vector<u8> buffer;
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
||||||
const std::vector<u8> buffer = ReadSPI(joycon_handle, Joycon::CalAddr::SERIAL_NUMBER, 16);
|
const auto result = ReadSPI(joycon_handle, Joycon::CalAddr::SERIAL_NUMBER, buffer, 16);
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
||||||
|
if (result != ErrorCode::Success) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
for (std::size_t i = 0; i < serial_number.size(); ++i) {
|
for (std::size_t i = 0; i < serial_number.size(); ++i) {
|
||||||
serial_number[i] = buffer[i + 1];
|
serial_number[i] = buffer[i + 1];
|
||||||
}
|
}
|
||||||
return serial_number;
|
return ErrorCode::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
ControllerType GetDeviceType(SDL_hid_device_info* device_info) {
|
ErrorCode GetDeviceType(SDL_hid_device_info* device_info, ControllerType& controller_type) {
|
||||||
if (device_info->vendor_id != 0x057e) {
|
constexpr u16 nintendo_vendor_id = 0x057e;
|
||||||
return ControllerType::None;
|
constexpr u16 left_joycon_id = 0x2006;
|
||||||
|
constexpr u16 right_joycon_id = 0x2007;
|
||||||
|
constexpr u16 pro_controller_id = 0x2009;
|
||||||
|
|
||||||
|
if (device_info->vendor_id != nintendo_vendor_id) {
|
||||||
|
return ErrorCode::UnsupportedControllerType;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (device_info->product_id) {
|
switch (device_info->product_id) {
|
||||||
case 0x2006:
|
case left_joycon_id:
|
||||||
return ControllerType::Left;
|
controller_type = ControllerType::Left;
|
||||||
case 0x2007:
|
break;
|
||||||
return ControllerType::Right;
|
case right_joycon_id:
|
||||||
case 0x2009:
|
controller_type = ControllerType::Right;
|
||||||
return ControllerType::Pro;
|
break;
|
||||||
|
case pro_controller_id:
|
||||||
|
controller_type = ControllerType::Pro;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return ControllerType::None;
|
controller_type = ControllerType::None;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
return ErrorCode::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
ControllerType GetDeviceType(JoyconHandle& joycon_handle) {
|
ErrorCode GetDeviceType(JoyconHandle& joycon_handle, ControllerType& controller_type) {
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
|
||||||
const std::vector<u8> buffer = ReadSPI(joycon_handle, Joycon::CalAddr::DEVICE_TYPE, 1);
|
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
|
||||||
return static_cast<Joycon::ControllerType>(buffer[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
u16 GetVersionNumber([[maybe_unused]] JoyconHandle& joycon_handle) {
|
|
||||||
// Not implemented
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
JoyStickCalibration GetLeftJoyStickCalibration(JoyconHandle& joycon_handle,
|
|
||||||
bool is_factory_calibration) {
|
|
||||||
JoyStickCalibration joystick{};
|
|
||||||
std::vector<u8> buffer;
|
std::vector<u8> buffer;
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
||||||
|
const auto result = ReadSPI(joycon_handle, Joycon::CalAddr::DEVICE_TYPE, buffer, 1);
|
||||||
|
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
||||||
|
if (result != ErrorCode::Success) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
controller_type = static_cast<Joycon::ControllerType>(buffer[0]);
|
||||||
|
return ErrorCode::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorCode GetVersionNumber([[maybe_unused]] JoyconHandle& joycon_handle, FirmwareVersion& version) {
|
||||||
|
// Not implemented
|
||||||
|
version = FirmwareVersion::Rev_0;
|
||||||
|
return ErrorCode::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorCode GetLeftJoyStickCalibration(JoyconHandle& joycon_handle, JoyStickCalibration& calibration,
|
||||||
|
bool is_factory_calibration) {
|
||||||
|
std::vector<u8> buffer;
|
||||||
|
ErrorCode result{ErrorCode::Unknown};
|
||||||
|
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
||||||
if (is_factory_calibration) {
|
if (is_factory_calibration) {
|
||||||
buffer = ReadSPI(joycon_handle, CalAddr::FACT_LEFT_DATA, 9);
|
result = ReadSPI(joycon_handle, CalAddr::FACT_LEFT_DATA, buffer, 9);
|
||||||
} else {
|
} else {
|
||||||
buffer = ReadSPI(joycon_handle, CalAddr::USER_LEFT_DATA, 9);
|
result = ReadSPI(joycon_handle, CalAddr::USER_LEFT_DATA, buffer, 9);
|
||||||
}
|
}
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
||||||
|
|
||||||
joystick.x.max = static_cast<u16>(((buffer[1] & 0x0F) << 8) | buffer[0]);
|
if (result != ErrorCode::Success) {
|
||||||
joystick.y.max = static_cast<u16>((buffer[2] << 4) | (buffer[1] >> 4));
|
return result;
|
||||||
joystick.x.center = static_cast<u16>(((buffer[4] & 0x0F) << 8) | buffer[3]);
|
}
|
||||||
joystick.y.center = static_cast<u16>((buffer[5] << 4) | (buffer[4] >> 4));
|
|
||||||
joystick.x.min = static_cast<u16>(((buffer[7] & 0x0F) << 8) | buffer[6]);
|
calibration.x.max = static_cast<u16>(((buffer[1] & 0x0F) << 8) | buffer[0]);
|
||||||
joystick.y.min = static_cast<u16>((buffer[8] << 4) | (buffer[7] >> 4));
|
calibration.y.max = static_cast<u16>((buffer[2] << 4) | (buffer[1] >> 4));
|
||||||
|
calibration.x.center = static_cast<u16>(((buffer[4] & 0x0F) << 8) | buffer[3]);
|
||||||
|
calibration.y.center = static_cast<u16>((buffer[5] << 4) | (buffer[4] >> 4));
|
||||||
|
calibration.x.min = static_cast<u16>(((buffer[7] & 0x0F) << 8) | buffer[6]);
|
||||||
|
calibration.y.min = static_cast<u16>((buffer[8] << 4) | (buffer[7] >> 4));
|
||||||
|
|
||||||
// Nintendo fix for drifting stick
|
// Nintendo fix for drifting stick
|
||||||
// buffer = ReadSPI(0x60, 0x86 , 16);
|
// result = ReadSPI(0x60, 0x86 ,buffer, 16);
|
||||||
// joystick.deadzone = (u16)((buffer[4] << 8) & 0xF00 | buffer[3]);
|
// calibration.deadzone = (u16)((buffer[4] << 8) & 0xF00 | buffer[3]);
|
||||||
return joystick;
|
return ErrorCode::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
JoyStickCalibration GetRightJoyStickCalibration(JoyconHandle& joycon_handle,
|
ErrorCode GetRightJoyStickCalibration(JoyconHandle& joycon_handle, JoyStickCalibration& calibration,
|
||||||
bool is_factory_calibration) {
|
bool is_factory_calibration) {
|
||||||
JoyStickCalibration joystick{};
|
|
||||||
std::vector<u8> buffer;
|
std::vector<u8> buffer;
|
||||||
|
ErrorCode result{ErrorCode::Unknown};
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
||||||
if (is_factory_calibration) {
|
if (is_factory_calibration) {
|
||||||
buffer = ReadSPI(joycon_handle, CalAddr::FACT_RIGHT_DATA, 9);
|
result = ReadSPI(joycon_handle, CalAddr::FACT_RIGHT_DATA, buffer, 9);
|
||||||
} else {
|
} else {
|
||||||
buffer = ReadSPI(joycon_handle, CalAddr::USER_RIGHT_DATA, 9);
|
result = ReadSPI(joycon_handle, CalAddr::USER_RIGHT_DATA, buffer, 9);
|
||||||
}
|
}
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
||||||
|
|
||||||
joystick.x.center = static_cast<u16>(((buffer[1] & 0x0F) << 8) | buffer[0]);
|
if (result != ErrorCode::Success) {
|
||||||
joystick.y.center = static_cast<u16>((buffer[2] << 4) | (buffer[1] >> 4));
|
return result;
|
||||||
joystick.x.min = static_cast<u16>(((buffer[4] & 0x0F) << 8) | buffer[3]);
|
}
|
||||||
joystick.y.min = static_cast<u16>((buffer[5] << 4) | (buffer[4] >> 4));
|
|
||||||
joystick.x.max = static_cast<u16>(((buffer[7] & 0x0F) << 8) | buffer[6]);
|
calibration.x.center = static_cast<u16>(((buffer[1] & 0x0F) << 8) | buffer[0]);
|
||||||
joystick.y.max = static_cast<u16>((buffer[8] << 4) | (buffer[7] >> 4));
|
calibration.y.center = static_cast<u16>((buffer[2] << 4) | (buffer[1] >> 4));
|
||||||
|
calibration.x.min = static_cast<u16>(((buffer[4] & 0x0F) << 8) | buffer[3]);
|
||||||
|
calibration.y.min = static_cast<u16>((buffer[5] << 4) | (buffer[4] >> 4));
|
||||||
|
calibration.x.max = static_cast<u16>(((buffer[7] & 0x0F) << 8) | buffer[6]);
|
||||||
|
calibration.y.max = static_cast<u16>((buffer[8] << 4) | (buffer[7] >> 4));
|
||||||
|
|
||||||
// Nintendo fix for drifting stick
|
// Nintendo fix for drifting stick
|
||||||
// buffer = ReadSPI(0x60, 0x98 , 16);
|
// buffer = ReadSPI(0x60, 0x98 , 16);
|
||||||
// joystick.deadzone = (u16)((buffer[4] << 8) & 0xF00 | buffer[3]);
|
// joystick.deadzone = (u16)((buffer[4] << 8) & 0xF00 | buffer[3]);
|
||||||
return joystick;
|
return ErrorCode::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImuCalibration GetImuCalibration(JoyconHandle& joycon_handle, bool is_factory_calibration) {
|
ErrorCode GetImuCalibration(JoyconHandle& joycon_handle, ImuCalibration& calibration,
|
||||||
ImuCalibration imu{};
|
bool is_factory_calibration) {
|
||||||
std::vector<u8> buffer;
|
std::vector<u8> buffer;
|
||||||
|
ErrorCode result{ErrorCode::Unknown};
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
||||||
if (is_factory_calibration) {
|
if (is_factory_calibration) {
|
||||||
buffer = ReadSPI(joycon_handle, CalAddr::FACT_IMU_DATA, 24);
|
result = ReadSPI(joycon_handle, CalAddr::FACT_IMU_DATA, buffer, 24);
|
||||||
} else {
|
} else {
|
||||||
buffer = ReadSPI(joycon_handle, CalAddr::USER_IMU_DATA, 24);
|
result = ReadSPI(joycon_handle, CalAddr::USER_IMU_DATA, buffer, 24);
|
||||||
}
|
}
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
||||||
for (std::size_t i = 0; i < imu.accelerometer.size(); ++i) {
|
|
||||||
const std::size_t index = i * 2;
|
if (result != ErrorCode::Success) {
|
||||||
imu.accelerometer[i].offset = static_cast<s16>(buffer[index] | (buffer[index + 1] << 8));
|
return result;
|
||||||
imu.accelerometer[i].scale = static_cast<s16>(buffer[index + 6] | (buffer[index + 7] << 8));
|
|
||||||
}
|
}
|
||||||
for (std::size_t i = 0; i < imu.gyro.size(); ++i) {
|
|
||||||
|
for (std::size_t i = 0; i < calibration.accelerometer.size(); ++i) {
|
||||||
const std::size_t index = i * 2;
|
const std::size_t index = i * 2;
|
||||||
imu.gyro[i].offset = static_cast<s16>(buffer[index + 12] | (buffer[index + 13] << 8));
|
calibration.accelerometer[i].offset =
|
||||||
imu.gyro[i].scale = static_cast<s16>(buffer[index + 18] | (buffer[index + 19] << 8));
|
static_cast<s16>(buffer[index] | (buffer[index + 1] << 8));
|
||||||
|
calibration.accelerometer[i].scale =
|
||||||
|
static_cast<s16>(buffer[index + 6] | (buffer[index + 7] << 8));
|
||||||
}
|
}
|
||||||
return imu;
|
for (std::size_t i = 0; i < calibration.gyro.size(); ++i) {
|
||||||
|
const std::size_t index = i * 2;
|
||||||
|
calibration.gyro[i].offset =
|
||||||
|
static_cast<s16>(buffer[index + 12] | (buffer[index + 13] << 8));
|
||||||
|
calibration.gyro[i].scale =
|
||||||
|
static_cast<s16>(buffer[index + 18] | (buffer[index + 19] << 8));
|
||||||
|
}
|
||||||
|
return ErrorCode::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
CalibrationData GetUserCalibrationData(JoyconHandle& joycon_handle,
|
ErrorCode GetUserCalibrationData(JoyconHandle& joycon_handle, CalibrationData& calibration_data,
|
||||||
ControllerType controller_type) {
|
ControllerType controller_type) {
|
||||||
CalibrationData calibration{};
|
ErrorCode result{ErrorCode::Unknown};
|
||||||
switch (controller_type) {
|
switch (controller_type) {
|
||||||
case ControllerType::Left:
|
case ControllerType::Left:
|
||||||
calibration.left_stick = GetLeftJoyStickCalibration(joycon_handle, false);
|
result = GetLeftJoyStickCalibration(joycon_handle, calibration_data.left_stick, false);
|
||||||
|
if (result != ErrorCode::Success) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ControllerType::Right:
|
case ControllerType::Right:
|
||||||
calibration.right_stick = GetRightJoyStickCalibration(joycon_handle, false);
|
result = GetRightJoyStickCalibration(joycon_handle, calibration_data.right_stick, false);
|
||||||
|
if (result != ErrorCode::Success) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Joycon::ControllerType::Pro:
|
case Joycon::ControllerType::Pro:
|
||||||
calibration.left_stick = GetLeftJoyStickCalibration(joycon_handle, false);
|
result = GetLeftJoyStickCalibration(joycon_handle, calibration_data.left_stick, false);
|
||||||
calibration.right_stick = GetRightJoyStickCalibration(joycon_handle, false);
|
if (result != ErrorCode::Success) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = GetRightJoyStickCalibration(joycon_handle, calibration_data.right_stick, false);
|
||||||
|
if (result != ErrorCode::Success) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
return ErrorCode::UnsupportedControllerType;
|
||||||
}
|
}
|
||||||
|
|
||||||
calibration.imu = GetImuCalibration(joycon_handle, false);
|
result = GetImuCalibration(joycon_handle, calibration_data.imu, false);
|
||||||
return calibration;
|
|
||||||
|
if (result != ErrorCode::Success) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorCode::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
CalibrationData GetFactoryCalibrationData(JoyconHandle& joycon_handle,
|
ErrorCode GetFactoryCalibrationData(JoyconHandle& joycon_handle, CalibrationData& calibration_data,
|
||||||
ControllerType controller_type) {
|
ControllerType controller_type) {
|
||||||
CalibrationData calibration{};
|
ErrorCode result{ErrorCode::Unknown};
|
||||||
switch (controller_type) {
|
switch (controller_type) {
|
||||||
case ControllerType::Left:
|
case ControllerType::Left:
|
||||||
calibration.left_stick = GetLeftJoyStickCalibration(joycon_handle, true);
|
result = GetLeftJoyStickCalibration(joycon_handle, calibration_data.left_stick, true);
|
||||||
|
if (result != ErrorCode::Success) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ControllerType::Right:
|
case ControllerType::Right:
|
||||||
calibration.right_stick = GetRightJoyStickCalibration(joycon_handle, true);
|
result = GetRightJoyStickCalibration(joycon_handle, calibration_data.right_stick, true);
|
||||||
|
if (result != ErrorCode::Success) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Joycon::ControllerType::Pro:
|
case Joycon::ControllerType::Pro:
|
||||||
calibration.left_stick = GetLeftJoyStickCalibration(joycon_handle, true);
|
result = GetLeftJoyStickCalibration(joycon_handle, calibration_data.left_stick, true);
|
||||||
calibration.right_stick = GetRightJoyStickCalibration(joycon_handle, true);
|
if (result != ErrorCode::Success) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = GetRightJoyStickCalibration(joycon_handle, calibration_data.right_stick, true);
|
||||||
|
if (result != ErrorCode::Success) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
return ErrorCode::UnsupportedControllerType;
|
||||||
}
|
}
|
||||||
|
|
||||||
calibration.imu = GetImuCalibration(joycon_handle, true);
|
result = GetImuCalibration(joycon_handle, calibration_data.imu, true);
|
||||||
return calibration;
|
|
||||||
|
if (result != ErrorCode::Success) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorCode::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnableImu(JoyconHandle& joycon_handle, bool enable) {
|
ErrorCode EnableImu(JoyconHandle& joycon_handle, bool enable) {
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
|
||||||
const std::vector<u8> buffer{static_cast<u8>(enable ? 1 : 0)};
|
const std::vector<u8> buffer{static_cast<u8>(enable ? 1 : 0)};
|
||||||
SendSubCommand(joycon_handle, SubCommand::ENABLE_IMU, buffer, buffer.size());
|
std::vector<u8> output;
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnableRumble(JoyconHandle& joycon_handle, bool enable) {
|
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
||||||
const std::vector<u8> buffer{static_cast<u8>(enable ? 1 : 0)};
|
const auto result =
|
||||||
SendSubCommand(joycon_handle, SubCommand::ENABLE_VIBRATION, buffer, buffer.size());
|
SendSubCommand(joycon_handle, SubCommand::ENABLE_IMU, buffer, buffer.size(), output);
|
||||||
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendData(JoyconHandle& joycon_handle, std::span<const u8> buffer, std::size_t size) {
|
ErrorCode EnableRumble(JoyconHandle& joycon_handle, bool enable) {
|
||||||
SDL_hid_write(joycon_handle.handle, buffer.data(), size);
|
const std::vector<u8> buffer{static_cast<u8>(enable ? 1 : 0)};
|
||||||
|
std::vector<u8> output;
|
||||||
|
SDL_hid_set_nonblocking(joycon_handle.handle, 0);
|
||||||
|
const auto result =
|
||||||
|
SendSubCommand(joycon_handle, SubCommand::ENABLE_VIBRATION, buffer, buffer.size(), output);
|
||||||
|
SDL_hid_set_nonblocking(joycon_handle.handle, 1);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> GetResponse(JoyconHandle& joycon_handle, SubCommand sc) {
|
ErrorCode SendData(JoyconHandle& joycon_handle, std::span<const u8> buffer, std::size_t size) {
|
||||||
|
const auto result = SDL_hid_write(joycon_handle.handle, buffer.data(), size);
|
||||||
|
if (result == -1) {
|
||||||
|
return ErrorCode::ErrorWritingData;
|
||||||
|
}
|
||||||
|
return ErrorCode::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorCode GetResponse(JoyconHandle& joycon_handle, SubCommand sc, std::vector<u8>& output) {
|
||||||
constexpr int timeout_mili = 100;
|
constexpr int timeout_mili = 100;
|
||||||
|
constexpr int max_tries = 10;
|
||||||
int tries = 0;
|
int tries = 0;
|
||||||
std::vector<u8> buffer(max_resp_size);
|
std::vector<u8> buffer(max_resp_size);
|
||||||
do {
|
do {
|
||||||
int result =
|
int result =
|
||||||
SDL_hid_read_timeout(joycon_handle.handle, buffer.data(), max_resp_size, timeout_time);
|
SDL_hid_read_timeout(joycon_handle.handle, buffer.data(), max_resp_size, timeout_mili);
|
||||||
if (result < 1) {
|
if (result < 1) {
|
||||||
LOG_ERROR(Input, "No response from joycon");
|
LOG_ERROR(Input, "No response from joycon");
|
||||||
}
|
}
|
||||||
tries++;
|
tries++;
|
||||||
} while (tries < 10 && buffer[0] != 0x21 && buffer[14] != static_cast<u8>(sc));
|
} while (tries < max_tries && buffer[0] != 0x21 && buffer[14] != static_cast<u8>(sc));
|
||||||
return buffer;
|
|
||||||
|
if (tries >= max_tries) {
|
||||||
|
return ErrorCode::Timeout;
|
||||||
|
}
|
||||||
|
if (buffer[0] != 0x21 && buffer[14] != static_cast<u8>(sc)) {
|
||||||
|
return ErrorCode::WrongReply;
|
||||||
|
}
|
||||||
|
|
||||||
|
output = buffer;
|
||||||
|
return ErrorCode::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> SendSubCommand(JoyconHandle& joycon_handle, SubCommand sc,
|
ErrorCode SendSubCommand(JoyconHandle& joycon_handle, SubCommand sc, std::span<const u8> buffer,
|
||||||
std::span<const u8> buffer, std::size_t size) {
|
std::size_t size, std::vector<u8>& output) {
|
||||||
std::vector<u8> local_buffer(size + 11);
|
std::vector<u8> local_buffer(size + 11);
|
||||||
|
|
||||||
local_buffer[0] = static_cast<u8>(OutputReport::RUMBLE_AND_SUBCMD);
|
local_buffer[0] = static_cast<u8>(OutputReport::RUMBLE_AND_SUBCMD);
|
||||||
@@ -337,26 +440,40 @@ std::vector<u8> SendSubCommand(JoyconHandle& joycon_handle, SubCommand sc,
|
|||||||
local_buffer[11 + i] = buffer[i];
|
local_buffer[11 + i] = buffer[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
SendData(joycon_handle, local_buffer, size + 11);
|
auto result = SendData(joycon_handle, local_buffer, size + 11);
|
||||||
return GetResponse(joycon_handle, sc);
|
|
||||||
|
if (result != ErrorCode::Success) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = GetResponse(joycon_handle, sc, output);
|
||||||
|
|
||||||
|
return ErrorCode::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> ReadSPI(JoyconHandle& joycon_handle, CalAddr addr, u8 size) {
|
ErrorCode ReadSPI(JoyconHandle& joycon_handle, CalAddr addr, std::vector<u8>& output, u8 size) {
|
||||||
constexpr std::size_t max_tries = 10;
|
constexpr std::size_t max_tries = 10;
|
||||||
|
std::size_t tries = 0;
|
||||||
std::vector<u8> buffer = {0x00, 0x00, 0x00, 0x00, size};
|
std::vector<u8> 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);
|
||||||
buffer[1] = static_cast<u8>((static_cast<u16>(addr) & 0xFF00) >> 8);
|
buffer[1] = static_cast<u8>((static_cast<u16>(addr) & 0xFF00) >> 8);
|
||||||
for (std::size_t i = 0; i < max_tries; ++i) {
|
do {
|
||||||
local_buffer =
|
const auto result = SendSubCommand(joycon_handle, SubCommand::SPI_FLASH_READ, buffer,
|
||||||
SendSubCommand(joycon_handle, SubCommand::SPI_FLASH_READ, buffer, buffer.size());
|
buffer.size(), local_buffer);
|
||||||
// Recieved packed has to match with the requested address
|
if (result != ErrorCode::Success) {
|
||||||
if (local_buffer[15] == buffer[0] && local_buffer[16] == buffer[1]) {
|
return result;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
tries++;
|
||||||
|
} while (tries < max_tries && (local_buffer[15] != buffer[0] || local_buffer[16] != buffer[1]));
|
||||||
|
|
||||||
|
if (tries >= max_tries) {
|
||||||
|
return ErrorCode::Timeout;
|
||||||
}
|
}
|
||||||
return std::vector<u8>(local_buffer.begin() + 20, local_buffer.end());
|
|
||||||
|
output = std::vector<u8>(local_buffer.begin() + 20, local_buffer.end());
|
||||||
|
return ErrorCode::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace InputCommon::Joycon
|
} // namespace InputCommon::Joycon
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ namespace InputCommon::Joycon {
|
|||||||
constexpr u32 max_resp_size = 49;
|
constexpr u32 max_resp_size = 49;
|
||||||
constexpr std::array<u8, 8> default_buffer{0x0, 0x1, 0x40, 0x40, 0x0, 0x1, 0x40, 0x40};
|
constexpr std::array<u8, 8> default_buffer{0x0, 0x1, 0x40, 0x40, 0x0, 0x1, 0x40, 0x40};
|
||||||
|
|
||||||
|
using MacAddress = std::array<u8, 6>;
|
||||||
|
using SerialNumber = std::array<u8, 15>;
|
||||||
|
|
||||||
enum class ControllerType {
|
enum class ControllerType {
|
||||||
None,
|
None,
|
||||||
Left,
|
Left,
|
||||||
@@ -170,6 +173,21 @@ enum class AccelerometerPerformance {
|
|||||||
HZ100, // Default
|
HZ100, // Default
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class FirmwareVersion {
|
||||||
|
Rev_0,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ErrorCode {
|
||||||
|
Success,
|
||||||
|
WrongReply,
|
||||||
|
Timeout,
|
||||||
|
UnsupportedControllerType,
|
||||||
|
HandleInUse,
|
||||||
|
ErrorReadingData,
|
||||||
|
ErrorWritingData,
|
||||||
|
Unknown,
|
||||||
|
};
|
||||||
|
|
||||||
struct ImuSensorCalibration {
|
struct ImuSensorCalibration {
|
||||||
s16 offset;
|
s16 offset;
|
||||||
s16 scale;
|
s16 scale;
|
||||||
@@ -226,21 +244,10 @@ u8 GetCounter(JoyconHandle& joycon_handle);
|
|||||||
/**
|
/**
|
||||||
* Verifies and sets the joycon_handle if device is valid
|
* Verifies and sets the joycon_handle if device is valid
|
||||||
* @param joycon_handle device to send the data
|
* @param joycon_handle device to send the data
|
||||||
* @param device device info from the driver
|
* @param device info from the driver
|
||||||
* @returns true if the device is valid
|
* @returns true if the device is valid
|
||||||
*/
|
*/
|
||||||
bool CheckDeviceAccess(JoyconHandle& joycon_handle, SDL_hid_device_info* device);
|
ErrorCode CheckDeviceAccess(JoyconHandle& joycon_handle, SDL_hid_device_info* device);
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a request to set the configuration of the motion sensor
|
|
||||||
* @param joycon_handle device to send the data
|
|
||||||
* @param gsen gyro sensitivity
|
|
||||||
* @param gfrec gyro update frequency
|
|
||||||
* @param asen accelerometer sensitivity
|
|
||||||
* @param afrec accelerometer update frequency
|
|
||||||
*/
|
|
||||||
void SetImuConfig(JoyconHandle& joycon_handle, GyroSensitivity gsen, GyroPerformance gfrec,
|
|
||||||
AccelerometerSensitivity asen, AccelerometerPerformance afrec);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encondes the amplitude to be sended on a packet
|
* Encondes the amplitude to be sended on a packet
|
||||||
@@ -254,63 +261,74 @@ f32 EncodeRumbleAmplification(f32 amplification);
|
|||||||
* @param joycon_handle device to send the data
|
* @param joycon_handle device to send the data
|
||||||
* @param vibration amplitude and frequency of the vibration
|
* @param vibration amplitude and frequency of the vibration
|
||||||
*/
|
*/
|
||||||
void SetVibration(JoyconHandle& joycon_handle, VibrationValue vibration);
|
ErrorCode SetVibration(JoyconHandle& joycon_handle, VibrationValue vibration);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a request to set the configuration of the motion sensor
|
||||||
|
* @param joycon_handle device to send the data
|
||||||
|
* @param gsen gyro sensitivity
|
||||||
|
* @param gfrec gyro update frequency
|
||||||
|
* @param asen accelerometer sensitivity
|
||||||
|
* @param afrec accelerometer update frequency
|
||||||
|
*/
|
||||||
|
ErrorCode SetImuConfig(JoyconHandle& joycon_handle, GyroSensitivity gsen, GyroPerformance gfrec,
|
||||||
|
AccelerometerSensitivity asen, AccelerometerPerformance afrec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a request to set the polling mode of the joycon
|
* Sends a request to set the polling mode of the joycon
|
||||||
* @param joycon_handle device to send the data
|
* @param joycon_handle device to send the data
|
||||||
* @param report_mode polling mode to be set
|
* @param report_mode polling mode to be set
|
||||||
*/
|
*/
|
||||||
void SetReportMode(JoyconHandle& joycon_handle, Joycon::ReportMode report_mode);
|
ErrorCode SetReportMode(JoyconHandle& joycon_handle, Joycon::ReportMode report_mode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a request to set a specific led pattern
|
* Sends a request to set a specific led pattern
|
||||||
* @param joycon_handle device to send the data
|
* @param joycon_handle device to send the data
|
||||||
* @param leds led pattern to be set
|
* @param leds led pattern to be set
|
||||||
*/
|
*/
|
||||||
void SetLedConfig(JoyconHandle& joycon_handle, u8 leds);
|
ErrorCode SetLedConfig(JoyconHandle& joycon_handle, u8 leds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a request to obtain the joycon colors from memory
|
* Sends a request to obtain the joycon colors from memory
|
||||||
* @param joycon_handle device to read the data
|
* @param joycon_handle device to read the data
|
||||||
* @returns color object with the colors of the joycon
|
* @returns color object with the colors of the joycon
|
||||||
*/
|
*/
|
||||||
Color GetColor(JoyconHandle& joycon_handle);
|
ErrorCode GetColor(JoyconHandle& joycon_handle, Color& color);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a request to obtain the joycon mac address from handle
|
* Sends a request to obtain the joycon mac address from handle
|
||||||
* @param joycon_handle device to read the data
|
* @param joycon_handle device to read the data
|
||||||
* @returns array containing the mac address
|
* @returns array containing the mac address
|
||||||
*/
|
*/
|
||||||
std::array<u8, 6> GetMacAddress(JoyconHandle& joycon_handle);
|
ErrorCode GetMacAddress(JoyconHandle& joycon_handle, MacAddress& mac_address);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a request to obtain the joycon serial number from memory
|
* Sends a request to obtain the joycon serial number from memory
|
||||||
* @param joycon_handle device to read the data
|
* @param joycon_handle device to read the data
|
||||||
* @returns array containing the serial number
|
* @returns array containing the serial number
|
||||||
*/
|
*/
|
||||||
std::array<u8, 15> GetSerialNumber(JoyconHandle& joycon_handle);
|
ErrorCode GetSerialNumber(JoyconHandle& joycon_handle, SerialNumber& serial_number);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a request to obtain the joycon type from handle
|
* Sends a request to obtain the joycon type from handle
|
||||||
* @param joycon_handle device to read the data
|
* @param joycon_handle device to read the data
|
||||||
* @returns controller type of the joycon
|
* @returns controller type of the joycon
|
||||||
*/
|
*/
|
||||||
ControllerType GetDeviceType(JoyconHandle& joycon_handle);
|
ErrorCode GetDeviceType(JoyconHandle& joycon_handle, ControllerType& controller_type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a request to obtain the joycon tyoe from memory
|
* Sends a request to obtain the joycon tyoe from memory
|
||||||
* @param joycon_handle device to read the data
|
* @param joycon_handle device to read the data
|
||||||
* @returns controller type of the joycon
|
* @returns controller type of the joycon
|
||||||
*/
|
*/
|
||||||
ControllerType GetDeviceType(SDL_hid_device_info* device_info);
|
ErrorCode GetDeviceType(SDL_hid_device_info* device_info, ControllerType& controller_type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a request to obtain the joycon firmware version
|
* Sends a request to obtain the joycon firmware version
|
||||||
* @param joycon_handle device to read the data
|
* @param joycon_handle device to read the data
|
||||||
* @returns u16 with the version number
|
* @returns u16 with the version number
|
||||||
*/
|
*/
|
||||||
u16 GetVersionNumber(JoyconHandle& joycon_handle);
|
ErrorCode GetVersionNumber(JoyconHandle& joycon_handle, FirmwareVersion& version);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a request to obtain the left stick calibration from memory
|
* Sends a request to obtain the left stick calibration from memory
|
||||||
@@ -318,8 +336,8 @@ u16 GetVersionNumber(JoyconHandle& joycon_handle);
|
|||||||
* @param is_factory_calibration if true factory values will be returned
|
* @param is_factory_calibration if true factory values will be returned
|
||||||
* @returns JoyStickCalibration of the left joystick
|
* @returns JoyStickCalibration of the left joystick
|
||||||
*/
|
*/
|
||||||
JoyStickCalibration GetLeftJoyStickCalibration(JoyconHandle& joycon_handle,
|
ErrorCode GetLeftJoyStickCalibration(JoyconHandle& joycon_handle, JoyStickCalibration& calibration,
|
||||||
bool is_factory_calibration);
|
bool is_factory_calibration);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a request to obtain the right stick calibration from memory
|
* Sends a request to obtain the right stick calibration from memory
|
||||||
@@ -327,8 +345,8 @@ JoyStickCalibration GetLeftJoyStickCalibration(JoyconHandle& joycon_handle,
|
|||||||
* @param is_factory_calibration if true factory values will be returned
|
* @param is_factory_calibration if true factory values will be returned
|
||||||
* @returns JoyStickCalibration of the left joystick
|
* @returns JoyStickCalibration of the left joystick
|
||||||
*/
|
*/
|
||||||
JoyStickCalibration GetRightJoyStickCalibration(JoyconHandle& joycon_handle,
|
ErrorCode GetRightJoyStickCalibration(JoyconHandle& joycon_handle, JoyStickCalibration& calibration,
|
||||||
bool is_factory_calibration);
|
bool is_factory_calibration);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a request to obtain the motion calibration from memory
|
* Sends a request to obtain the motion calibration from memory
|
||||||
@@ -336,7 +354,8 @@ JoyStickCalibration GetRightJoyStickCalibration(JoyconHandle& joycon_handle,
|
|||||||
* @param is_factory_calibration if true factory values will be returned
|
* @param is_factory_calibration if true factory values will be returned
|
||||||
* @returns ImuCalibration of the joystick motion
|
* @returns ImuCalibration of the joystick motion
|
||||||
*/
|
*/
|
||||||
ImuCalibration GetImuCalibration(JoyconHandle& joycon_handle, bool is_factory_calibration);
|
ErrorCode GetImuCalibration(JoyconHandle& joycon_handle, ImuCalibration& calibration,
|
||||||
|
bool is_factory_calibration);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests user calibration from the joystick
|
* Requests user calibration from the joystick
|
||||||
@@ -344,7 +363,8 @@ ImuCalibration GetImuCalibration(JoyconHandle& joycon_handle, bool is_factory_ca
|
|||||||
* @param controller_type type of calibration to be requested
|
* @param controller_type type of calibration to be requested
|
||||||
* @returns User CalibrationData of the joystick
|
* @returns User CalibrationData of the joystick
|
||||||
*/
|
*/
|
||||||
CalibrationData GetUserCalibrationData(JoyconHandle& joycon_handle, ControllerType controller_type);
|
ErrorCode GetUserCalibrationData(JoyconHandle& joycon_handle, CalibrationData& calibration_data,
|
||||||
|
ControllerType controller_type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests factory calibration from the joystick
|
* Requests factory calibration from the joystick
|
||||||
@@ -352,22 +372,22 @@ CalibrationData GetUserCalibrationData(JoyconHandle& joycon_handle, ControllerTy
|
|||||||
* @param controller_type type of calibration to be requested
|
* @param controller_type type of calibration to be requested
|
||||||
* @returns Factory CalibrationData of the joystick
|
* @returns Factory CalibrationData of the joystick
|
||||||
*/
|
*/
|
||||||
CalibrationData GetFactoryCalibrationData(JoyconHandle& joycon_handle,
|
ErrorCode GetFactoryCalibrationData(JoyconHandle& joycon_handle, CalibrationData& calibration_data,
|
||||||
ControllerType controller_type);
|
ControllerType controller_type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a request to enable motion
|
* Sends a request to enable motion
|
||||||
* @param joycon_handle device to read the data
|
* @param joycon_handle device to read the data
|
||||||
* @param is_factory_calibration if true motion data will be enabled
|
* @param is_factory_calibration if true motion data will be enabled
|
||||||
*/
|
*/
|
||||||
void EnableImu(JoyconHandle& joycon_handle, bool enable);
|
ErrorCode EnableImu(JoyconHandle& joycon_handle, bool enable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a request to enable vibrations
|
* Sends a request to enable vibrations
|
||||||
* @param joycon_handle device to read the data
|
* @param joycon_handle device to read the data
|
||||||
* @param is_factory_calibration if true rumble will be enabled
|
* @param is_factory_calibration if true rumble will be enabled
|
||||||
*/
|
*/
|
||||||
void EnableRumble(JoyconHandle& joycon_handle, bool enable);
|
ErrorCode EnableRumble(JoyconHandle& joycon_handle, bool enable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends data to the joycon device
|
* Sends data to the joycon device
|
||||||
@@ -375,7 +395,7 @@ void EnableRumble(JoyconHandle& joycon_handle, bool enable);
|
|||||||
* @param buffer data to be send
|
* @param buffer data to be send
|
||||||
* @param size size in bytes of the buffer
|
* @param size size in bytes of the buffer
|
||||||
*/
|
*/
|
||||||
void SendData(JoyconHandle& joycon_handle, std::span<const u8> buffer, std::size_t size);
|
ErrorCode SendData(JoyconHandle& joycon_handle, std::span<const u8> buffer, std::size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Waits for incoming data of the joycon device that matchs the subcommand
|
* Waits for incoming data of the joycon device that matchs the subcommand
|
||||||
@@ -383,7 +403,7 @@ void SendData(JoyconHandle& joycon_handle, std::span<const u8> buffer, std::size
|
|||||||
* @param sub_command type of data to be returned
|
* @param sub_command type of data to be returned
|
||||||
* @returns a buffer containing the responce
|
* @returns a buffer containing the responce
|
||||||
*/
|
*/
|
||||||
std::vector<u8> GetResponse(JoyconHandle& joycon_handle, SubCommand sub_command);
|
ErrorCode GetResponse(JoyconHandle& joycon_handle, SubCommand sub_command, std::vector<u8>& output);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends data to the joycon device
|
* Sends data to the joycon device
|
||||||
@@ -391,8 +411,8 @@ std::vector<u8> GetResponse(JoyconHandle& joycon_handle, SubCommand sub_command)
|
|||||||
* @param buffer data to be send
|
* @param buffer data to be send
|
||||||
* @param size size in bytes of the buffer
|
* @param size size in bytes of the buffer
|
||||||
*/
|
*/
|
||||||
std::vector<u8> SendSubCommand(JoyconHandle& joycon_handle, SubCommand sc,
|
ErrorCode SendSubCommand(JoyconHandle& joycon_handle, SubCommand sc, std::span<const u8> buffer,
|
||||||
std::span<const u8> buffer, std::size_t size);
|
std::size_t size, std::vector<u8>& output);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends data to the joycon device
|
* Sends data to the joycon device
|
||||||
@@ -400,6 +420,6 @@ std::vector<u8> SendSubCommand(JoyconHandle& joycon_handle, SubCommand sc,
|
|||||||
* @param buffer data to be send
|
* @param buffer data to be send
|
||||||
* @param size size in bytes of the buffer
|
* @param size size in bytes of the buffer
|
||||||
*/
|
*/
|
||||||
std::vector<u8> ReadSPI(JoyconHandle& joycon_handle, CalAddr addr, u8 size);
|
ErrorCode ReadSPI(JoyconHandle& joycon_handle, CalAddr addr, std::vector<u8>& output, u8 size);
|
||||||
|
|
||||||
} // namespace InputCommon::Joycon
|
} // namespace InputCommon::Joycon
|
||||||
|
|||||||
Reference in New Issue
Block a user