diff options
| author | 2023-01-27 22:30:44 -0600 | |
|---|---|---|
| committer | 2023-01-29 20:12:58 -0600 | |
| commit | c318a4c80b4b6eef9f8020f452573ef5c80f6716 (patch) | |
| tree | ea031039eb63ef385ceeb0a5c0694baa9e8da8be /src | |
| parent | input_common: joycon: Fill missing enum data (diff) | |
| download | yuzu-c318a4c80b4b6eef9f8020f452573ef5c80f6716.tar.gz yuzu-c318a4c80b4b6eef9f8020f452573ef5c80f6716.tar.xz yuzu-c318a4c80b4b6eef9f8020f452573ef5c80f6716.zip | |
input_common: joycon: Remove Magic numbers from common protocol
Diffstat (limited to 'src')
9 files changed, 221 insertions, 154 deletions
diff --git a/src/input_common/helpers/joycon_driver.cpp b/src/input_common/helpers/joycon_driver.cpp index 3775e2d35..8f94c9f45 100644 --- a/src/input_common/helpers/joycon_driver.cpp +++ b/src/input_common/helpers/joycon_driver.cpp | |||
| @@ -162,14 +162,14 @@ void JoyconDriver::InputThread(std::stop_token stop_token) { | |||
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | void JoyconDriver::OnNewData(std::span<u8> buffer) { | 164 | void JoyconDriver::OnNewData(std::span<u8> buffer) { |
| 165 | const auto report_mode = static_cast<InputReport>(buffer[0]); | 165 | const auto report_mode = static_cast<ReportMode>(buffer[0]); |
| 166 | 166 | ||
| 167 | // Packages can be a litte bit inconsistent. Average the delta time to provide a smoother motion | 167 | // Packages can be a litte bit inconsistent. Average the delta time to provide a smoother motion |
| 168 | // experience | 168 | // experience |
| 169 | switch (report_mode) { | 169 | switch (report_mode) { |
| 170 | case InputReport::STANDARD_FULL_60HZ: | 170 | case ReportMode::STANDARD_FULL_60HZ: |
| 171 | case InputReport::NFC_IR_MODE_60HZ: | 171 | case ReportMode::NFC_IR_MODE_60HZ: |
| 172 | case InputReport::SIMPLE_HID_MODE: { | 172 | case ReportMode::SIMPLE_HID_MODE: { |
| 173 | const auto now = std::chrono::steady_clock::now(); | 173 | const auto now = std::chrono::steady_clock::now(); |
| 174 | const auto new_delta_time = static_cast<u64>( | 174 | const auto new_delta_time = static_cast<u64>( |
| 175 | std::chrono::duration_cast<std::chrono::microseconds>(now - last_update).count()); | 175 | std::chrono::duration_cast<std::chrono::microseconds>(now - last_update).count()); |
| @@ -190,7 +190,7 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) { | |||
| 190 | }; | 190 | }; |
| 191 | 191 | ||
| 192 | // TODO: Remove this when calibration is properly loaded and not calculated | 192 | // TODO: Remove this when calibration is properly loaded and not calculated |
| 193 | if (ring_connected && report_mode == InputReport::STANDARD_FULL_60HZ) { | 193 | if (ring_connected && report_mode == ReportMode::STANDARD_FULL_60HZ) { |
| 194 | InputReportActive data{}; | 194 | InputReportActive data{}; |
| 195 | memcpy(&data, buffer.data(), sizeof(InputReportActive)); | 195 | memcpy(&data, buffer.data(), sizeof(InputReportActive)); |
| 196 | calibration_protocol->GetRingCalibration(ring_calibration, data.ring_input); | 196 | calibration_protocol->GetRingCalibration(ring_calibration, data.ring_input); |
| @@ -228,16 +228,16 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) { | |||
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | switch (report_mode) { | 230 | switch (report_mode) { |
| 231 | case InputReport::STANDARD_FULL_60HZ: | 231 | case ReportMode::STANDARD_FULL_60HZ: |
| 232 | joycon_poller->ReadActiveMode(buffer, motion_status, ring_status); | 232 | joycon_poller->ReadActiveMode(buffer, motion_status, ring_status); |
| 233 | break; | 233 | break; |
| 234 | case InputReport::NFC_IR_MODE_60HZ: | 234 | case ReportMode::NFC_IR_MODE_60HZ: |
| 235 | joycon_poller->ReadNfcIRMode(buffer, motion_status); | 235 | joycon_poller->ReadNfcIRMode(buffer, motion_status); |
| 236 | break; | 236 | break; |
| 237 | case InputReport::SIMPLE_HID_MODE: | 237 | case ReportMode::SIMPLE_HID_MODE: |
| 238 | joycon_poller->ReadPassiveMode(buffer); | 238 | joycon_poller->ReadPassiveMode(buffer); |
| 239 | break; | 239 | break; |
| 240 | case InputReport::SUBCMD_REPLY: | 240 | case ReportMode::SUBCMD_REPLY: |
| 241 | LOG_DEBUG(Input, "Unhandled command reply"); | 241 | LOG_DEBUG(Input, "Unhandled command reply"); |
| 242 | break; | 242 | break; |
| 243 | default: | 243 | default: |
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() { | |||
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | DriverResult JoyconCommonProtocol::GetDeviceType(ControllerType& controller_type) { | 24 | DriverResult JoyconCommonProtocol::GetDeviceType(ControllerType& controller_type) { |
| 25 | std::array<u8, 1> buffer{}; | 25 | const auto result = ReadSPI(SpiAddress::DEVICE_TYPE, controller_type); |
| 26 | const auto result = ReadRawSPI(SpiAddress::DEVICE_TYPE, buffer); | ||
| 27 | controller_type = ControllerType::None; | ||
| 28 | 26 | ||
| 29 | if (result == DriverResult::Success) { | 27 | if (result == DriverResult::Success) { |
| 30 | controller_type = static_cast<ControllerType>(buffer[0]); | ||
| 31 | // Fallback to 3rd party pro controllers | 28 | // Fallback to 3rd party pro controllers |
| 32 | if (controller_type == ControllerType::None) { | 29 | if (controller_type == ControllerType::None) { |
| 33 | controller_type = ControllerType::Pro; | 30 | controller_type = ControllerType::Pro; |
| @@ -40,6 +37,7 @@ DriverResult JoyconCommonProtocol::GetDeviceType(ControllerType& controller_type | |||
| 40 | DriverResult JoyconCommonProtocol::CheckDeviceAccess(SDL_hid_device_info* device_info) { | 37 | DriverResult JoyconCommonProtocol::CheckDeviceAccess(SDL_hid_device_info* device_info) { |
| 41 | ControllerType controller_type{ControllerType::None}; | 38 | ControllerType controller_type{ControllerType::None}; |
| 42 | const auto result = GetDeviceType(controller_type); | 39 | const auto result = GetDeviceType(controller_type); |
| 40 | |||
| 43 | if (result != DriverResult::Success || controller_type == ControllerType::None) { | 41 | if (result != DriverResult::Success || controller_type == ControllerType::None) { |
| 44 | return DriverResult::UnsupportedControllerType; | 42 | return DriverResult::UnsupportedControllerType; |
| 45 | } | 43 | } |
| @@ -62,7 +60,7 @@ DriverResult JoyconCommonProtocol::SetReportMode(ReportMode report_mode) { | |||
| 62 | return SendSubCommand(SubCommand::SET_REPORT_MODE, buffer); | 60 | return SendSubCommand(SubCommand::SET_REPORT_MODE, buffer); |
| 63 | } | 61 | } |
| 64 | 62 | ||
| 65 | DriverResult JoyconCommonProtocol::SendData(std::span<const u8> buffer) { | 63 | DriverResult JoyconCommonProtocol::SendRawData(std::span<const u8> buffer) { |
| 66 | const auto result = SDL_hid_write(hidapi_handle->handle, buffer.data(), buffer.size()); | 64 | const auto result = SDL_hid_write(hidapi_handle->handle, buffer.data(), buffer.size()); |
| 67 | 65 | ||
| 68 | if (result == -1) { | 66 | if (result == -1) { |
| @@ -72,15 +70,15 @@ DriverResult JoyconCommonProtocol::SendData(std::span<const u8> buffer) { | |||
| 72 | return DriverResult::Success; | 70 | return DriverResult::Success; |
| 73 | } | 71 | } |
| 74 | 72 | ||
| 75 | DriverResult JoyconCommonProtocol::GetSubCommandResponse(SubCommand sc, std::vector<u8>& output) { | 73 | DriverResult JoyconCommonProtocol::GetSubCommandResponse(SubCommand sc, |
| 74 | SubCommandResponse& output) { | ||
| 76 | constexpr int timeout_mili = 66; | 75 | constexpr int timeout_mili = 66; |
| 77 | constexpr int MaxTries = 15; | 76 | constexpr int MaxTries = 15; |
| 78 | int tries = 0; | 77 | int tries = 0; |
| 79 | output.resize(MaxSubCommandResponseSize); | ||
| 80 | 78 | ||
| 81 | do { | 79 | do { |
| 82 | int result = SDL_hid_read_timeout(hidapi_handle->handle, output.data(), | 80 | int result = SDL_hid_read_timeout(hidapi_handle->handle, reinterpret_cast<u8*>(&output), |
| 83 | MaxSubCommandResponseSize, timeout_mili); | 81 | sizeof(SubCommandResponse), timeout_mili); |
| 84 | 82 | ||
| 85 | if (result < 1) { | 83 | if (result < 1) { |
| 86 | LOG_ERROR(Input, "No response from joycon"); | 84 | LOG_ERROR(Input, "No response from joycon"); |
| @@ -88,27 +86,28 @@ DriverResult JoyconCommonProtocol::GetSubCommandResponse(SubCommand sc, std::vec | |||
| 88 | if (tries++ > MaxTries) { | 86 | if (tries++ > MaxTries) { |
| 89 | return DriverResult::Timeout; | 87 | return DriverResult::Timeout; |
| 90 | } | 88 | } |
| 91 | } while (output[0] != 0x21 && output[14] != static_cast<u8>(sc)); | 89 | } while (output.input_report.report_mode != ReportMode::SUBCMD_REPLY && |
| 92 | 90 | output.sub_command != sc); | |
| 93 | if (output[0] != 0x21 && output[14] != static_cast<u8>(sc)) { | ||
| 94 | return DriverResult::WrongReply; | ||
| 95 | } | ||
| 96 | 91 | ||
| 97 | return DriverResult::Success; | 92 | return DriverResult::Success; |
| 98 | } | 93 | } |
| 99 | 94 | ||
| 100 | DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const u8> buffer, | 95 | DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const u8> buffer, |
| 101 | std::vector<u8>& output) { | 96 | SubCommandResponse& output) { |
| 102 | std::vector<u8> local_buffer(MaxResponseSize); | 97 | SubCommandPacket packet{ |
| 103 | 98 | .output_report = OutputReport::RUMBLE_AND_SUBCMD, | |
| 104 | local_buffer[0] = static_cast<u8>(OutputReport::RUMBLE_AND_SUBCMD); | 99 | .packet_counter = GetCounter(), |
| 105 | local_buffer[1] = GetCounter(); | 100 | .sub_command = sc, |
| 106 | local_buffer[10] = static_cast<u8>(sc); | 101 | .command_data = {}, |
| 107 | for (std::size_t i = 0; i < buffer.size(); ++i) { | 102 | }; |
| 108 | local_buffer[11 + i] = buffer[i]; | 103 | |
| 104 | if (buffer.size() > packet.command_data.size()) { | ||
| 105 | return DriverResult::InvalidParameters; | ||
| 109 | } | 106 | } |
| 110 | 107 | ||
| 111 | auto result = SendData(local_buffer); | 108 | memcpy(packet.command_data.data(), buffer.data(), buffer.size()); |
| 109 | |||
| 110 | auto result = SendData(packet); | ||
| 112 | 111 | ||
| 113 | if (result != DriverResult::Success) { | 112 | if (result != DriverResult::Success) { |
| 114 | return result; | 113 | return result; |
| @@ -120,46 +119,57 @@ DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const | |||
| 120 | } | 119 | } |
| 121 | 120 | ||
| 122 | DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const u8> buffer) { | 121 | DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const u8> buffer) { |
| 123 | std::vector<u8> output; | 122 | SubCommandResponse output{}; |
| 124 | return SendSubCommand(sc, buffer, output); | 123 | return SendSubCommand(sc, buffer, output); |
| 125 | } | 124 | } |
| 126 | 125 | ||
| 127 | DriverResult JoyconCommonProtocol::SendMCUCommand(SubCommand sc, std::span<const u8> buffer) { | 126 | DriverResult JoyconCommonProtocol::SendMCUCommand(SubCommand sc, std::span<const u8> buffer) { |
| 128 | std::vector<u8> local_buffer(MaxResponseSize); | 127 | SubCommandPacket packet{ |
| 129 | 128 | .output_report = OutputReport::MCU_DATA, | |
| 130 | local_buffer[0] = static_cast<u8>(OutputReport::MCU_DATA); | 129 | .packet_counter = GetCounter(), |
| 131 | local_buffer[1] = GetCounter(); | 130 | .sub_command = sc, |
| 132 | local_buffer[10] = static_cast<u8>(sc); | 131 | .command_data = {}, |
| 133 | for (std::size_t i = 0; i < buffer.size(); ++i) { | 132 | }; |
| 134 | local_buffer[11 + i] = buffer[i]; | 133 | |
| 134 | if (buffer.size() > packet.command_data.size()) { | ||
| 135 | return DriverResult::InvalidParameters; | ||
| 135 | } | 136 | } |
| 136 | 137 | ||
| 137 | return SendData(local_buffer); | 138 | memcpy(packet.command_data.data(), buffer.data(), buffer.size()); |
| 139 | |||
| 140 | return SendData(packet); | ||
| 138 | } | 141 | } |
| 139 | 142 | ||
| 140 | DriverResult JoyconCommonProtocol::SendVibrationReport(std::span<const u8> buffer) { | 143 | DriverResult JoyconCommonProtocol::SendVibrationReport(std::span<const u8> buffer) { |
| 141 | std::vector<u8> local_buffer(MaxResponseSize); | 144 | VibrationPacket packet{ |
| 142 | 145 | .output_report = OutputReport::RUMBLE_ONLY, | |
| 143 | local_buffer[0] = static_cast<u8>(Joycon::OutputReport::RUMBLE_ONLY); | 146 | .packet_counter = GetCounter(), |
| 144 | local_buffer[1] = GetCounter(); | 147 | .vibration_data = {}, |
| 148 | }; | ||
| 149 | |||
| 150 | if (buffer.size() > packet.vibration_data.size()) { | ||
| 151 | return DriverResult::InvalidParameters; | ||
| 152 | } | ||
| 145 | 153 | ||
| 146 | memcpy(local_buffer.data() + 2, buffer.data(), buffer.size()); | 154 | memcpy(packet.vibration_data.data(), buffer.data(), buffer.size()); |
| 147 | 155 | ||
| 148 | return SendData(local_buffer); | 156 | return SendData(packet); |
| 149 | } | 157 | } |
| 150 | 158 | ||
| 151 | DriverResult JoyconCommonProtocol::ReadRawSPI(SpiAddress addr, std::span<u8> output) { | 159 | DriverResult JoyconCommonProtocol::ReadRawSPI(SpiAddress addr, std::span<u8> output) { |
| 152 | constexpr std::size_t HeaderSize = 20; | 160 | constexpr std::size_t HeaderSize = 5; |
| 153 | constexpr std::size_t MaxTries = 10; | 161 | constexpr std::size_t MaxTries = 10; |
| 154 | const auto size = output.size(); | ||
| 155 | std::size_t tries = 0; | 162 | std::size_t tries = 0; |
| 156 | std::array<u8, 5> buffer = {0x00, 0x00, 0x00, 0x00, static_cast<u8>(size)}; | 163 | SubCommandResponse response{}; |
| 157 | std::vector<u8> local_buffer{}; | 164 | std::array<u8, sizeof(ReadSpiPacket)> buffer{}; |
| 158 | 165 | const ReadSpiPacket packet_data{ | |
| 159 | buffer[0] = static_cast<u8>(static_cast<u16>(addr) & 0x00FF); | 166 | .spi_address = addr, |
| 160 | buffer[1] = static_cast<u8>((static_cast<u16>(addr) & 0xFF00) >> 8); | 167 | .size = static_cast<u8>(output.size()), |
| 168 | }; | ||
| 169 | |||
| 170 | memcpy(buffer.data(), &packet_data, sizeof(ReadSpiPacket)); | ||
| 161 | do { | 171 | do { |
| 162 | const auto result = SendSubCommand(SubCommand::SPI_FLASH_READ, buffer, local_buffer); | 172 | const auto result = SendSubCommand(SubCommand::SPI_FLASH_READ, buffer, response); |
| 163 | if (result != DriverResult::Success) { | 173 | if (result != DriverResult::Success) { |
| 164 | return result; | 174 | return result; |
| 165 | } | 175 | } |
| @@ -167,14 +177,14 @@ DriverResult JoyconCommonProtocol::ReadRawSPI(SpiAddress addr, std::span<u8> out | |||
| 167 | if (tries++ > MaxTries) { | 177 | if (tries++ > MaxTries) { |
| 168 | return DriverResult::Timeout; | 178 | return DriverResult::Timeout; |
| 169 | } | 179 | } |
| 170 | } while (local_buffer[15] != buffer[0] || local_buffer[16] != buffer[1]); | 180 | } while (response.spi_address != addr); |
| 171 | 181 | ||
| 172 | if (local_buffer.size() < size + HeaderSize) { | 182 | if (response.command_data.size() < packet_data.size + HeaderSize) { |
| 173 | return DriverResult::WrongReply; | 183 | return DriverResult::WrongReply; |
| 174 | } | 184 | } |
| 175 | 185 | ||
| 176 | // Remove header from output | 186 | // Remove header from output |
| 177 | memcpy(output.data(), local_buffer.data() + HeaderSize, size); | 187 | memcpy(output.data(), response.command_data.data() + HeaderSize, packet_data.size); |
| 178 | return DriverResult::Success; | 188 | return DriverResult::Success; |
| 179 | } | 189 | } |
| 180 | 190 | ||
| @@ -183,7 +193,7 @@ DriverResult JoyconCommonProtocol::EnableMCU(bool enable) { | |||
| 183 | const auto result = SendSubCommand(SubCommand::SET_MCU_STATE, mcu_state); | 193 | const auto result = SendSubCommand(SubCommand::SET_MCU_STATE, mcu_state); |
| 184 | 194 | ||
| 185 | if (result != DriverResult::Success) { | 195 | if (result != DriverResult::Success) { |
| 186 | LOG_ERROR(Input, "SendMCUData failed with error {}", result); | 196 | LOG_ERROR(Input, "Failed with error {}", result); |
| 187 | } | 197 | } |
| 188 | 198 | ||
| 189 | return result; | 199 | return result; |
| @@ -198,22 +208,21 @@ DriverResult JoyconCommonProtocol::ConfigureMCU(const MCUConfig& config) { | |||
| 198 | const auto result = SendSubCommand(SubCommand::SET_MCU_CONFIG, config_buffer); | 208 | const auto result = SendSubCommand(SubCommand::SET_MCU_CONFIG, config_buffer); |
| 199 | 209 | ||
| 200 | if (result != DriverResult::Success) { | 210 | if (result != DriverResult::Success) { |
| 201 | LOG_ERROR(Input, "Set MCU config failed with error {}", result); | 211 | LOG_ERROR(Input, "Failed with error {}", result); |
| 202 | } | 212 | } |
| 203 | 213 | ||
| 204 | return result; | 214 | return result; |
| 205 | } | 215 | } |
| 206 | 216 | ||
| 207 | DriverResult JoyconCommonProtocol::GetMCUDataResponse(ReportMode report_mode_, | 217 | DriverResult JoyconCommonProtocol::GetMCUDataResponse(ReportMode report_mode, |
| 208 | std::vector<u8>& output) { | 218 | MCUCommandResponse& output) { |
| 209 | const int report_mode = static_cast<u8>(report_mode_); | ||
| 210 | constexpr int TimeoutMili = 200; | 219 | constexpr int TimeoutMili = 200; |
| 211 | constexpr int MaxTries = 9; | 220 | constexpr int MaxTries = 9; |
| 212 | int tries = 0; | 221 | int tries = 0; |
| 213 | output.resize(0x170); | ||
| 214 | 222 | ||
| 215 | do { | 223 | do { |
| 216 | int result = SDL_hid_read_timeout(hidapi_handle->handle, output.data(), 0x170, TimeoutMili); | 224 | int result = SDL_hid_read_timeout(hidapi_handle->handle, reinterpret_cast<u8*>(&output), |
| 225 | sizeof(MCUCommandResponse), TimeoutMili); | ||
| 217 | 226 | ||
| 218 | if (result < 1) { | 227 | if (result < 1) { |
| 219 | LOG_ERROR(Input, "No response from joycon attempt {}", tries); | 228 | LOG_ERROR(Input, "No response from joycon attempt {}", tries); |
| @@ -221,28 +230,29 @@ DriverResult JoyconCommonProtocol::GetMCUDataResponse(ReportMode report_mode_, | |||
| 221 | if (tries++ > MaxTries) { | 230 | if (tries++ > MaxTries) { |
| 222 | return DriverResult::Timeout; | 231 | return DriverResult::Timeout; |
| 223 | } | 232 | } |
| 224 | } while (output[0] != report_mode || output[49] == 0xFF); | 233 | } while (output.input_report.report_mode != report_mode || |
| 225 | 234 | output.mcu_report == MCUReport::EmptyAwaitingCmd); | |
| 226 | if (output[0] != report_mode || output[49] == 0xFF) { | ||
| 227 | return DriverResult::WrongReply; | ||
| 228 | } | ||
| 229 | 235 | ||
| 230 | return DriverResult::Success; | 236 | return DriverResult::Success; |
| 231 | } | 237 | } |
| 232 | 238 | ||
| 233 | DriverResult JoyconCommonProtocol::SendMCUData(ReportMode report_mode, SubCommand sc, | 239 | DriverResult JoyconCommonProtocol::SendMCUData(ReportMode report_mode, SubCommand sc, |
| 234 | std::span<const u8> buffer, | 240 | std::span<const u8> buffer, |
| 235 | std::vector<u8>& output) { | 241 | MCUCommandResponse& output) { |
| 236 | std::vector<u8> local_buffer(MaxResponseSize); | 242 | SubCommandPacket packet{ |
| 237 | 243 | .output_report = OutputReport::MCU_DATA, | |
| 238 | local_buffer[0] = static_cast<u8>(OutputReport::MCU_DATA); | 244 | .packet_counter = GetCounter(), |
| 239 | local_buffer[1] = GetCounter(); | 245 | .sub_command = sc, |
| 240 | local_buffer[9] = static_cast<u8>(sc); | 246 | .command_data = {}, |
| 241 | for (std::size_t i = 0; i < buffer.size(); ++i) { | 247 | }; |
| 242 | local_buffer[10 + i] = buffer[i]; | 248 | |
| 249 | if (buffer.size() > packet.command_data.size()) { | ||
| 250 | return DriverResult::InvalidParameters; | ||
| 243 | } | 251 | } |
| 244 | 252 | ||
| 245 | auto result = SendData(local_buffer); | 253 | memcpy(packet.command_data.data(), buffer.data(), buffer.size()); |
| 254 | |||
| 255 | auto result = SendData(packet); | ||
| 246 | 256 | ||
| 247 | if (result != DriverResult::Success) { | 257 | if (result != DriverResult::Success) { |
| 248 | return result; | 258 | return result; |
| @@ -254,7 +264,7 @@ DriverResult JoyconCommonProtocol::SendMCUData(ReportMode report_mode, SubComman | |||
| 254 | } | 264 | } |
| 255 | 265 | ||
| 256 | DriverResult JoyconCommonProtocol::WaitSetMCUMode(ReportMode report_mode, MCUMode mode) { | 266 | DriverResult JoyconCommonProtocol::WaitSetMCUMode(ReportMode report_mode, MCUMode mode) { |
| 257 | std::vector<u8> output; | 267 | MCUCommandResponse output{}; |
| 258 | constexpr std::size_t MaxTries{8}; | 268 | constexpr std::size_t MaxTries{8}; |
| 259 | std::size_t tries{}; | 269 | std::size_t tries{}; |
| 260 | 270 | ||
| @@ -269,7 +279,8 @@ DriverResult JoyconCommonProtocol::WaitSetMCUMode(ReportMode report_mode, MCUMod | |||
| 269 | if (tries++ > MaxTries) { | 279 | if (tries++ > MaxTries) { |
| 270 | return DriverResult::WrongReply; | 280 | return DriverResult::WrongReply; |
| 271 | } | 281 | } |
| 272 | } while (output[49] != 1 || output[56] != static_cast<u8>(mode)); | 282 | } while (output.mcu_report != MCUReport::StateReport || |
| 283 | output.mcu_data[6] != static_cast<u8>(mode)); | ||
| 273 | 284 | ||
| 274 | return DriverResult::Success; | 285 | return DriverResult::Success; |
| 275 | } | 286 | } |
diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.h b/src/input_common/helpers/joycon_protocol/common_protocol.h index 188f6ecfa..f44f73ba4 100644 --- a/src/input_common/helpers/joycon_protocol/common_protocol.h +++ b/src/input_common/helpers/joycon_protocol/common_protocol.h | |||
| @@ -57,22 +57,31 @@ public: | |||
| 57 | * Sends data to the joycon device | 57 | * Sends data to the joycon device |
| 58 | * @param buffer data to be send | 58 | * @param buffer data to be send |
| 59 | */ | 59 | */ |
| 60 | DriverResult SendData(std::span<const u8> buffer); | 60 | DriverResult SendRawData(std::span<const u8> buffer); |
| 61 | |||
| 62 | template <typename Output> | ||
| 63 | requires std::is_trivially_copyable_v<Output> | ||
| 64 | DriverResult SendData(const Output& output) { | ||
| 65 | std::array<u8, sizeof(Output)> buffer; | ||
| 66 | std::memcpy(buffer.data(), &output, sizeof(Output)); | ||
| 67 | return SendRawData(buffer); | ||
| 68 | } | ||
| 61 | 69 | ||
| 62 | /** | 70 | /** |
| 63 | * Waits for incoming data of the joycon device that matchs the subcommand | 71 | * Waits for incoming data of the joycon device that matchs the subcommand |
| 64 | * @param sub_command type of data to be returned | 72 | * @param sub_command type of data to be returned |
| 65 | * @returns a buffer containing the responce | 73 | * @returns a buffer containing the response |
| 66 | */ | 74 | */ |
| 67 | DriverResult GetSubCommandResponse(SubCommand sub_command, std::vector<u8>& output); | 75 | DriverResult GetSubCommandResponse(SubCommand sub_command, SubCommandResponse& output); |
| 68 | 76 | ||
| 69 | /** | 77 | /** |
| 70 | * Sends a sub command to the device and waits for it's reply | 78 | * Sends a sub command to the device and waits for it's reply |
| 71 | * @param sc sub command to be send | 79 | * @param sc sub command to be send |
| 72 | * @param buffer data to be send | 80 | * @param buffer data to be send |
| 73 | * @returns output buffer containing the responce | 81 | * @returns output buffer containing the response |
| 74 | */ | 82 | */ |
| 75 | DriverResult SendSubCommand(SubCommand sc, std::span<const u8> buffer, std::vector<u8>& output); | 83 | DriverResult SendSubCommand(SubCommand sc, std::span<const u8> buffer, |
| 84 | SubCommandResponse& output); | ||
| 76 | 85 | ||
| 77 | /** | 86 | /** |
| 78 | * Sends a sub command to the device and waits for it's reply and ignores the output | 87 | * Sends a sub command to the device and waits for it's reply and ignores the output |
| @@ -97,14 +106,14 @@ public: | |||
| 97 | /** | 106 | /** |
| 98 | * Reads the SPI memory stored on the joycon | 107 | * Reads the SPI memory stored on the joycon |
| 99 | * @param Initial address location | 108 | * @param Initial address location |
| 100 | * @returns output buffer containing the responce | 109 | * @returns output buffer containing the response |
| 101 | */ | 110 | */ |
| 102 | DriverResult ReadRawSPI(SpiAddress addr, std::span<u8> output); | 111 | DriverResult ReadRawSPI(SpiAddress addr, std::span<u8> output); |
| 103 | 112 | ||
| 104 | /** | 113 | /** |
| 105 | * Reads the SPI memory stored on the joycon | 114 | * Reads the SPI memory stored on the joycon |
| 106 | * @param Initial address location | 115 | * @param Initial address location |
| 107 | * @returns output object containing the responce | 116 | * @returns output object containing the response |
| 108 | */ | 117 | */ |
| 109 | template <typename Output> | 118 | template <typename Output> |
| 110 | requires std::is_trivially_copyable_v<Output> | 119 | requires std::is_trivially_copyable_v<Output> |
| @@ -136,19 +145,19 @@ public: | |||
| 136 | /** | 145 | /** |
| 137 | * Waits until there's MCU data available. On timeout returns error | 146 | * Waits until there's MCU data available. On timeout returns error |
| 138 | * @param report mode of the expected reply | 147 | * @param report mode of the expected reply |
| 139 | * @returns a buffer containing the responce | 148 | * @returns a buffer containing the response |
| 140 | */ | 149 | */ |
| 141 | DriverResult GetMCUDataResponse(ReportMode report_mode_, std::vector<u8>& output); | 150 | DriverResult GetMCUDataResponse(ReportMode report_mode_, MCUCommandResponse& output); |
| 142 | 151 | ||
| 143 | /** | 152 | /** |
| 144 | * Sends data to the MCU chip and waits for it's reply | 153 | * Sends data to the MCU chip and waits for it's reply |
| 145 | * @param report mode of the expected reply | 154 | * @param report mode of the expected reply |
| 146 | * @param sub command to be send | 155 | * @param sub command to be send |
| 147 | * @param buffer data to be send | 156 | * @param buffer data to be send |
| 148 | * @returns output buffer containing the responce | 157 | * @returns output buffer containing the response |
| 149 | */ | 158 | */ |
| 150 | DriverResult SendMCUData(ReportMode report_mode, SubCommand sc, std::span<const u8> buffer, | 159 | DriverResult SendMCUData(ReportMode report_mode, SubCommand sc, std::span<const u8> buffer, |
| 151 | std::vector<u8>& output); | 160 | MCUCommandResponse& output); |
| 152 | 161 | ||
| 153 | /** | 162 | /** |
| 154 | * Wait's until the MCU chip is on the specified mode | 163 | * Wait's until the MCU chip is on the specified mode |
diff --git a/src/input_common/helpers/joycon_protocol/generic_functions.cpp b/src/input_common/helpers/joycon_protocol/generic_functions.cpp index f3fefd5b6..548a4b9e3 100644 --- a/src/input_common/helpers/joycon_protocol/generic_functions.cpp +++ b/src/input_common/helpers/joycon_protocol/generic_functions.cpp | |||
| @@ -32,13 +32,13 @@ DriverResult GenericProtocol::TriggersElapsed() { | |||
| 32 | 32 | ||
| 33 | DriverResult GenericProtocol::GetDeviceInfo(DeviceInfo& device_info) { | 33 | DriverResult GenericProtocol::GetDeviceInfo(DeviceInfo& device_info) { |
| 34 | ScopedSetBlocking sb(this); | 34 | ScopedSetBlocking sb(this); |
| 35 | std::vector<u8> output; | 35 | SubCommandResponse output{}; |
| 36 | 36 | ||
| 37 | const auto result = SendSubCommand(SubCommand::REQ_DEV_INFO, {}, output); | 37 | const auto result = SendSubCommand(SubCommand::REQ_DEV_INFO, {}, output); |
| 38 | 38 | ||
| 39 | device_info = {}; | 39 | device_info = {}; |
| 40 | if (result == DriverResult::Success) { | 40 | if (result == DriverResult::Success) { |
| 41 | memcpy(&device_info, output.data() + 15, sizeof(DeviceInfo)); | 41 | device_info = output.device_info; |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | return result; | 44 | return result; |
diff --git a/src/input_common/helpers/joycon_protocol/irs.cpp b/src/input_common/helpers/joycon_protocol/irs.cpp index 09e17bc5b..731fd5981 100644 --- a/src/input_common/helpers/joycon_protocol/irs.cpp +++ b/src/input_common/helpers/joycon_protocol/irs.cpp | |||
| @@ -132,7 +132,7 @@ DriverResult IrsProtocol::RequestImage(std::span<u8> buffer) { | |||
| 132 | DriverResult IrsProtocol::ConfigureIrs() { | 132 | DriverResult IrsProtocol::ConfigureIrs() { |
| 133 | LOG_DEBUG(Input, "Configure IRS"); | 133 | LOG_DEBUG(Input, "Configure IRS"); |
| 134 | constexpr std::size_t max_tries = 28; | 134 | constexpr std::size_t max_tries = 28; |
| 135 | std::vector<u8> output; | 135 | SubCommandResponse output{}; |
| 136 | std::size_t tries = 0; | 136 | std::size_t tries = 0; |
| 137 | 137 | ||
| 138 | const IrsConfigure irs_configuration{ | 138 | const IrsConfigure irs_configuration{ |
| @@ -158,7 +158,7 @@ DriverResult IrsProtocol::ConfigureIrs() { | |||
| 158 | if (tries++ >= max_tries) { | 158 | if (tries++ >= max_tries) { |
| 159 | return DriverResult::WrongReply; | 159 | return DriverResult::WrongReply; |
| 160 | } | 160 | } |
| 161 | } while (output[15] != 0x0b); | 161 | } while (output.command_data[0] != 0x0b); |
| 162 | 162 | ||
| 163 | return DriverResult::Success; | 163 | return DriverResult::Success; |
| 164 | } | 164 | } |
| @@ -167,7 +167,7 @@ DriverResult IrsProtocol::WriteRegistersStep1() { | |||
| 167 | LOG_DEBUG(Input, "WriteRegistersStep1"); | 167 | LOG_DEBUG(Input, "WriteRegistersStep1"); |
| 168 | DriverResult result{DriverResult::Success}; | 168 | DriverResult result{DriverResult::Success}; |
| 169 | constexpr std::size_t max_tries = 28; | 169 | constexpr std::size_t max_tries = 28; |
| 170 | std::vector<u8> output; | 170 | SubCommandResponse output{}; |
| 171 | std::size_t tries = 0; | 171 | std::size_t tries = 0; |
| 172 | 172 | ||
| 173 | const IrsWriteRegisters irs_registers{ | 173 | const IrsWriteRegisters irs_registers{ |
| @@ -218,7 +218,8 @@ DriverResult IrsProtocol::WriteRegistersStep1() { | |||
| 218 | if (tries++ >= max_tries) { | 218 | if (tries++ >= max_tries) { |
| 219 | return DriverResult::WrongReply; | 219 | return DriverResult::WrongReply; |
| 220 | } | 220 | } |
| 221 | } while (!(output[15] == 0x13 && output[17] == 0x07) && output[15] != 0x23); | 221 | } while (!(output.command_data[0] == 0x13 && output.command_data[2] == 0x07) && |
| 222 | output.command_data[0] != 0x23); | ||
| 222 | 223 | ||
| 223 | return DriverResult::Success; | 224 | return DriverResult::Success; |
| 224 | } | 225 | } |
| @@ -226,7 +227,7 @@ DriverResult IrsProtocol::WriteRegistersStep1() { | |||
| 226 | DriverResult IrsProtocol::WriteRegistersStep2() { | 227 | DriverResult IrsProtocol::WriteRegistersStep2() { |
| 227 | LOG_DEBUG(Input, "WriteRegistersStep2"); | 228 | LOG_DEBUG(Input, "WriteRegistersStep2"); |
| 228 | constexpr std::size_t max_tries = 28; | 229 | constexpr std::size_t max_tries = 28; |
| 229 | std::vector<u8> output; | 230 | SubCommandResponse output{}; |
| 230 | std::size_t tries = 0; | 231 | std::size_t tries = 0; |
| 231 | 232 | ||
| 232 | const IrsWriteRegisters irs_registers{ | 233 | const IrsWriteRegisters irs_registers{ |
| @@ -260,7 +261,7 @@ DriverResult IrsProtocol::WriteRegistersStep2() { | |||
| 260 | if (tries++ >= max_tries) { | 261 | if (tries++ >= max_tries) { |
| 261 | return DriverResult::WrongReply; | 262 | return DriverResult::WrongReply; |
| 262 | } | 263 | } |
| 263 | } while (output[15] != 0x13 && output[15] != 0x23); | 264 | } while (output.command_data[0] != 0x13 && output.command_data[0] != 0x23); |
| 264 | 265 | ||
| 265 | return DriverResult::Success; | 266 | return DriverResult::Success; |
| 266 | } | 267 | } |
diff --git a/src/input_common/helpers/joycon_protocol/joycon_types.h b/src/input_common/helpers/joycon_protocol/joycon_types.h index ddb48a553..b91934990 100644 --- a/src/input_common/helpers/joycon_protocol/joycon_types.h +++ b/src/input_common/helpers/joycon_protocol/joycon_types.h | |||
| @@ -19,8 +19,6 @@ | |||
| 19 | namespace InputCommon::Joycon { | 19 | namespace InputCommon::Joycon { |
| 20 | constexpr u32 MaxErrorCount = 50; | 20 | constexpr u32 MaxErrorCount = 50; |
| 21 | constexpr u32 MaxBufferSize = 368; | 21 | constexpr u32 MaxBufferSize = 368; |
| 22 | constexpr u32 MaxResponseSize = 49; | ||
| 23 | constexpr u32 MaxSubCommandResponseSize = 64; | ||
| 24 | constexpr std::array<u8, 8> DefaultVibrationBuffer{0x0, 0x1, 0x40, 0x40, 0x0, 0x1, 0x40, 0x40}; | 22 | constexpr std::array<u8, 8> DefaultVibrationBuffer{0x0, 0x1, 0x40, 0x40, 0x0, 0x1, 0x40, 0x40}; |
| 25 | 23 | ||
| 26 | using MacAddress = std::array<u8, 6>; | 24 | using MacAddress = std::array<u8, 6>; |
| @@ -105,14 +103,6 @@ enum class OutputReport : u8 { | |||
| 105 | USB_CMD = 0x80, | 103 | USB_CMD = 0x80, |
| 106 | }; | 104 | }; |
| 107 | 105 | ||
| 108 | enum class InputReport : u8 { | ||
| 109 | SUBCMD_REPLY = 0x21, | ||
| 110 | STANDARD_FULL_60HZ = 0x30, | ||
| 111 | NFC_IR_MODE_60HZ = 0x31, | ||
| 112 | SIMPLE_HID_MODE = 0x3F, | ||
| 113 | INPUT_USB_RESPONSE = 0x81, | ||
| 114 | }; | ||
| 115 | |||
| 116 | enum class FeatureReport : u8 { | 106 | enum class FeatureReport : u8 { |
| 117 | Last_SUBCMD = 0x02, | 107 | Last_SUBCMD = 0x02, |
| 118 | OTA_GW_UPGRADE = 0x70, | 108 | OTA_GW_UPGRADE = 0x70, |
| @@ -171,7 +161,7 @@ enum class CalibrationMagic : u8 { | |||
| 171 | USR_MAGIC_1 = 0xA1, | 161 | USR_MAGIC_1 = 0xA1, |
| 172 | }; | 162 | }; |
| 173 | 163 | ||
| 174 | enum class SpiAddress { | 164 | enum class SpiAddress : u16 { |
| 175 | MAGIC = 0x0000, | 165 | MAGIC = 0x0000, |
| 176 | MAC_ADDRESS = 0x0015, | 166 | MAC_ADDRESS = 0x0015, |
| 177 | PAIRING_INFO = 0x2000, | 167 | PAIRING_INFO = 0x2000, |
| @@ -198,10 +188,12 @@ enum class ReportMode : u8 { | |||
| 198 | ACTIVE_POLLING_NFC_IR_CAMERA_CONFIGURATION = 0x01, | 188 | ACTIVE_POLLING_NFC_IR_CAMERA_CONFIGURATION = 0x01, |
| 199 | ACTIVE_POLLING_NFC_IR_CAMERA_DATA_CONFIGURATION = 0x02, | 189 | ACTIVE_POLLING_NFC_IR_CAMERA_DATA_CONFIGURATION = 0x02, |
| 200 | ACTIVE_POLLING_IR_CAMERA_DATA = 0x03, | 190 | ACTIVE_POLLING_IR_CAMERA_DATA = 0x03, |
| 191 | SUBCMD_REPLY = 0x21, | ||
| 201 | MCU_UPDATE_STATE = 0x23, | 192 | MCU_UPDATE_STATE = 0x23, |
| 202 | STANDARD_FULL_60HZ = 0x30, | 193 | STANDARD_FULL_60HZ = 0x30, |
| 203 | NFC_IR_MODE_60HZ = 0x31, | 194 | NFC_IR_MODE_60HZ = 0x31, |
| 204 | SIMPLE_HID_MODE = 0x3F, | 195 | SIMPLE_HID_MODE = 0x3F, |
| 196 | INPUT_USB_RESPONSE = 0x81, | ||
| 205 | }; | 197 | }; |
| 206 | 198 | ||
| 207 | enum class GyroSensitivity : u8 { | 199 | enum class GyroSensitivity : u8 { |
| @@ -372,15 +364,16 @@ enum class IrRegistersAddress : u16 { | |||
| 372 | DenoiseColor = 0x6901, | 364 | DenoiseColor = 0x6901, |
| 373 | }; | 365 | }; |
| 374 | 366 | ||
| 375 | enum class ExternalDeviceId : u8 { | 367 | enum class ExternalDeviceId : u16 { |
| 376 | RingController = 0x20, | 368 | RingController = 0x2000, |
| 377 | Starlink = 0x28, | 369 | Starlink = 0x2800, |
| 378 | }; | 370 | }; |
| 379 | 371 | ||
| 380 | enum class DriverResult { | 372 | enum class DriverResult { |
| 381 | Success, | 373 | Success, |
| 382 | WrongReply, | 374 | WrongReply, |
| 383 | Timeout, | 375 | Timeout, |
| 376 | InvalidParameters, | ||
| 384 | UnsupportedControllerType, | 377 | UnsupportedControllerType, |
| 385 | HandleInUse, | 378 | HandleInUse, |
| 386 | ErrorReadingData, | 379 | ErrorReadingData, |
| @@ -503,7 +496,7 @@ static_assert(sizeof(MCUConfig) == 0x26, "MCUConfig is an invalid size"); | |||
| 503 | 496 | ||
| 504 | #pragma pack(push, 1) | 497 | #pragma pack(push, 1) |
| 505 | struct InputReportPassive { | 498 | struct InputReportPassive { |
| 506 | InputReport report_mode; | 499 | ReportMode report_mode; |
| 507 | u16 button_input; | 500 | u16 button_input; |
| 508 | u8 stick_state; | 501 | u8 stick_state; |
| 509 | std::array<u8, 10> unknown_data; | 502 | std::array<u8, 10> unknown_data; |
| @@ -511,7 +504,7 @@ struct InputReportPassive { | |||
| 511 | static_assert(sizeof(InputReportPassive) == 0xE, "InputReportPassive is an invalid size"); | 504 | static_assert(sizeof(InputReportPassive) == 0xE, "InputReportPassive is an invalid size"); |
| 512 | 505 | ||
| 513 | struct InputReportActive { | 506 | struct InputReportActive { |
| 514 | InputReport report_mode; | 507 | ReportMode report_mode; |
| 515 | u8 packet_id; | 508 | u8 packet_id; |
| 516 | Battery battery_status; | 509 | Battery battery_status; |
| 517 | std::array<u8, 3> button_input; | 510 | std::array<u8, 3> button_input; |
| @@ -525,7 +518,7 @@ struct InputReportActive { | |||
| 525 | static_assert(sizeof(InputReportActive) == 0x29, "InputReportActive is an invalid size"); | 518 | static_assert(sizeof(InputReportActive) == 0x29, "InputReportActive is an invalid size"); |
| 526 | 519 | ||
| 527 | struct InputReportNfcIr { | 520 | struct InputReportNfcIr { |
| 528 | InputReport report_mode; | 521 | ReportMode report_mode; |
| 529 | u8 packet_id; | 522 | u8 packet_id; |
| 530 | Battery battery_status; | 523 | Battery battery_status; |
| 531 | std::array<u8, 3> button_input; | 524 | std::array<u8, 3> button_input; |
| @@ -643,6 +636,53 @@ struct RingStatus { | |||
| 643 | s16 min_value; | 636 | s16 min_value; |
| 644 | }; | 637 | }; |
| 645 | 638 | ||
| 639 | struct VibrationPacket { | ||
| 640 | OutputReport output_report; | ||
| 641 | u8 packet_counter; | ||
| 642 | std::array<u8, 0x8> vibration_data; | ||
| 643 | }; | ||
| 644 | static_assert(sizeof(VibrationPacket) == 0xA, "VibrationPacket is an invalid size"); | ||
| 645 | |||
| 646 | struct SubCommandPacket { | ||
| 647 | OutputReport output_report; | ||
| 648 | u8 packet_counter; | ||
| 649 | INSERT_PADDING_BYTES(0x8); // This contains vibration data | ||
| 650 | SubCommand sub_command; | ||
| 651 | std::array<u8, 0x26> command_data; | ||
| 652 | }; | ||
| 653 | static_assert(sizeof(SubCommandPacket) == 0x31, "SubCommandPacket is an invalid size"); | ||
| 654 | |||
| 655 | #pragma pack(push, 1) | ||
| 656 | struct ReadSpiPacket { | ||
| 657 | SpiAddress spi_address; | ||
| 658 | INSERT_PADDING_BYTES(0x2); | ||
| 659 | u8 size; | ||
| 660 | }; | ||
| 661 | static_assert(sizeof(ReadSpiPacket) == 0x5, "ReadSpiPacket is an invalid size"); | ||
| 662 | |||
| 663 | struct SubCommandResponse { | ||
| 664 | InputReportPassive input_report; | ||
| 665 | SubCommand sub_command; | ||
| 666 | union { | ||
| 667 | std::array<u8, 0x30> command_data; | ||
| 668 | SpiAddress spi_address; // Reply from SPI_FLASH_READ subcommand | ||
| 669 | ExternalDeviceId external_device_id; // Reply from GET_EXTERNAL_DEVICE_INFO subcommand | ||
| 670 | DeviceInfo device_info; // Reply from REQ_DEV_INFO subcommand | ||
| 671 | }; | ||
| 672 | u8 crc; // This is never used | ||
| 673 | }; | ||
| 674 | static_assert(sizeof(SubCommandResponse) == 0x40, "SubCommandResponse is an invalid size"); | ||
| 675 | #pragma pack(pop) | ||
| 676 | |||
| 677 | struct MCUCommandResponse { | ||
| 678 | InputReportNfcIr input_report; | ||
| 679 | INSERT_PADDING_BYTES(0x8); | ||
| 680 | MCUReport mcu_report; | ||
| 681 | std::array<u8, 0x13D> mcu_data; | ||
| 682 | u8 crc; | ||
| 683 | }; | ||
| 684 | static_assert(sizeof(MCUCommandResponse) == 0x170, "MCUCommandResponse is an invalid size"); | ||
| 685 | |||
| 646 | struct JoyconCallbacks { | 686 | struct JoyconCallbacks { |
| 647 | std::function<void(Battery)> on_battery_data; | 687 | std::function<void(Battery)> on_battery_data; |
| 648 | std::function<void(Color)> on_color_data; | 688 | std::function<void(Color)> on_color_data; |
diff --git a/src/input_common/helpers/joycon_protocol/nfc.cpp b/src/input_common/helpers/joycon_protocol/nfc.cpp index 5c0f71722..eeba82986 100644 --- a/src/input_common/helpers/joycon_protocol/nfc.cpp +++ b/src/input_common/helpers/joycon_protocol/nfc.cpp | |||
| @@ -110,7 +110,7 @@ bool NfcProtocol::HasAmiibo() { | |||
| 110 | 110 | ||
| 111 | DriverResult NfcProtocol::WaitUntilNfcIsReady() { | 111 | DriverResult NfcProtocol::WaitUntilNfcIsReady() { |
| 112 | constexpr std::size_t timeout_limit = 10; | 112 | constexpr std::size_t timeout_limit = 10; |
| 113 | std::vector<u8> output; | 113 | MCUCommandResponse output{}; |
| 114 | std::size_t tries = 0; | 114 | std::size_t tries = 0; |
| 115 | 115 | ||
| 116 | do { | 116 | do { |
| @@ -122,8 +122,9 @@ DriverResult NfcProtocol::WaitUntilNfcIsReady() { | |||
| 122 | if (tries++ > timeout_limit) { | 122 | if (tries++ > timeout_limit) { |
| 123 | return DriverResult::Timeout; | 123 | return DriverResult::Timeout; |
| 124 | } | 124 | } |
| 125 | } while (output[49] != 0x2a || (output[51] << 8) + output[50] != 0x0500 || output[55] != 0x31 || | 125 | } while (output.mcu_report != MCUReport::NFCState || |
| 126 | output[56] != 0x00); | 126 | (output.mcu_data[1] << 8) + output.mcu_data[0] != 0x0500 || |
| 127 | output.mcu_data[5] != 0x31 || output.mcu_data[6] != 0x00); | ||
| 127 | 128 | ||
| 128 | return DriverResult::Success; | 129 | return DriverResult::Success; |
| 129 | } | 130 | } |
| @@ -131,7 +132,7 @@ DriverResult NfcProtocol::WaitUntilNfcIsReady() { | |||
| 131 | DriverResult NfcProtocol::StartPolling(TagFoundData& data) { | 132 | DriverResult NfcProtocol::StartPolling(TagFoundData& data) { |
| 132 | LOG_DEBUG(Input, "Start Polling for tag"); | 133 | LOG_DEBUG(Input, "Start Polling for tag"); |
| 133 | constexpr std::size_t timeout_limit = 7; | 134 | constexpr std::size_t timeout_limit = 7; |
| 134 | std::vector<u8> output; | 135 | MCUCommandResponse output{}; |
| 135 | std::size_t tries = 0; | 136 | std::size_t tries = 0; |
| 136 | 137 | ||
| 137 | do { | 138 | do { |
| @@ -142,18 +143,20 @@ DriverResult NfcProtocol::StartPolling(TagFoundData& data) { | |||
| 142 | if (tries++ > timeout_limit) { | 143 | if (tries++ > timeout_limit) { |
| 143 | return DriverResult::Timeout; | 144 | return DriverResult::Timeout; |
| 144 | } | 145 | } |
| 145 | } while (output[49] != 0x2a || (output[51] << 8) + output[50] != 0x0500 || output[56] != 0x09); | 146 | } while (output.mcu_report != MCUReport::NFCState || |
| 147 | (output.mcu_data[1] << 8) + output.mcu_data[0] != 0x0500 || | ||
| 148 | output.mcu_data[6] != 0x09); | ||
| 146 | 149 | ||
| 147 | data.type = output[62]; | 150 | data.type = output.mcu_data[12]; |
| 148 | data.uuid.resize(output[64]); | 151 | data.uuid.resize(output.mcu_data[14]); |
| 149 | memcpy(data.uuid.data(), output.data() + 65, data.uuid.size()); | 152 | memcpy(data.uuid.data(), output.mcu_data.data() + 15, data.uuid.size()); |
| 150 | 153 | ||
| 151 | return DriverResult::Success; | 154 | return DriverResult::Success; |
| 152 | } | 155 | } |
| 153 | 156 | ||
| 154 | DriverResult NfcProtocol::ReadTag(const TagFoundData& data) { | 157 | DriverResult NfcProtocol::ReadTag(const TagFoundData& data) { |
| 155 | constexpr std::size_t timeout_limit = 10; | 158 | constexpr std::size_t timeout_limit = 10; |
| 156 | std::vector<u8> output; | 159 | MCUCommandResponse output{}; |
| 157 | std::size_t tries = 0; | 160 | std::size_t tries = 0; |
| 158 | 161 | ||
| 159 | std::string uuid_string; | 162 | std::string uuid_string; |
| @@ -168,23 +171,24 @@ DriverResult NfcProtocol::ReadTag(const TagFoundData& data) { | |||
| 168 | // Read Tag data | 171 | // Read Tag data |
| 169 | while (true) { | 172 | while (true) { |
| 170 | auto result = SendReadAmiiboRequest(output, ntag_pages); | 173 | auto result = SendReadAmiiboRequest(output, ntag_pages); |
| 171 | const auto mcu_report = static_cast<MCUReport>(output[49]); | 174 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); |
| 172 | const auto nfc_status = static_cast<NFCStatus>(output[56]); | ||
| 173 | 175 | ||
| 174 | if (result != DriverResult::Success) { | 176 | if (result != DriverResult::Success) { |
| 175 | return result; | 177 | return result; |
| 176 | } | 178 | } |
| 177 | 179 | ||
| 178 | if ((mcu_report == MCUReport::NFCReadData || mcu_report == MCUReport::NFCState) && | 180 | if ((output.mcu_report == MCUReport::NFCReadData || |
| 181 | output.mcu_report == MCUReport::NFCState) && | ||
| 179 | nfc_status == NFCStatus::TagLost) { | 182 | nfc_status == NFCStatus::TagLost) { |
| 180 | return DriverResult::ErrorReadingData; | 183 | return DriverResult::ErrorReadingData; |
| 181 | } | 184 | } |
| 182 | 185 | ||
| 183 | if (mcu_report == MCUReport::NFCReadData && output[51] == 0x07 && output[52] == 0x01) { | 186 | if (output.mcu_report == MCUReport::NFCReadData && output.mcu_data[1] == 0x07 && |
| 187 | output.mcu_data[2] == 0x01) { | ||
| 184 | if (data.type != 2) { | 188 | if (data.type != 2) { |
| 185 | continue; | 189 | continue; |
| 186 | } | 190 | } |
| 187 | switch (output[74]) { | 191 | switch (output.mcu_data[24]) { |
| 188 | case 0: | 192 | case 0: |
| 189 | ntag_pages = NFCPages::Block135; | 193 | ntag_pages = NFCPages::Block135; |
| 190 | break; | 194 | break; |
| @@ -200,14 +204,14 @@ DriverResult NfcProtocol::ReadTag(const TagFoundData& data) { | |||
| 200 | continue; | 204 | continue; |
| 201 | } | 205 | } |
| 202 | 206 | ||
| 203 | if (mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) { | 207 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) { |
| 204 | // finished | 208 | // finished |
| 205 | SendStopPollingRequest(output); | 209 | SendStopPollingRequest(output); |
| 206 | return DriverResult::Success; | 210 | return DriverResult::Success; |
| 207 | } | 211 | } |
| 208 | 212 | ||
| 209 | // Ignore other state reports | 213 | // Ignore other state reports |
| 210 | if (mcu_report == MCUReport::NFCState) { | 214 | if (output.mcu_report == MCUReport::NFCState) { |
| 211 | continue; | 215 | continue; |
| 212 | } | 216 | } |
| 213 | 217 | ||
| @@ -221,7 +225,7 @@ DriverResult NfcProtocol::ReadTag(const TagFoundData& data) { | |||
| 221 | 225 | ||
| 222 | DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) { | 226 | DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) { |
| 223 | constexpr std::size_t timeout_limit = 10; | 227 | constexpr std::size_t timeout_limit = 10; |
| 224 | std::vector<u8> output; | 228 | MCUCommandResponse output{}; |
| 225 | std::size_t tries = 0; | 229 | std::size_t tries = 0; |
| 226 | 230 | ||
| 227 | NFCPages ntag_pages = NFCPages::Block135; | 231 | NFCPages ntag_pages = NFCPages::Block135; |
| @@ -229,36 +233,38 @@ DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) { | |||
| 229 | // Read Tag data | 233 | // Read Tag data |
| 230 | while (true) { | 234 | while (true) { |
| 231 | auto result = SendReadAmiiboRequest(output, ntag_pages); | 235 | auto result = SendReadAmiiboRequest(output, ntag_pages); |
| 232 | const auto mcu_report = static_cast<MCUReport>(output[49]); | 236 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); |
| 233 | const auto nfc_status = static_cast<NFCStatus>(output[56]); | ||
| 234 | 237 | ||
| 235 | if (result != DriverResult::Success) { | 238 | if (result != DriverResult::Success) { |
| 236 | return result; | 239 | return result; |
| 237 | } | 240 | } |
| 238 | 241 | ||
| 239 | if ((mcu_report == MCUReport::NFCReadData || mcu_report == MCUReport::NFCState) && | 242 | if ((output.mcu_report == MCUReport::NFCReadData || |
| 243 | output.mcu_report == MCUReport::NFCState) && | ||
| 240 | nfc_status == NFCStatus::TagLost) { | 244 | nfc_status == NFCStatus::TagLost) { |
| 241 | return DriverResult::ErrorReadingData; | 245 | return DriverResult::ErrorReadingData; |
| 242 | } | 246 | } |
| 243 | 247 | ||
| 244 | if (mcu_report == MCUReport::NFCReadData && output[51] == 0x07) { | 248 | if (output.mcu_report == MCUReport::NFCReadData && output.mcu_data[1] == 0x07) { |
| 245 | std::size_t payload_size = (output[54] << 8 | output[55]) & 0x7FF; | 249 | std::size_t payload_size = (output.mcu_data[4] << 8 | output.mcu_data[5]) & 0x7FF; |
| 246 | if (output[52] == 0x01) { | 250 | if (output.mcu_data[2] == 0x01) { |
| 247 | memcpy(ntag_data.data() + ntag_buffer_pos, output.data() + 116, payload_size - 60); | 251 | memcpy(ntag_data.data() + ntag_buffer_pos, output.mcu_data.data() + 66, |
| 252 | payload_size - 60); | ||
| 248 | ntag_buffer_pos += payload_size - 60; | 253 | ntag_buffer_pos += payload_size - 60; |
| 249 | } else { | 254 | } else { |
| 250 | memcpy(ntag_data.data() + ntag_buffer_pos, output.data() + 56, payload_size); | 255 | memcpy(ntag_data.data() + ntag_buffer_pos, output.mcu_data.data() + 6, |
| 256 | payload_size); | ||
| 251 | } | 257 | } |
| 252 | continue; | 258 | continue; |
| 253 | } | 259 | } |
| 254 | 260 | ||
| 255 | if (mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) { | 261 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) { |
| 256 | LOG_INFO(Input, "Finished reading amiibo"); | 262 | LOG_INFO(Input, "Finished reading amiibo"); |
| 257 | return DriverResult::Success; | 263 | return DriverResult::Success; |
| 258 | } | 264 | } |
| 259 | 265 | ||
| 260 | // Ignore other state reports | 266 | // Ignore other state reports |
| 261 | if (mcu_report == MCUReport::NFCState) { | 267 | if (output.mcu_report == MCUReport::NFCState) { |
| 262 | continue; | 268 | continue; |
| 263 | } | 269 | } |
| 264 | 270 | ||
| @@ -270,7 +276,7 @@ DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) { | |||
| 270 | return DriverResult::Success; | 276 | return DriverResult::Success; |
| 271 | } | 277 | } |
| 272 | 278 | ||
| 273 | DriverResult NfcProtocol::SendStartPollingRequest(std::vector<u8>& output) { | 279 | DriverResult NfcProtocol::SendStartPollingRequest(MCUCommandResponse& output) { |
| 274 | NFCRequestState request{ | 280 | NFCRequestState request{ |
| 275 | .sub_command = MCUSubCommand::ReadDeviceMode, | 281 | .sub_command = MCUSubCommand::ReadDeviceMode, |
| 276 | .command_argument = NFCReadCommand::StartPolling, | 282 | .command_argument = NFCReadCommand::StartPolling, |
| @@ -294,7 +300,7 @@ DriverResult NfcProtocol::SendStartPollingRequest(std::vector<u8>& output) { | |||
| 294 | return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); | 300 | return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); |
| 295 | } | 301 | } |
| 296 | 302 | ||
| 297 | DriverResult NfcProtocol::SendStopPollingRequest(std::vector<u8>& output) { | 303 | DriverResult NfcProtocol::SendStopPollingRequest(MCUCommandResponse& output) { |
| 298 | NFCRequestState request{ | 304 | NFCRequestState request{ |
| 299 | .sub_command = MCUSubCommand::ReadDeviceMode, | 305 | .sub_command = MCUSubCommand::ReadDeviceMode, |
| 300 | .command_argument = NFCReadCommand::StopPolling, | 306 | .command_argument = NFCReadCommand::StopPolling, |
| @@ -311,7 +317,7 @@ DriverResult NfcProtocol::SendStopPollingRequest(std::vector<u8>& output) { | |||
| 311 | return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); | 317 | return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); |
| 312 | } | 318 | } |
| 313 | 319 | ||
| 314 | DriverResult NfcProtocol::SendStartWaitingRecieveRequest(std::vector<u8>& output) { | 320 | DriverResult NfcProtocol::SendStartWaitingRecieveRequest(MCUCommandResponse& output) { |
| 315 | NFCRequestState request{ | 321 | NFCRequestState request{ |
| 316 | .sub_command = MCUSubCommand::ReadDeviceMode, | 322 | .sub_command = MCUSubCommand::ReadDeviceMode, |
| 317 | .command_argument = NFCReadCommand::StartWaitingRecieve, | 323 | .command_argument = NFCReadCommand::StartWaitingRecieve, |
| @@ -328,7 +334,7 @@ DriverResult NfcProtocol::SendStartWaitingRecieveRequest(std::vector<u8>& output | |||
| 328 | return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); | 334 | return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); |
| 329 | } | 335 | } |
| 330 | 336 | ||
| 331 | DriverResult NfcProtocol::SendReadAmiiboRequest(std::vector<u8>& output, NFCPages ntag_pages) { | 337 | DriverResult NfcProtocol::SendReadAmiiboRequest(MCUCommandResponse& output, NFCPages ntag_pages) { |
| 332 | NFCRequestState request{ | 338 | NFCRequestState request{ |
| 333 | .sub_command = MCUSubCommand::ReadDeviceMode, | 339 | .sub_command = MCUSubCommand::ReadDeviceMode, |
| 334 | .command_argument = NFCReadCommand::Ntag, | 340 | .command_argument = NFCReadCommand::Ntag, |
diff --git a/src/input_common/helpers/joycon_protocol/nfc.h b/src/input_common/helpers/joycon_protocol/nfc.h index e63665aa9..11e263e07 100644 --- a/src/input_common/helpers/joycon_protocol/nfc.h +++ b/src/input_common/helpers/joycon_protocol/nfc.h | |||
| @@ -45,13 +45,13 @@ private: | |||
| 45 | 45 | ||
| 46 | DriverResult GetAmiiboData(std::vector<u8>& data); | 46 | DriverResult GetAmiiboData(std::vector<u8>& data); |
| 47 | 47 | ||
| 48 | DriverResult SendStartPollingRequest(std::vector<u8>& output); | 48 | DriverResult SendStartPollingRequest(MCUCommandResponse& output); |
| 49 | 49 | ||
| 50 | DriverResult SendStopPollingRequest(std::vector<u8>& output); | 50 | DriverResult SendStopPollingRequest(MCUCommandResponse& output); |
| 51 | 51 | ||
| 52 | DriverResult SendStartWaitingRecieveRequest(std::vector<u8>& output); | 52 | DriverResult SendStartWaitingRecieveRequest(MCUCommandResponse& output); |
| 53 | 53 | ||
| 54 | DriverResult SendReadAmiiboRequest(std::vector<u8>& output, NFCPages ntag_pages); | 54 | DriverResult SendReadAmiiboRequest(MCUCommandResponse& output, NFCPages ntag_pages); |
| 55 | 55 | ||
| 56 | NFCReadBlockCommand GetReadBlockCommand(NFCPages pages) const; | 56 | NFCReadBlockCommand GetReadBlockCommand(NFCPages pages) const; |
| 57 | 57 | ||
diff --git a/src/input_common/helpers/joycon_protocol/ringcon.cpp b/src/input_common/helpers/joycon_protocol/ringcon.cpp index 3c2ca4379..190cef812 100644 --- a/src/input_common/helpers/joycon_protocol/ringcon.cpp +++ b/src/input_common/helpers/joycon_protocol/ringcon.cpp | |||
| @@ -70,7 +70,7 @@ DriverResult RingConProtocol::StartRingconPolling() { | |||
| 70 | DriverResult RingConProtocol::IsRingConnected(bool& is_connected) { | 70 | DriverResult RingConProtocol::IsRingConnected(bool& is_connected) { |
| 71 | LOG_DEBUG(Input, "IsRingConnected"); | 71 | LOG_DEBUG(Input, "IsRingConnected"); |
| 72 | constexpr std::size_t max_tries = 28; | 72 | constexpr std::size_t max_tries = 28; |
| 73 | std::vector<u8> output; | 73 | SubCommandResponse output{}; |
| 74 | std::size_t tries = 0; | 74 | std::size_t tries = 0; |
| 75 | is_connected = false; | 75 | is_connected = false; |
| 76 | 76 | ||
| @@ -84,7 +84,7 @@ DriverResult RingConProtocol::IsRingConnected(bool& is_connected) { | |||
| 84 | if (tries++ >= max_tries) { | 84 | if (tries++ >= max_tries) { |
| 85 | return DriverResult::NoDeviceDetected; | 85 | return DriverResult::NoDeviceDetected; |
| 86 | } | 86 | } |
| 87 | } while (output[16] != static_cast<u8>(ExternalDeviceId::RingController)); | 87 | } while (output.external_device_id != ExternalDeviceId::RingController); |
| 88 | 88 | ||
| 89 | is_connected = true; | 89 | is_connected = true; |
| 90 | return DriverResult::Success; | 90 | return DriverResult::Success; |