summaryrefslogtreecommitdiff
path: root/src/input_common/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common/drivers')
-rw-r--r--src/input_common/drivers/joycon.cpp158
-rw-r--r--src/input_common/drivers/joycon.h19
-rw-r--r--src/input_common/drivers/mouse.cpp99
-rw-r--r--src/input_common/drivers/mouse.h2
-rw-r--r--src/input_common/drivers/sdl_driver.cpp32
-rw-r--r--src/input_common/drivers/virtual_amiibo.cpp130
-rw-r--r--src/input_common/drivers/virtual_amiibo.h16
7 files changed, 356 insertions, 100 deletions
diff --git a/src/input_common/drivers/joycon.cpp b/src/input_common/drivers/joycon.cpp
index b2b5677c8..0aca5a3a3 100644
--- a/src/input_common/drivers/joycon.cpp
+++ b/src/input_common/drivers/joycon.cpp
@@ -102,12 +102,12 @@ bool Joycons::IsDeviceNew(SDL_hid_device_info* device_info) const {
102 Joycon::SerialNumber serial_number{}; 102 Joycon::SerialNumber serial_number{};
103 103
104 const auto result = Joycon::JoyconDriver::GetDeviceType(device_info, type); 104 const auto result = Joycon::JoyconDriver::GetDeviceType(device_info, type);
105 if (result != Joycon::DriverResult::Success) { 105 if (result != Common::Input::DriverResult::Success) {
106 return false; 106 return false;
107 } 107 }
108 108
109 const auto result2 = Joycon::JoyconDriver::GetSerialNumber(device_info, serial_number); 109 const auto result2 = Joycon::JoyconDriver::GetSerialNumber(device_info, serial_number);
110 if (result2 != Joycon::DriverResult::Success) { 110 if (result2 != Common::Input::DriverResult::Success) {
111 return false; 111 return false;
112 } 112 }
113 113
@@ -171,10 +171,10 @@ void Joycons::RegisterNewDevice(SDL_hid_device_info* device_info) {
171 LOG_WARNING(Input, "No free handles available"); 171 LOG_WARNING(Input, "No free handles available");
172 return; 172 return;
173 } 173 }
174 if (result == Joycon::DriverResult::Success) { 174 if (result == Common::Input::DriverResult::Success) {
175 result = handle->RequestDeviceAccess(device_info); 175 result = handle->RequestDeviceAccess(device_info);
176 } 176 }
177 if (result == Joycon::DriverResult::Success) { 177 if (result == Common::Input::DriverResult::Success) {
178 LOG_WARNING(Input, "Initialize device"); 178 LOG_WARNING(Input, "Initialize device");
179 179
180 const std::size_t port = handle->GetDevicePort(); 180 const std::size_t port = handle->GetDevicePort();
@@ -195,8 +195,8 @@ void Joycons::RegisterNewDevice(SDL_hid_device_info* device_info) {
195 OnMotionUpdate(port, type, id, value); 195 OnMotionUpdate(port, type, id, value);
196 }}, 196 }},
197 .on_ring_data = {[this](f32 ring_data) { OnRingConUpdate(ring_data); }}, 197 .on_ring_data = {[this](f32 ring_data) { OnRingConUpdate(ring_data); }},
198 .on_amiibo_data = {[this, port, type](const std::vector<u8>& amiibo_data) { 198 .on_amiibo_data = {[this, port, type](const Joycon::TagInfo& tag_info) {
199 OnAmiiboUpdate(port, type, amiibo_data); 199 OnAmiiboUpdate(port, type, tag_info);
200 }}, 200 }},
201 .on_camera_data = {[this, port](const std::vector<u8>& camera_data, 201 .on_camera_data = {[this, port](const std::vector<u8>& camera_data,
202 Joycon::IrsResolution format) { 202 Joycon::IrsResolution format) {
@@ -273,8 +273,7 @@ Common::Input::DriverResult Joycons::SetLeds(const PadIdentifier& identifier,
273 led_config += led_status.led_3 ? 4 : 0; 273 led_config += led_status.led_3 ? 4 : 0;
274 led_config += led_status.led_4 ? 8 : 0; 274 led_config += led_status.led_4 ? 8 : 0;
275 275
276 return static_cast<Common::Input::DriverResult>( 276 return handle->SetLedConfig(static_cast<u8>(led_config));
277 handle->SetLedConfig(static_cast<u8>(led_config)));
278} 277}
279 278
280Common::Input::DriverResult Joycons::SetCameraFormat(const PadIdentifier& identifier, 279Common::Input::DriverResult Joycons::SetCameraFormat(const PadIdentifier& identifier,
@@ -283,21 +282,113 @@ Common::Input::DriverResult Joycons::SetCameraFormat(const PadIdentifier& identi
283 if (handle == nullptr) { 282 if (handle == nullptr) {
284 return Common::Input::DriverResult::InvalidHandle; 283 return Common::Input::DriverResult::InvalidHandle;
285 } 284 }
286 return static_cast<Common::Input::DriverResult>(handle->SetIrsConfig( 285 return handle->SetIrsConfig(Joycon::IrsMode::ImageTransfer,
287 Joycon::IrsMode::ImageTransfer, static_cast<Joycon::IrsResolution>(camera_format))); 286 static_cast<Joycon::IrsResolution>(camera_format));
288}; 287};
289 288
290Common::Input::NfcState Joycons::SupportsNfc(const PadIdentifier& identifier_) const { 289Common::Input::NfcState Joycons::SupportsNfc(const PadIdentifier& identifier_) const {
291 return Common::Input::NfcState::Success; 290 return Common::Input::NfcState::Success;
292}; 291};
293 292
293Common::Input::NfcState Joycons::StartNfcPolling(const PadIdentifier& identifier) {
294 auto handle = GetHandle(identifier);
295 if (handle == nullptr) {
296 return Common::Input::NfcState::Unknown;
297 }
298 return TranslateDriverResult(handle->StartNfcPolling());
299};
300
301Common::Input::NfcState Joycons::StopNfcPolling(const PadIdentifier& identifier) {
302 auto handle = GetHandle(identifier);
303 if (handle == nullptr) {
304 return Common::Input::NfcState::Unknown;
305 }
306 return TranslateDriverResult(handle->StopNfcPolling());
307};
308
309Common::Input::NfcState Joycons::ReadAmiiboData(const PadIdentifier& identifier,
310 std::vector<u8>& out_data) {
311 auto handle = GetHandle(identifier);
312 if (handle == nullptr) {
313 return Common::Input::NfcState::Unknown;
314 }
315 return TranslateDriverResult(handle->ReadAmiiboData(out_data));
316}
317
294Common::Input::NfcState Joycons::WriteNfcData(const PadIdentifier& identifier, 318Common::Input::NfcState Joycons::WriteNfcData(const PadIdentifier& identifier,
295 const std::vector<u8>& data) { 319 const std::vector<u8>& data) {
296 auto handle = GetHandle(identifier); 320 auto handle = GetHandle(identifier);
297 if (handle->WriteNfcData(data) != Joycon::DriverResult::Success) { 321 if (handle == nullptr) {
298 return Common::Input::NfcState::WriteFailed; 322 return Common::Input::NfcState::Unknown;
299 } 323 }
300 return Common::Input::NfcState::Success; 324 return TranslateDriverResult(handle->WriteNfcData(data));
325};
326
327Common::Input::NfcState Joycons::ReadMifareData(const PadIdentifier& identifier,
328 const Common::Input::MifareRequest& request,
329 Common::Input::MifareRequest& data) {
330 auto handle = GetHandle(identifier);
331 if (handle == nullptr) {
332 return Common::Input::NfcState::Unknown;
333 }
334
335 const auto command = static_cast<Joycon::MifareCmd>(request.data[0].command);
336 std::vector<Joycon::MifareReadChunk> read_request{};
337 for (const auto& request_data : request.data) {
338 if (request_data.command == 0) {
339 continue;
340 }
341 Joycon::MifareReadChunk chunk = {
342 .command = command,
343 .sector_key = {},
344 .sector = request_data.sector,
345 };
346 memcpy(chunk.sector_key.data(), request_data.key.data(),
347 sizeof(Joycon::MifareReadChunk::sector_key));
348 read_request.emplace_back(chunk);
349 }
350
351 std::vector<Joycon::MifareReadData> read_data(read_request.size());
352 const auto result = handle->ReadMifareData(read_request, read_data);
353 if (result == Common::Input::DriverResult::Success) {
354 for (std::size_t i = 0; i < read_request.size(); i++) {
355 data.data[i] = {
356 .command = static_cast<u8>(command),
357 .sector = read_data[i].sector,
358 .key = {},
359 .data = read_data[i].data,
360 };
361 }
362 }
363 return TranslateDriverResult(result);
364};
365
366Common::Input::NfcState Joycons::WriteMifareData(const PadIdentifier& identifier,
367 const Common::Input::MifareRequest& request) {
368 auto handle = GetHandle(identifier);
369 if (handle == nullptr) {
370 return Common::Input::NfcState::Unknown;
371 }
372
373 const auto command = static_cast<Joycon::MifareCmd>(request.data[0].command);
374 std::vector<Joycon::MifareWriteChunk> write_request{};
375 for (const auto& request_data : request.data) {
376 if (request_data.command == 0) {
377 continue;
378 }
379 Joycon::MifareWriteChunk chunk = {
380 .command = command,
381 .sector_key = {},
382 .sector = request_data.sector,
383 .data = {},
384 };
385 memcpy(chunk.sector_key.data(), request_data.key.data(),
386 sizeof(Joycon::MifareReadChunk::sector_key));
387 memcpy(chunk.data.data(), request_data.data.data(), sizeof(Joycon::MifareWriteChunk::data));
388 write_request.emplace_back(chunk);
389 }
390
391 return TranslateDriverResult(handle->WriteMifareData(write_request));
301}; 392};
302 393
303Common::Input::DriverResult Joycons::SetPollingMode(const PadIdentifier& identifier, 394Common::Input::DriverResult Joycons::SetPollingMode(const PadIdentifier& identifier,
@@ -310,15 +401,15 @@ Common::Input::DriverResult Joycons::SetPollingMode(const PadIdentifier& identif
310 401
311 switch (polling_mode) { 402 switch (polling_mode) {
312 case Common::Input::PollingMode::Active: 403 case Common::Input::PollingMode::Active:
313 return static_cast<Common::Input::DriverResult>(handle->SetActiveMode()); 404 return handle->SetActiveMode();
314 case Common::Input::PollingMode::Passive: 405 case Common::Input::PollingMode::Passive:
315 return static_cast<Common::Input::DriverResult>(handle->SetPassiveMode()); 406 return handle->SetPassiveMode();
316 case Common::Input::PollingMode::IR: 407 case Common::Input::PollingMode::IR:
317 return static_cast<Common::Input::DriverResult>(handle->SetIrMode()); 408 return handle->SetIrMode();
318 case Common::Input::PollingMode::NFC: 409 case Common::Input::PollingMode::NFC:
319 return static_cast<Common::Input::DriverResult>(handle->SetNfcMode()); 410 return handle->SetNfcMode();
320 case Common::Input::PollingMode::Ring: 411 case Common::Input::PollingMode::Ring:
321 return static_cast<Common::Input::DriverResult>(handle->SetRingConMode()); 412 return handle->SetRingConMode();
322 default: 413 default:
323 return Common::Input::DriverResult::NotSupported; 414 return Common::Input::DriverResult::NotSupported;
324 } 415 }
@@ -403,11 +494,20 @@ void Joycons::OnRingConUpdate(f32 ring_data) {
403} 494}
404 495
405void Joycons::OnAmiiboUpdate(std::size_t port, Joycon::ControllerType type, 496void Joycons::OnAmiiboUpdate(std::size_t port, Joycon::ControllerType type,
406 const std::vector<u8>& amiibo_data) { 497 const Joycon::TagInfo& tag_info) {
407 const auto identifier = GetIdentifier(port, type); 498 const auto identifier = GetIdentifier(port, type);
408 const auto nfc_state = amiibo_data.empty() ? Common::Input::NfcState::AmiiboRemoved 499 const auto nfc_state = tag_info.uuid_length == 0 ? Common::Input::NfcState::AmiiboRemoved
409 : Common::Input::NfcState::NewAmiibo; 500 : Common::Input::NfcState::NewAmiibo;
410 SetNfc(identifier, {nfc_state, amiibo_data}); 501
502 const Common::Input::NfcStatus nfc_status{
503 .state = nfc_state,
504 .uuid_length = tag_info.uuid_length,
505 .protocol = tag_info.protocol,
506 .tag_type = tag_info.tag_type,
507 .uuid = tag_info.uuid,
508 };
509
510 SetNfc(identifier, nfc_status);
411} 511}
412 512
413void Joycons::OnCameraUpdate(std::size_t port, const std::vector<u8>& camera_data, 513void Joycons::OnCameraUpdate(std::size_t port, const std::vector<u8>& camera_data,
@@ -726,4 +826,18 @@ std::string Joycons::JoyconName(Joycon::ControllerType type) const {
726 return "Unknown Switch Controller"; 826 return "Unknown Switch Controller";
727 } 827 }
728} 828}
829
830Common::Input::NfcState Joycons::TranslateDriverResult(Common::Input::DriverResult result) const {
831 switch (result) {
832 case Common::Input::DriverResult::Success:
833 return Common::Input::NfcState::Success;
834 case Common::Input::DriverResult::Disabled:
835 return Common::Input::NfcState::WrongDeviceState;
836 case Common::Input::DriverResult::NotSupported:
837 return Common::Input::NfcState::NotSupported;
838 default:
839 return Common::Input::NfcState::Unknown;
840 }
841}
842
729} // namespace InputCommon 843} // namespace InputCommon
diff --git a/src/input_common/drivers/joycon.h b/src/input_common/drivers/joycon.h
index e3f0ad78f..112e970e1 100644
--- a/src/input_common/drivers/joycon.h
+++ b/src/input_common/drivers/joycon.h
@@ -15,8 +15,8 @@ using SerialNumber = std::array<u8, 15>;
15struct Battery; 15struct Battery;
16struct Color; 16struct Color;
17struct MotionData; 17struct MotionData;
18struct TagInfo;
18enum class ControllerType : u8; 19enum class ControllerType : u8;
19enum class DriverResult;
20enum class IrsResolution; 20enum class IrsResolution;
21class JoyconDriver; 21class JoyconDriver;
22} // namespace InputCommon::Joycon 22} // namespace InputCommon::Joycon
@@ -39,9 +39,18 @@ public:
39 Common::Input::DriverResult SetCameraFormat(const PadIdentifier& identifier, 39 Common::Input::DriverResult SetCameraFormat(const PadIdentifier& identifier,
40 Common::Input::CameraFormat camera_format) override; 40 Common::Input::CameraFormat camera_format) override;
41 41
42 Common::Input::NfcState SupportsNfc(const PadIdentifier& identifier_) const override; 42 Common::Input::NfcState SupportsNfc(const PadIdentifier& identifier) const override;
43 Common::Input::NfcState WriteNfcData(const PadIdentifier& identifier_, 43 Common::Input::NfcState StartNfcPolling(const PadIdentifier& identifier) override;
44 Common::Input::NfcState StopNfcPolling(const PadIdentifier& identifier) override;
45 Common::Input::NfcState ReadAmiiboData(const PadIdentifier& identifier,
46 std::vector<u8>& out_data) override;
47 Common::Input::NfcState WriteNfcData(const PadIdentifier& identifier,
44 const std::vector<u8>& data) override; 48 const std::vector<u8>& data) override;
49 Common::Input::NfcState ReadMifareData(const PadIdentifier& identifier,
50 const Common::Input::MifareRequest& request,
51 Common::Input::MifareRequest& out_data) override;
52 Common::Input::NfcState WriteMifareData(const PadIdentifier& identifier,
53 const Common::Input::MifareRequest& request) override;
45 54
46 Common::Input::DriverResult SetPollingMode( 55 Common::Input::DriverResult SetPollingMode(
47 const PadIdentifier& identifier, const Common::Input::PollingMode polling_mode) override; 56 const PadIdentifier& identifier, const Common::Input::PollingMode polling_mode) override;
@@ -82,7 +91,7 @@ private:
82 const Joycon::MotionData& value); 91 const Joycon::MotionData& value);
83 void OnRingConUpdate(f32 ring_data); 92 void OnRingConUpdate(f32 ring_data);
84 void OnAmiiboUpdate(std::size_t port, Joycon::ControllerType type, 93 void OnAmiiboUpdate(std::size_t port, Joycon::ControllerType type,
85 const std::vector<u8>& amiibo_data); 94 const Joycon::TagInfo& amiibo_data);
86 void OnCameraUpdate(std::size_t port, const std::vector<u8>& camera_data, 95 void OnCameraUpdate(std::size_t port, const std::vector<u8>& camera_data,
87 Joycon::IrsResolution format); 96 Joycon::IrsResolution format);
88 97
@@ -102,6 +111,8 @@ private:
102 /// Returns the name of the device in text format 111 /// Returns the name of the device in text format
103 std::string JoyconName(Joycon::ControllerType type) const; 112 std::string JoyconName(Joycon::ControllerType type) const;
104 113
114 Common::Input::NfcState TranslateDriverResult(Common::Input::DriverResult result) const;
115
105 std::jthread scan_thread; 116 std::jthread scan_thread;
106 117
107 // Joycon types are split by type to ease supporting dualjoycon configurations 118 // Joycon types are split by type to ease supporting dualjoycon configurations
diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp
index 0c9f642bb..f07cf8a0e 100644
--- a/src/input_common/drivers/mouse.cpp
+++ b/src/input_common/drivers/mouse.cpp
@@ -76,9 +76,6 @@ void Mouse::UpdateThread(std::stop_token stop_token) {
76 UpdateStickInput(); 76 UpdateStickInput();
77 UpdateMotionInput(); 77 UpdateMotionInput();
78 78
79 if (mouse_panning_timeout++ > 20) {
80 StopPanning();
81 }
82 std::this_thread::sleep_for(std::chrono::milliseconds(update_time)); 79 std::this_thread::sleep_for(std::chrono::milliseconds(update_time));
83 } 80 }
84} 81}
@@ -88,18 +85,45 @@ void Mouse::UpdateStickInput() {
88 return; 85 return;
89 } 86 }
90 87
91 const float sensitivity = 88 const float length = last_mouse_change.Length();
92 Settings::values.mouse_panning_sensitivity.GetValue() * default_stick_sensitivity;
93 89
94 // Slow movement by 4% 90 // Prevent input from exceeding the max range (1.0f) too much,
95 last_mouse_change *= 0.96f; 91 // but allow some room to make it easier to sustain
96 SetAxis(identifier, mouse_axis_x, last_mouse_change.x * sensitivity); 92 if (length > 1.2f) {
97 SetAxis(identifier, mouse_axis_y, -last_mouse_change.y * sensitivity); 93 last_mouse_change /= length;
94 last_mouse_change *= 1.2f;
95 }
96
97 auto mouse_change = last_mouse_change;
98
99 // Bind the mouse change to [0 <= deadzone_counterweight <= 1,1]
100 if (length < 1.0f) {
101 const float deadzone_h_counterweight =
102 Settings::values.mouse_panning_deadzone_x_counterweight.GetValue();
103 const float deadzone_v_counterweight =
104 Settings::values.mouse_panning_deadzone_y_counterweight.GetValue();
105 mouse_change /= length;
106 mouse_change.x *= length + (1 - length) * deadzone_h_counterweight * 0.01f;
107 mouse_change.y *= length + (1 - length) * deadzone_v_counterweight * 0.01f;
108 }
109
110 SetAxis(identifier, mouse_axis_x, mouse_change.x);
111 SetAxis(identifier, mouse_axis_y, -mouse_change.y);
112
113 // Decay input over time
114 const float clamped_length = std::min(1.0f, length);
115 const float decay_strength = Settings::values.mouse_panning_decay_strength.GetValue();
116 const float decay = 1 - clamped_length * clamped_length * decay_strength * 0.01f;
117 const float min_decay = Settings::values.mouse_panning_min_decay.GetValue();
118 const float clamped_decay = std::min(1 - min_decay / 100.0f, decay);
119 last_mouse_change *= clamped_decay;
98} 120}
99 121
100void Mouse::UpdateMotionInput() { 122void Mouse::UpdateMotionInput() {
101 const float sensitivity = 123 // This may need its own sensitivity instead of using the average
102 Settings::values.mouse_panning_sensitivity.GetValue() * default_motion_sensitivity; 124 const float sensitivity = (Settings::values.mouse_panning_x_sensitivity.GetValue() +
125 Settings::values.mouse_panning_y_sensitivity.GetValue()) /
126 2.0f * default_motion_sensitivity;
103 127
104 const float rotation_velocity = std::sqrt(last_motion_change.x * last_motion_change.x + 128 const float rotation_velocity = std::sqrt(last_motion_change.x * last_motion_change.x +
105 last_motion_change.y * last_motion_change.y); 129 last_motion_change.y * last_motion_change.y);
@@ -131,49 +155,28 @@ void Mouse::UpdateMotionInput() {
131 155
132void Mouse::Move(int x, int y, int center_x, int center_y) { 156void Mouse::Move(int x, int y, int center_x, int center_y) {
133 if (Settings::values.mouse_panning) { 157 if (Settings::values.mouse_panning) {
134 mouse_panning_timeout = 0; 158 const auto mouse_change =
135
136 auto mouse_change =
137 (Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y)).Cast<float>(); 159 (Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y)).Cast<float>();
138 last_motion_change += {-mouse_change.y, -mouse_change.x, 0}; 160 const float x_sensitivity =
139 161 Settings::values.mouse_panning_x_sensitivity.GetValue() * default_stick_sensitivity;
140 const auto move_distance = mouse_change.Length(); 162 const float y_sensitivity =
141 if (move_distance == 0) { 163 Settings::values.mouse_panning_y_sensitivity.GetValue() * default_stick_sensitivity;
142 return;
143 }
144 164
145 // Make slow movements at least 3 units on length 165 last_motion_change += {-mouse_change.y, -mouse_change.x, 0};
146 if (move_distance < 3.0f) { 166 last_mouse_change.x += mouse_change.x * x_sensitivity * 0.09f;
147 // Normalize value 167 last_mouse_change.y += mouse_change.y * y_sensitivity * 0.09f;
148 mouse_change /= move_distance;
149 mouse_change *= 3.0f;
150 }
151
152 // Average mouse movements
153 last_mouse_change = (last_mouse_change * 0.91f) + (mouse_change * 0.09f);
154
155 const auto last_move_distance = last_mouse_change.Length();
156
157 // Make fast movements clamp to 8 units on length
158 if (last_move_distance > 8.0f) {
159 // Normalize value
160 last_mouse_change /= last_move_distance;
161 last_mouse_change *= 8.0f;
162 }
163
164 // Ignore average if it's less than 1 unit and use current movement value
165 if (last_move_distance < 1.0f) {
166 last_mouse_change = mouse_change / mouse_change.Length();
167 }
168 168
169 return; 169 return;
170 } 170 }
171 171
172 if (button_pressed) { 172 if (button_pressed) {
173 const auto mouse_move = Common::MakeVec<int>(x, y) - mouse_origin; 173 const auto mouse_move = Common::MakeVec<int>(x, y) - mouse_origin;
174 const float sensitivity = Settings::values.mouse_panning_sensitivity.GetValue() * 0.0012f; 174 const float x_sensitivity = Settings::values.mouse_panning_x_sensitivity.GetValue();
175 SetAxis(identifier, mouse_axis_x, static_cast<float>(mouse_move.x) * sensitivity); 175 const float y_sensitivity = Settings::values.mouse_panning_y_sensitivity.GetValue();
176 SetAxis(identifier, mouse_axis_y, static_cast<float>(-mouse_move.y) * sensitivity); 176 SetAxis(identifier, mouse_axis_x,
177 static_cast<float>(mouse_move.x) * x_sensitivity * 0.0012f);
178 SetAxis(identifier, mouse_axis_y,
179 static_cast<float>(-mouse_move.y) * y_sensitivity * 0.0012f);
177 180
178 last_motion_change = { 181 last_motion_change = {
179 static_cast<float>(-mouse_move.y) / 50.0f, 182 static_cast<float>(-mouse_move.y) / 50.0f,
@@ -241,10 +244,6 @@ void Mouse::ReleaseAllButtons() {
241 button_pressed = false; 244 button_pressed = false;
242} 245}
243 246
244void Mouse::StopPanning() {
245 last_mouse_change = {};
246}
247
248std::vector<Common::ParamPackage> Mouse::GetInputDevices() const { 247std::vector<Common::ParamPackage> Mouse::GetInputDevices() const {
249 std::vector<Common::ParamPackage> devices; 248 std::vector<Common::ParamPackage> devices;
250 devices.emplace_back(Common::ParamPackage{ 249 devices.emplace_back(Common::ParamPackage{
diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h
index b872c7a0f..0e8edcce1 100644
--- a/src/input_common/drivers/mouse.h
+++ b/src/input_common/drivers/mouse.h
@@ -98,7 +98,6 @@ private:
98 void UpdateThread(std::stop_token stop_token); 98 void UpdateThread(std::stop_token stop_token);
99 void UpdateStickInput(); 99 void UpdateStickInput();
100 void UpdateMotionInput(); 100 void UpdateMotionInput();
101 void StopPanning();
102 101
103 Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const; 102 Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const;
104 103
@@ -108,7 +107,6 @@ private:
108 Common::Vec3<float> last_motion_change; 107 Common::Vec3<float> last_motion_change;
109 Common::Vec2<int> wheel_position; 108 Common::Vec2<int> wheel_position;
110 bool button_pressed; 109 bool button_pressed;
111 int mouse_panning_timeout{};
112 std::jthread update_thread; 110 std::jthread update_thread;
113}; 111};
114 112
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index 9a0439bb5..9f26392b1 100644
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -150,6 +150,8 @@ public:
150 if (sdl_controller) { 150 if (sdl_controller) {
151 const auto type = SDL_GameControllerGetType(sdl_controller.get()); 151 const auto type = SDL_GameControllerGetType(sdl_controller.get());
152 return (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) || 152 return (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) ||
153 (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT) ||
154 (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT) ||
153 (type == SDL_CONTROLLER_TYPE_PS5); 155 (type == SDL_CONTROLLER_TYPE_PS5);
154 } 156 }
155 return false; 157 return false;
@@ -228,9 +230,8 @@ public:
228 return false; 230 return false;
229 } 231 }
230 232
231 Common::Input::BatteryLevel GetBatteryLevel() { 233 Common::Input::BatteryLevel GetBatteryLevel(SDL_JoystickPowerLevel battery_level) {
232 const auto level = SDL_JoystickCurrentPowerLevel(sdl_joystick.get()); 234 switch (battery_level) {
233 switch (level) {
234 case SDL_JOYSTICK_POWER_EMPTY: 235 case SDL_JOYSTICK_POWER_EMPTY:
235 return Common::Input::BatteryLevel::Empty; 236 return Common::Input::BatteryLevel::Empty;
236 case SDL_JOYSTICK_POWER_LOW: 237 case SDL_JOYSTICK_POWER_LOW:
@@ -378,7 +379,6 @@ void SDLDriver::InitJoystick(int joystick_index) {
378 if (joystick_map.find(guid) == joystick_map.end()) { 379 if (joystick_map.find(guid) == joystick_map.end()) {
379 auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller); 380 auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller);
380 PreSetController(joystick->GetPadIdentifier()); 381 PreSetController(joystick->GetPadIdentifier());
381 SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel());
382 joystick->EnableMotion(); 382 joystick->EnableMotion();
383 joystick_map[guid].emplace_back(std::move(joystick)); 383 joystick_map[guid].emplace_back(std::move(joystick));
384 return; 384 return;
@@ -398,7 +398,6 @@ void SDLDriver::InitJoystick(int joystick_index) {
398 const int port = static_cast<int>(joystick_guid_list.size()); 398 const int port = static_cast<int>(joystick_guid_list.size());
399 auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_gamecontroller); 399 auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_gamecontroller);
400 PreSetController(joystick->GetPadIdentifier()); 400 PreSetController(joystick->GetPadIdentifier());
401 SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel());
402 joystick->EnableMotion(); 401 joystick->EnableMotion();
403 joystick_guid_list.emplace_back(std::move(joystick)); 402 joystick_guid_list.emplace_back(std::move(joystick));
404} 403}
@@ -438,8 +437,6 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) {
438 if (const auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) { 437 if (const auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) {
439 const PadIdentifier identifier = joystick->GetPadIdentifier(); 438 const PadIdentifier identifier = joystick->GetPadIdentifier();
440 SetButton(identifier, event.jbutton.button, true); 439 SetButton(identifier, event.jbutton.button, true);
441 // Battery doesn't trigger an event so just update every button press
442 SetBattery(identifier, joystick->GetBatteryLevel());
443 } 440 }
444 break; 441 break;
445 } 442 }
@@ -466,6 +463,13 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) {
466 } 463 }
467 break; 464 break;
468 } 465 }
466 case SDL_JOYBATTERYUPDATED: {
467 if (auto joystick = GetSDLJoystickBySDLID(event.jbattery.which)) {
468 const PadIdentifier identifier = joystick->GetPadIdentifier();
469 SetBattery(identifier, joystick->GetBatteryLevel(event.jbattery.level));
470 }
471 break;
472 }
469 case SDL_JOYDEVICEREMOVED: 473 case SDL_JOYDEVICEREMOVED:
470 LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which); 474 LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which);
471 CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which)); 475 CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which));
@@ -483,6 +487,10 @@ void SDLDriver::CloseJoysticks() {
483} 487}
484 488
485SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_engine_)) { 489SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
490 // Set our application name. Currently passed to DBus by SDL and visible to the user through
491 // their desktop environment.
492 SDL_SetHint(SDL_HINT_APP_NAME, "yuzu");
493
486 if (!Settings::values.enable_raw_input) { 494 if (!Settings::values.enable_raw_input) {
487 // Disable raw input. When enabled this setting causes SDL to die when a web applet opens 495 // Disable raw input. When enabled this setting causes SDL to die when a web applet opens
488 SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, "0"); 496 SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, "0");
@@ -501,6 +509,9 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en
501 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "0"); 509 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "0");
502 } else { 510 } else {
503 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1"); 511 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1");
512 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOYCON_HOME_LED, "0");
513 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_COMBINE_JOY_CONS, "0");
514 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS, "1");
504 } 515 }
505 516
506 // Disable hidapi drivers for pro controllers when the custom joycon driver is enabled 517 // Disable hidapi drivers for pro controllers when the custom joycon driver is enabled
@@ -508,8 +519,11 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en
508 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "0"); 519 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "0");
509 } else { 520 } else {
510 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "1"); 521 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "1");
522 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED, "0");
511 } 523 }
512 524
525 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED, "1");
526
513 // Disable hidapi driver for xbox. Already default on Windows, this causes conflict with native 527 // Disable hidapi driver for xbox. Already default on Windows, this causes conflict with native
514 // driver on Linux. 528 // driver on Linux.
515 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_XBOX, "0"); 529 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_XBOX, "0");
@@ -789,7 +803,9 @@ ButtonMapping SDLDriver::GetButtonMappingForDevice(const Common::ParamPackage& p
789 // This list also excludes Screenshot since there's not really a mapping for that 803 // This list also excludes Screenshot since there's not really a mapping for that
790 ButtonBindings switch_to_sdl_button; 804 ButtonBindings switch_to_sdl_button;
791 805
792 if (SDL_GameControllerGetType(controller) == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) { 806 if (SDL_GameControllerGetType(controller) == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO ||
807 SDL_GameControllerGetType(controller) == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT ||
808 SDL_GameControllerGetType(controller) == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT) {
793 switch_to_sdl_button = GetNintendoButtonBinding(joystick); 809 switch_to_sdl_button = GetNintendoButtonBinding(joystick);
794 } else { 810 } else {
795 switch_to_sdl_button = GetDefaultButtonBinding(); 811 switch_to_sdl_button = GetDefaultButtonBinding();
diff --git a/src/input_common/drivers/virtual_amiibo.cpp b/src/input_common/drivers/virtual_amiibo.cpp
index 6435b8af8..180eb53ef 100644
--- a/src/input_common/drivers/virtual_amiibo.cpp
+++ b/src/input_common/drivers/virtual_amiibo.cpp
@@ -29,14 +29,13 @@ Common::Input::DriverResult VirtualAmiibo::SetPollingMode(
29 29
30 switch (polling_mode) { 30 switch (polling_mode) {
31 case Common::Input::PollingMode::NFC: 31 case Common::Input::PollingMode::NFC:
32 if (state == State::Initialized) { 32 state = State::Initialized;
33 state = State::WaitingForAmiibo;
34 }
35 return Common::Input::DriverResult::Success; 33 return Common::Input::DriverResult::Success;
36 default: 34 default:
37 if (state == State::AmiiboIsOpen) { 35 if (state == State::TagNearby) {
38 CloseAmiibo(); 36 CloseAmiibo();
39 } 37 }
38 state = State::Disabled;
40 return Common::Input::DriverResult::NotSupported; 39 return Common::Input::DriverResult::NotSupported;
41 } 40 }
42} 41}
@@ -45,6 +44,39 @@ Common::Input::NfcState VirtualAmiibo::SupportsNfc(
45 [[maybe_unused]] const PadIdentifier& identifier_) const { 44 [[maybe_unused]] const PadIdentifier& identifier_) const {
46 return Common::Input::NfcState::Success; 45 return Common::Input::NfcState::Success;
47} 46}
47Common::Input::NfcState VirtualAmiibo::StartNfcPolling(const PadIdentifier& identifier_) {
48 if (state != State::Initialized) {
49 return Common::Input::NfcState::WrongDeviceState;
50 }
51 state = State::WaitingForAmiibo;
52 return Common::Input::NfcState::Success;
53}
54
55Common::Input::NfcState VirtualAmiibo::StopNfcPolling(const PadIdentifier& identifier_) {
56 if (state == State::Disabled) {
57 return Common::Input::NfcState::WrongDeviceState;
58 }
59 if (state == State::TagNearby) {
60 CloseAmiibo();
61 }
62 state = State::Initialized;
63 return Common::Input::NfcState::Success;
64}
65
66Common::Input::NfcState VirtualAmiibo::ReadAmiiboData(const PadIdentifier& identifier_,
67 std::vector<u8>& out_data) {
68 if (state != State::TagNearby) {
69 return Common::Input::NfcState::WrongDeviceState;
70 }
71
72 if (status.tag_type != 1U << 1) {
73 return Common::Input::NfcState::InvalidTagType;
74 }
75
76 out_data.resize(nfc_data.size());
77 memcpy(out_data.data(), nfc_data.data(), nfc_data.size());
78 return Common::Input::NfcState::Success;
79}
48 80
49Common::Input::NfcState VirtualAmiibo::WriteNfcData( 81Common::Input::NfcState VirtualAmiibo::WriteNfcData(
50 [[maybe_unused]] const PadIdentifier& identifier_, const std::vector<u8>& data) { 82 [[maybe_unused]] const PadIdentifier& identifier_, const std::vector<u8>& data) {
@@ -66,6 +98,69 @@ Common::Input::NfcState VirtualAmiibo::WriteNfcData(
66 return Common::Input::NfcState::Success; 98 return Common::Input::NfcState::Success;
67} 99}
68 100
101Common::Input::NfcState VirtualAmiibo::ReadMifareData(const PadIdentifier& identifier_,
102 const Common::Input::MifareRequest& request,
103 Common::Input::MifareRequest& out_data) {
104 if (state != State::TagNearby) {
105 return Common::Input::NfcState::WrongDeviceState;
106 }
107
108 if (status.tag_type != 1U << 6) {
109 return Common::Input::NfcState::InvalidTagType;
110 }
111
112 for (std::size_t i = 0; i < request.data.size(); i++) {
113 if (request.data[i].command == 0) {
114 continue;
115 }
116 out_data.data[i].command = request.data[i].command;
117 out_data.data[i].sector = request.data[i].sector;
118
119 const std::size_t sector_index =
120 request.data[i].sector * sizeof(Common::Input::MifareData::data);
121
122 if (nfc_data.size() < sector_index + sizeof(Common::Input::MifareData::data)) {
123 return Common::Input::NfcState::WriteFailed;
124 }
125
126 // Ignore the sector key as we don't support it
127 memcpy(out_data.data[i].data.data(), nfc_data.data() + sector_index,
128 sizeof(Common::Input::MifareData::data));
129 }
130
131 return Common::Input::NfcState::Success;
132}
133
134Common::Input::NfcState VirtualAmiibo::WriteMifareData(
135 const PadIdentifier& identifier_, const Common::Input::MifareRequest& request) {
136 if (state != State::TagNearby) {
137 return Common::Input::NfcState::WrongDeviceState;
138 }
139
140 if (status.tag_type != 1U << 6) {
141 return Common::Input::NfcState::InvalidTagType;
142 }
143
144 for (std::size_t i = 0; i < request.data.size(); i++) {
145 if (request.data[i].command == 0) {
146 continue;
147 }
148
149 const std::size_t sector_index =
150 request.data[i].sector * sizeof(Common::Input::MifareData::data);
151
152 if (nfc_data.size() < sector_index + sizeof(Common::Input::MifareData::data)) {
153 return Common::Input::NfcState::WriteFailed;
154 }
155
156 // Ignore the sector key as we don't support it
157 memcpy(nfc_data.data() + sector_index, request.data[i].data.data(),
158 sizeof(Common::Input::MifareData::data));
159 }
160
161 return Common::Input::NfcState::Success;
162}
163
69VirtualAmiibo::State VirtualAmiibo::GetCurrentState() const { 164VirtualAmiibo::State VirtualAmiibo::GetCurrentState() const {
70 return state; 165 return state;
71} 166}
@@ -112,23 +207,31 @@ VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(std::span<u8> data) {
112 case AmiiboSizeWithoutPassword: 207 case AmiiboSizeWithoutPassword:
113 case AmiiboSizeWithSignature: 208 case AmiiboSizeWithSignature:
114 nfc_data.resize(AmiiboSize); 209 nfc_data.resize(AmiiboSize);
210 status.tag_type = 1U << 1;
211 status.uuid_length = 7;
115 break; 212 break;
116 case MifareSize: 213 case MifareSize:
117 nfc_data.resize(MifareSize); 214 nfc_data.resize(MifareSize);
215 status.tag_type = 1U << 6;
216 status.uuid_length = 4;
118 break; 217 break;
119 default: 218 default:
120 return Info::NotAnAmiibo; 219 return Info::NotAnAmiibo;
121 } 220 }
122 221
123 state = State::AmiiboIsOpen; 222 status.uuid = {};
223 status.protocol = 1;
224 state = State::TagNearby;
225 status.state = Common::Input::NfcState::NewAmiibo,
124 memcpy(nfc_data.data(), data.data(), data.size_bytes()); 226 memcpy(nfc_data.data(), data.data(), data.size_bytes());
125 SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, nfc_data}); 227 memcpy(status.uuid.data(), nfc_data.data(), status.uuid_length);
228 SetNfc(identifier, status);
126 return Info::Success; 229 return Info::Success;
127} 230}
128 231
129VirtualAmiibo::Info VirtualAmiibo::ReloadAmiibo() { 232VirtualAmiibo::Info VirtualAmiibo::ReloadAmiibo() {
130 if (state == State::AmiiboIsOpen) { 233 if (state == State::TagNearby) {
131 SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, nfc_data}); 234 SetNfc(identifier, status);
132 return Info::Success; 235 return Info::Success;
133 } 236 }
134 237
@@ -136,9 +239,14 @@ VirtualAmiibo::Info VirtualAmiibo::ReloadAmiibo() {
136} 239}
137 240
138VirtualAmiibo::Info VirtualAmiibo::CloseAmiibo() { 241VirtualAmiibo::Info VirtualAmiibo::CloseAmiibo() {
139 state = polling_mode == Common::Input::PollingMode::NFC ? State::WaitingForAmiibo 242 if (state != State::TagNearby) {
140 : State::Initialized; 243 return Info::Success;
141 SetNfc(identifier, {Common::Input::NfcState::AmiiboRemoved, {}}); 244 }
245
246 state = State::WaitingForAmiibo;
247 status.state = Common::Input::NfcState::AmiiboRemoved;
248 SetNfc(identifier, status);
249 status.tag_type = 0;
142 return Info::Success; 250 return Info::Success;
143} 251}
144 252
diff --git a/src/input_common/drivers/virtual_amiibo.h b/src/input_common/drivers/virtual_amiibo.h
index 09ca09e68..490f38e05 100644
--- a/src/input_common/drivers/virtual_amiibo.h
+++ b/src/input_common/drivers/virtual_amiibo.h
@@ -20,9 +20,10 @@ namespace InputCommon {
20class VirtualAmiibo final : public InputEngine { 20class VirtualAmiibo final : public InputEngine {
21public: 21public:
22 enum class State { 22 enum class State {
23 Disabled,
23 Initialized, 24 Initialized,
24 WaitingForAmiibo, 25 WaitingForAmiibo,
25 AmiiboIsOpen, 26 TagNearby,
26 }; 27 };
27 28
28 enum class Info { 29 enum class Info {
@@ -41,9 +42,17 @@ public:
41 const PadIdentifier& identifier_, const Common::Input::PollingMode polling_mode_) override; 42 const PadIdentifier& identifier_, const Common::Input::PollingMode polling_mode_) override;
42 43
43 Common::Input::NfcState SupportsNfc(const PadIdentifier& identifier_) const override; 44 Common::Input::NfcState SupportsNfc(const PadIdentifier& identifier_) const override;
44 45 Common::Input::NfcState StartNfcPolling(const PadIdentifier& identifier_) override;
46 Common::Input::NfcState StopNfcPolling(const PadIdentifier& identifier_) override;
47 Common::Input::NfcState ReadAmiiboData(const PadIdentifier& identifier_,
48 std::vector<u8>& out_data) override;
45 Common::Input::NfcState WriteNfcData(const PadIdentifier& identifier_, 49 Common::Input::NfcState WriteNfcData(const PadIdentifier& identifier_,
46 const std::vector<u8>& data) override; 50 const std::vector<u8>& data) override;
51 Common::Input::NfcState ReadMifareData(const PadIdentifier& identifier_,
52 const Common::Input::MifareRequest& data,
53 Common::Input::MifareRequest& out_data) override;
54 Common::Input::NfcState WriteMifareData(const PadIdentifier& identifier_,
55 const Common::Input::MifareRequest& data) override;
47 56
48 State GetCurrentState() const; 57 State GetCurrentState() const;
49 58
@@ -61,8 +70,9 @@ private:
61 static constexpr std::size_t MifareSize = 0x400; 70 static constexpr std::size_t MifareSize = 0x400;
62 71
63 std::string file_path{}; 72 std::string file_path{};
64 State state{State::Initialized}; 73 State state{State::Disabled};
65 std::vector<u8> nfc_data; 74 std::vector<u8> nfc_data;
75 Common::Input::NfcStatus status;
66 Common::Input::PollingMode polling_mode{Common::Input::PollingMode::Passive}; 76 Common::Input::PollingMode polling_mode{Common::Input::PollingMode::Passive};
67}; 77};
68} // namespace InputCommon 78} // namespace InputCommon