diff options
Diffstat (limited to 'src/input_common/helpers/joycon_protocol/common_protocol.cpp')
-rw-r--r-- | src/input_common/helpers/joycon_protocol/common_protocol.cpp | 155 |
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; } |