diff options
| author | 2022-12-20 20:27:34 -0600 | |
|---|---|---|
| committer | 2023-01-19 18:05:21 -0600 | |
| commit | f09a023292e659af46d551b9b134d94d000a57c7 (patch) | |
| tree | f34ef390cac9f32f7d807614505601635ac62e28 /src/input_common/helpers/joycon_driver.cpp | |
| parent | input_common: Use calibration from joycon (diff) | |
| download | yuzu-f09a023292e659af46d551b9b134d94d000a57c7.tar.gz yuzu-f09a023292e659af46d551b9b134d94d000a57c7.tar.xz yuzu-f09a023292e659af46d551b9b134d94d000a57c7.zip | |
input_common: Add support for joycon input reports
Diffstat (limited to 'src/input_common/helpers/joycon_driver.cpp')
| -rw-r--r-- | src/input_common/helpers/joycon_driver.cpp | 100 |
1 files changed, 40 insertions, 60 deletions
diff --git a/src/input_common/helpers/joycon_driver.cpp b/src/input_common/helpers/joycon_driver.cpp index ac11be1c1..5d0aeabf5 100644 --- a/src/input_common/helpers/joycon_driver.cpp +++ b/src/input_common/helpers/joycon_driver.cpp | |||
| @@ -66,6 +66,7 @@ DriverResult JoyconDriver::InitializeDevice() { | |||
| 66 | // Initialize HW Protocols | 66 | // Initialize HW Protocols |
| 67 | calibration_protocol = std::make_unique<CalibrationProtocol>(hidapi_handle); | 67 | calibration_protocol = std::make_unique<CalibrationProtocol>(hidapi_handle); |
| 68 | generic_protocol = std::make_unique<GenericProtocol>(hidapi_handle); | 68 | generic_protocol = std::make_unique<GenericProtocol>(hidapi_handle); |
| 69 | rumble_protocol = std::make_unique<RumbleProtocol>(hidapi_handle); | ||
| 69 | 70 | ||
| 70 | // Get fixed joycon info | 71 | // Get fixed joycon info |
| 71 | generic_protocol->GetVersionNumber(version); | 72 | generic_protocol->GetVersionNumber(version); |
| @@ -90,6 +91,10 @@ DriverResult JoyconDriver::InitializeDevice() { | |||
| 90 | // Apply HW configuration | 91 | // Apply HW configuration |
| 91 | SetPollingMode(); | 92 | SetPollingMode(); |
| 92 | 93 | ||
| 94 | // Initialize joycon poller | ||
| 95 | joycon_poller = std::make_unique<JoyconPoller>(device_type, left_stick_calibration, | ||
| 96 | right_stick_calibration, motion_calibration); | ||
| 97 | |||
| 93 | // Start pooling for data | 98 | // Start pooling for data |
| 94 | is_connected = true; | 99 | is_connected = true; |
| 95 | if (!input_thread_running) { | 100 | if (!input_thread_running) { |
| @@ -142,15 +147,40 @@ void JoyconDriver::InputThread(std::stop_token stop_token) { | |||
| 142 | void JoyconDriver::OnNewData(std::span<u8> buffer) { | 147 | void JoyconDriver::OnNewData(std::span<u8> buffer) { |
| 143 | const auto report_mode = static_cast<InputReport>(buffer[0]); | 148 | const auto report_mode = static_cast<InputReport>(buffer[0]); |
| 144 | 149 | ||
| 150 | // Packages can be a litte bit inconsistent. Average the delta time to provide a smoother motion | ||
| 151 | // experience | ||
| 152 | switch (report_mode) { | ||
| 153 | case InputReport::STANDARD_FULL_60HZ: | ||
| 154 | case InputReport::NFC_IR_MODE_60HZ: | ||
| 155 | case InputReport::SIMPLE_HID_MODE: { | ||
| 156 | const auto now = std::chrono::steady_clock::now(); | ||
| 157 | const auto new_delta_time = static_cast<u64>( | ||
| 158 | std::chrono::duration_cast<std::chrono::microseconds>(now - last_update).count()); | ||
| 159 | delta_time = ((delta_time * 8) + (new_delta_time * 2)) / 10; | ||
| 160 | last_update = now; | ||
| 161 | joycon_poller->UpdateColor(color); | ||
| 162 | break; | ||
| 163 | } | ||
| 164 | default: | ||
| 165 | break; | ||
| 166 | } | ||
| 167 | |||
| 168 | const MotionStatus motion_status{ | ||
| 169 | .is_enabled = motion_enabled, | ||
| 170 | .delta_time = delta_time, | ||
| 171 | .gyro_sensitivity = gyro_sensitivity, | ||
| 172 | .accelerometer_sensitivity = accelerometer_sensitivity, | ||
| 173 | }; | ||
| 174 | |||
| 145 | switch (report_mode) { | 175 | switch (report_mode) { |
| 146 | case InputReport::STANDARD_FULL_60HZ: | 176 | case InputReport::STANDARD_FULL_60HZ: |
| 147 | ReadActiveMode(buffer); | 177 | joycon_poller->ReadActiveMode(buffer, motion_status); |
| 148 | break; | 178 | break; |
| 149 | case InputReport::NFC_IR_MODE_60HZ: | 179 | case InputReport::NFC_IR_MODE_60HZ: |
| 150 | ReadNfcIRMode(buffer); | 180 | joycon_poller->ReadNfcIRMode(buffer, motion_status); |
| 151 | break; | 181 | break; |
| 152 | case InputReport::SIMPLE_HID_MODE: | 182 | case InputReport::SIMPLE_HID_MODE: |
| 153 | ReadPassiveMode(buffer); | 183 | joycon_poller->ReadPassiveMode(buffer); |
| 154 | break; | 184 | break; |
| 155 | case InputReport::SUBCMD_REPLY: | 185 | case InputReport::SUBCMD_REPLY: |
| 156 | LOG_DEBUG(Input, "Unhandled command reply"); | 186 | LOG_DEBUG(Input, "Unhandled command reply"); |
| @@ -164,6 +194,8 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) { | |||
| 164 | void JoyconDriver::SetPollingMode() { | 194 | void JoyconDriver::SetPollingMode() { |
| 165 | disable_input_thread = true; | 195 | disable_input_thread = true; |
| 166 | 196 | ||
| 197 | rumble_protocol->EnableRumble(vibration_enabled && supported_features.vibration); | ||
| 198 | |||
| 167 | if (motion_enabled && supported_features.motion) { | 199 | if (motion_enabled && supported_features.motion) { |
| 168 | generic_protocol->EnableImu(true); | 200 | generic_protocol->EnableImu(true); |
| 169 | generic_protocol->SetImuConfig(gyro_sensitivity, gyro_performance, | 201 | generic_protocol->SetImuConfig(gyro_sensitivity, gyro_performance, |
| @@ -209,62 +241,6 @@ JoyconDriver::SupportedFeatures JoyconDriver::GetSupportedFeatures() { | |||
| 209 | return features; | 241 | return features; |
| 210 | } | 242 | } |
| 211 | 243 | ||
| 212 | void JoyconDriver::ReadActiveMode(std::span<u8> buffer) { | ||
| 213 | InputReportActive data{}; | ||
| 214 | memcpy(&data, buffer.data(), sizeof(InputReportActive)); | ||
| 215 | |||
| 216 | // Packages can be a litte bit inconsistent. Average the delta time to provide a smoother motion | ||
| 217 | // experience | ||
| 218 | const auto now = std::chrono::steady_clock::now(); | ||
| 219 | const auto new_delta_time = | ||
| 220 | std::chrono::duration_cast<std::chrono::microseconds>(now - last_update).count(); | ||
| 221 | delta_time = static_cast<u64>((delta_time * 0.8f) + (new_delta_time * 0.2)); | ||
| 222 | last_update = now; | ||
| 223 | |||
| 224 | switch (device_type) { | ||
| 225 | case Joycon::ControllerType::Left: | ||
| 226 | break; | ||
| 227 | case Joycon::ControllerType::Right: | ||
| 228 | break; | ||
| 229 | case Joycon::ControllerType::Pro: | ||
| 230 | break; | ||
| 231 | case Joycon::ControllerType::Grip: | ||
| 232 | case Joycon::ControllerType::Dual: | ||
| 233 | case Joycon::ControllerType::None: | ||
| 234 | break; | ||
| 235 | } | ||
| 236 | |||
| 237 | on_battery_data(data.battery_status); | ||
| 238 | on_color_data(color); | ||
| 239 | } | ||
| 240 | |||
| 241 | void JoyconDriver::ReadPassiveMode(std::span<u8> buffer) { | ||
| 242 | InputReportPassive data{}; | ||
| 243 | memcpy(&data, buffer.data(), sizeof(InputReportPassive)); | ||
| 244 | |||
| 245 | switch (device_type) { | ||
| 246 | case Joycon::ControllerType::Left: | ||
| 247 | break; | ||
| 248 | case Joycon::ControllerType::Right: | ||
| 249 | break; | ||
| 250 | case Joycon::ControllerType::Pro: | ||
| 251 | break; | ||
| 252 | case Joycon::ControllerType::Grip: | ||
| 253 | case Joycon::ControllerType::Dual: | ||
| 254 | case Joycon::ControllerType::None: | ||
| 255 | break; | ||
| 256 | } | ||
| 257 | } | ||
| 258 | |||
| 259 | void JoyconDriver::ReadNfcIRMode(std::span<u8> buffer) { | ||
| 260 | // This mode is compatible with the active mode | ||
| 261 | ReadActiveMode(buffer); | ||
| 262 | |||
| 263 | if (!nfc_enabled) { | ||
| 264 | return; | ||
| 265 | } | ||
| 266 | } | ||
| 267 | |||
| 268 | bool JoyconDriver::IsInputThreadValid() const { | 244 | bool JoyconDriver::IsInputThreadValid() const { |
| 269 | if (!is_connected) { | 245 | if (!is_connected) { |
| 270 | return false; | 246 | return false; |
| @@ -302,7 +278,7 @@ DriverResult JoyconDriver::SetVibration(const VibrationValue& vibration) { | |||
| 302 | if (disable_input_thread) { | 278 | if (disable_input_thread) { |
| 303 | return DriverResult::HandleInUse; | 279 | return DriverResult::HandleInUse; |
| 304 | } | 280 | } |
| 305 | return DriverResult::NotSupported; | 281 | return rumble_protocol->SendVibration(vibration); |
| 306 | } | 282 | } |
| 307 | 283 | ||
| 308 | DriverResult JoyconDriver::SetLedConfig(u8 led_pattern) { | 284 | DriverResult JoyconDriver::SetLedConfig(u8 led_pattern) { |
| @@ -398,6 +374,10 @@ SerialNumber JoyconDriver::GetHandleSerialNumber() const { | |||
| 398 | return handle_serial_number; | 374 | return handle_serial_number; |
| 399 | } | 375 | } |
| 400 | 376 | ||
| 377 | void JoyconDriver::SetCallbacks(const Joycon::JoyconCallbacks& callbacks) { | ||
| 378 | joycon_poller->SetCallbacks(callbacks); | ||
| 379 | } | ||
| 380 | |||
| 401 | Joycon::DriverResult JoyconDriver::GetDeviceType(SDL_hid_device_info* device_info, | 381 | Joycon::DriverResult JoyconDriver::GetDeviceType(SDL_hid_device_info* device_info, |
| 402 | ControllerType& controller_type) { | 382 | ControllerType& controller_type) { |
| 403 | std::array<std::pair<u32, Joycon::ControllerType>, 4> supported_devices{ | 383 | std::array<std::pair<u32, Joycon::ControllerType>, 4> supported_devices{ |