summaryrefslogtreecommitdiffstats
path: root/src/input_common/helpers/joycon_protocol/common_protocol.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common/helpers/joycon_protocol/common_protocol.cpp')
-rw-r--r--src/input_common/helpers/joycon_protocol/common_protocol.cpp155
1 files changed, 83 insertions, 72 deletions
diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.cpp b/src/input_common/helpers/joycon_protocol/common_protocol.cpp
index 0ef240344..2b42a4555 100644
--- a/src/input_common/helpers/joycon_protocol/common_protocol.cpp
+++ b/src/input_common/helpers/joycon_protocol/common_protocol.cpp
@@ -22,12 +22,9 @@ void JoyconCommonProtocol::SetNonBlocking() {
}
DriverResult JoyconCommonProtocol::GetDeviceType(ControllerType& controller_type) {
- std::array<u8, 1> buffer{};
- const auto result = ReadRawSPI(SpiAddress::DEVICE_TYPE, buffer);
- controller_type = ControllerType::None;
+ const auto result = ReadSPI(SpiAddress::DEVICE_TYPE, controller_type);
if (result == DriverResult::Success) {
- controller_type = static_cast<ControllerType>(buffer[0]);
// Fallback to 3rd party pro controllers
if (controller_type == ControllerType::None) {
controller_type = ControllerType::Pro;
@@ -40,6 +37,7 @@ DriverResult JoyconCommonProtocol::GetDeviceType(ControllerType& controller_type
DriverResult JoyconCommonProtocol::CheckDeviceAccess(SDL_hid_device_info* device_info) {
ControllerType controller_type{ControllerType::None};
const auto result = GetDeviceType(controller_type);
+
if (result != DriverResult::Success || controller_type == ControllerType::None) {
return DriverResult::UnsupportedControllerType;
}
@@ -62,7 +60,7 @@ DriverResult JoyconCommonProtocol::SetReportMode(ReportMode report_mode) {
return SendSubCommand(SubCommand::SET_REPORT_MODE, buffer);
}
-DriverResult JoyconCommonProtocol::SendData(std::span<const u8> buffer) {
+DriverResult JoyconCommonProtocol::SendRawData(std::span<const u8> buffer) {
const auto result = SDL_hid_write(hidapi_handle->handle, buffer.data(), buffer.size());
if (result == -1) {
@@ -72,15 +70,15 @@ DriverResult JoyconCommonProtocol::SendData(std::span<const u8> buffer) {
return DriverResult::Success;
}
-DriverResult JoyconCommonProtocol::GetSubCommandResponse(SubCommand sc, std::vector<u8>& output) {
+DriverResult JoyconCommonProtocol::GetSubCommandResponse(SubCommand sc,
+ SubCommandResponse& output) {
constexpr int timeout_mili = 66;
constexpr int MaxTries = 15;
int tries = 0;
- output.resize(MaxSubCommandResponseSize);
do {
- int result = SDL_hid_read_timeout(hidapi_handle->handle, output.data(),
- MaxSubCommandResponseSize, timeout_mili);
+ int result = SDL_hid_read_timeout(hidapi_handle->handle, reinterpret_cast<u8*>(&output),
+ sizeof(SubCommandResponse), timeout_mili);
if (result < 1) {
LOG_ERROR(Input, "No response from joycon");
@@ -88,27 +86,28 @@ DriverResult JoyconCommonProtocol::GetSubCommandResponse(SubCommand sc, std::vec
if (tries++ > MaxTries) {
return DriverResult::Timeout;
}
- } while (output[0] != 0x21 && output[14] != static_cast<u8>(sc));
-
- if (output[0] != 0x21 && output[14] != static_cast<u8>(sc)) {
- return DriverResult::WrongReply;
- }
+ } while (output.input_report.report_mode != ReportMode::SUBCMD_REPLY &&
+ output.sub_command != sc);
return DriverResult::Success;
}
DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const u8> buffer,
- std::vector<u8>& output) {
- std::vector<u8> local_buffer(MaxResponseSize);
-
- local_buffer[0] = static_cast<u8>(OutputReport::RUMBLE_AND_SUBCMD);
- local_buffer[1] = GetCounter();
- local_buffer[10] = static_cast<u8>(sc);
- for (std::size_t i = 0; i < buffer.size(); ++i) {
- local_buffer[11 + i] = buffer[i];
+ SubCommandResponse& output) {
+ SubCommandPacket packet{
+ .output_report = OutputReport::RUMBLE_AND_SUBCMD,
+ .packet_counter = GetCounter(),
+ .sub_command = sc,
+ .command_data = {},
+ };
+
+ if (buffer.size() > packet.command_data.size()) {
+ return DriverResult::InvalidParameters;
}
- auto result = SendData(local_buffer);
+ memcpy(packet.command_data.data(), buffer.data(), buffer.size());
+
+ auto result = SendData(packet);
if (result != DriverResult::Success) {
return result;
@@ -120,46 +119,57 @@ DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const
}
DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const u8> buffer) {
- std::vector<u8> output;
+ SubCommandResponse output{};
return SendSubCommand(sc, buffer, output);
}
DriverResult JoyconCommonProtocol::SendMCUCommand(SubCommand sc, std::span<const u8> buffer) {
- std::vector<u8> local_buffer(MaxResponseSize);
-
- local_buffer[0] = static_cast<u8>(OutputReport::MCU_DATA);
- local_buffer[1] = GetCounter();
- local_buffer[10] = static_cast<u8>(sc);
- for (std::size_t i = 0; i < buffer.size(); ++i) {
- local_buffer[11 + i] = buffer[i];
+ SubCommandPacket packet{
+ .output_report = OutputReport::MCU_DATA,
+ .packet_counter = GetCounter(),
+ .sub_command = sc,
+ .command_data = {},
+ };
+
+ if (buffer.size() > packet.command_data.size()) {
+ return DriverResult::InvalidParameters;
}
- return SendData(local_buffer);
+ memcpy(packet.command_data.data(), buffer.data(), buffer.size());
+
+ return SendData(packet);
}
DriverResult JoyconCommonProtocol::SendVibrationReport(std::span<const u8> buffer) {
- std::vector<u8> local_buffer(MaxResponseSize);
-
- local_buffer[0] = static_cast<u8>(Joycon::OutputReport::RUMBLE_ONLY);
- local_buffer[1] = GetCounter();
+ VibrationPacket packet{
+ .output_report = OutputReport::RUMBLE_ONLY,
+ .packet_counter = GetCounter(),
+ .vibration_data = {},
+ };
+
+ if (buffer.size() > packet.vibration_data.size()) {
+ return DriverResult::InvalidParameters;
+ }
- memcpy(local_buffer.data() + 2, buffer.data(), buffer.size());
+ memcpy(packet.vibration_data.data(), buffer.data(), buffer.size());
- return SendData(local_buffer);
+ return SendData(packet);
}
DriverResult JoyconCommonProtocol::ReadRawSPI(SpiAddress addr, std::span<u8> output) {
- constexpr std::size_t HeaderSize = 20;
+ constexpr std::size_t HeaderSize = 5;
constexpr std::size_t MaxTries = 10;
- const auto size = output.size();
std::size_t tries = 0;
- std::array<u8, 5> buffer = {0x00, 0x00, 0x00, 0x00, static_cast<u8>(size)};
- std::vector<u8> local_buffer{};
-
- buffer[0] = static_cast<u8>(static_cast<u16>(addr) & 0x00FF);
- buffer[1] = static_cast<u8>((static_cast<u16>(addr) & 0xFF00) >> 8);
+ SubCommandResponse response{};
+ std::array<u8, sizeof(ReadSpiPacket)> buffer{};
+ const ReadSpiPacket packet_data{
+ .spi_address = addr,
+ .size = static_cast<u8>(output.size()),
+ };
+
+ memcpy(buffer.data(), &packet_data, sizeof(ReadSpiPacket));
do {
- const auto result = SendSubCommand(SubCommand::SPI_FLASH_READ, buffer, local_buffer);
+ const auto result = SendSubCommand(SubCommand::SPI_FLASH_READ, buffer, response);
if (result != DriverResult::Success) {
return result;
}
@@ -167,14 +177,14 @@ DriverResult JoyconCommonProtocol::ReadRawSPI(SpiAddress addr, std::span<u8> out
if (tries++ > MaxTries) {
return DriverResult::Timeout;
}
- } while (local_buffer[15] != buffer[0] || local_buffer[16] != buffer[1]);
+ } while (response.spi_address != addr);
- if (local_buffer.size() < size + HeaderSize) {
+ if (response.command_data.size() < packet_data.size + HeaderSize) {
return DriverResult::WrongReply;
}
// Remove header from output
- memcpy(output.data(), local_buffer.data() + HeaderSize, size);
+ memcpy(output.data(), response.command_data.data() + HeaderSize, packet_data.size);
return DriverResult::Success;
}
@@ -183,7 +193,7 @@ DriverResult JoyconCommonProtocol::EnableMCU(bool enable) {
const auto result = SendSubCommand(SubCommand::SET_MCU_STATE, mcu_state);
if (result != DriverResult::Success) {
- LOG_ERROR(Input, "SendMCUData failed with error {}", result);
+ LOG_ERROR(Input, "Failed with error {}", result);
}
return result;
@@ -198,22 +208,21 @@ DriverResult JoyconCommonProtocol::ConfigureMCU(const MCUConfig& config) {
const auto result = SendSubCommand(SubCommand::SET_MCU_CONFIG, config_buffer);
if (result != DriverResult::Success) {
- LOG_ERROR(Input, "Set MCU config failed with error {}", result);
+ LOG_ERROR(Input, "Failed with error {}", result);
}
return result;
}
-DriverResult JoyconCommonProtocol::GetMCUDataResponse(ReportMode report_mode_,
- std::vector<u8>& output) {
- const int report_mode = static_cast<u8>(report_mode_);
+DriverResult JoyconCommonProtocol::GetMCUDataResponse(ReportMode report_mode,
+ MCUCommandResponse& output) {
constexpr int TimeoutMili = 200;
constexpr int MaxTries = 9;
int tries = 0;
- output.resize(0x170);
do {
- int result = SDL_hid_read_timeout(hidapi_handle->handle, output.data(), 0x170, TimeoutMili);
+ int result = SDL_hid_read_timeout(hidapi_handle->handle, reinterpret_cast<u8*>(&output),
+ sizeof(MCUCommandResponse), TimeoutMili);
if (result < 1) {
LOG_ERROR(Input, "No response from joycon attempt {}", tries);
@@ -221,28 +230,29 @@ DriverResult JoyconCommonProtocol::GetMCUDataResponse(ReportMode report_mode_,
if (tries++ > MaxTries) {
return DriverResult::Timeout;
}
- } while (output[0] != report_mode || output[49] == 0xFF);
-
- if (output[0] != report_mode || output[49] == 0xFF) {
- return DriverResult::WrongReply;
- }
+ } while (output.input_report.report_mode != report_mode ||
+ output.mcu_report == MCUReport::EmptyAwaitingCmd);
return DriverResult::Success;
}
DriverResult JoyconCommonProtocol::SendMCUData(ReportMode report_mode, SubCommand sc,
std::span<const u8> buffer,
- std::vector<u8>& output) {
- std::vector<u8> local_buffer(MaxResponseSize);
-
- local_buffer[0] = static_cast<u8>(OutputReport::MCU_DATA);
- local_buffer[1] = GetCounter();
- local_buffer[9] = static_cast<u8>(sc);
- for (std::size_t i = 0; i < buffer.size(); ++i) {
- local_buffer[10 + i] = buffer[i];
+ MCUCommandResponse& output) {
+ SubCommandPacket packet{
+ .output_report = OutputReport::MCU_DATA,
+ .packet_counter = GetCounter(),
+ .sub_command = sc,
+ .command_data = {},
+ };
+
+ if (buffer.size() > packet.command_data.size()) {
+ return DriverResult::InvalidParameters;
}
- auto result = SendData(local_buffer);
+ memcpy(packet.command_data.data(), buffer.data(), buffer.size());
+
+ auto result = SendData(packet);
if (result != DriverResult::Success) {
return result;
@@ -254,7 +264,7 @@ DriverResult JoyconCommonProtocol::SendMCUData(ReportMode report_mode, SubComman
}
DriverResult JoyconCommonProtocol::WaitSetMCUMode(ReportMode report_mode, MCUMode mode) {
- std::vector<u8> output;
+ MCUCommandResponse output{};
constexpr std::size_t MaxTries{8};
std::size_t tries{};
@@ -269,7 +279,8 @@ DriverResult JoyconCommonProtocol::WaitSetMCUMode(ReportMode report_mode, MCUMod
if (tries++ > MaxTries) {
return DriverResult::WrongReply;
}
- } while (output[49] != 1 || output[56] != static_cast<u8>(mode));
+ } while (output.mcu_report != MCUReport::StateReport ||
+ output.mcu_data[6] != static_cast<u8>(mode));
return DriverResult::Success;
}