summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Ameer2020-06-21 18:43:01 -0400
committerGravatar Ameer2020-06-21 21:17:07 -0400
commit121af3646dad0f80453d2ffffa688dd4435d3acc (patch)
tree020971e22b4423f63a0a04da7fa4087bf85e2bb9 /src
parentClang Formatting (diff)
downloadyuzu-121af3646dad0f80453d2ffffa688dd4435d3acc.tar.gz
yuzu-121af3646dad0f80453d2ffffa688dd4435d3acc.tar.xz
yuzu-121af3646dad0f80453d2ffffa688dd4435d3acc.zip
Singleton GC Adapter class, remove globals, fix naming convention
Fix clang formatting Manual fix for configure_input_player formatting Add missing lib usb cmake command
Diffstat (limited to 'src')
-rw-r--r--src/input_common/gcadapter/gc_adapter.cpp176
-rw-r--r--src/input_common/gcadapter/gc_adapter.h145
-rw-r--r--src/input_common/gcadapter/gc_poller.cpp125
-rw-r--r--src/input_common/gcadapter/gc_poller.h3
-rw-r--r--src/input_common/main.cpp2
-rw-r--r--src/input_common/main.h4
-rw-r--r--src/input_common/udp/client.cpp6
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp50
8 files changed, 283 insertions, 228 deletions
diff --git a/src/input_common/gcadapter/gc_adapter.cpp b/src/input_common/gcadapter/gc_adapter.cpp
index dc04116ce..0696a96c7 100644
--- a/src/input_common/gcadapter/gc_adapter.cpp
+++ b/src/input_common/gcadapter/gc_adapter.cpp
@@ -3,45 +3,41 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6#include "common/threadsafe_queue.h"
7#include "input_common/gcadapter/gc_adapter.h" 6#include "input_common/gcadapter/gc_adapter.h"
8 7
9Common::SPSCQueue<GCPadStatus> pad_queue[4];
10struct GCState state[4];
11
12namespace GCAdapter { 8namespace GCAdapter {
9Adapter* Adapter::adapter_instance{nullptr};
13 10
14static libusb_device_handle* usb_adapter_handle = nullptr; 11Adapter::Adapter() {
15static u8 adapter_controllers_status[4] = { 12 if (usb_adapter_handle != nullptr) {
16 ControllerTypes::CONTROLLER_NONE, ControllerTypes::CONTROLLER_NONE, 13 return;
17 ControllerTypes::CONTROLLER_NONE, ControllerTypes::CONTROLLER_NONE}; 14 }
18 15 LOG_INFO(Input, "GC Adapter Initialization started");
19static std::mutex s_mutex;
20
21static std::thread adapter_input_thread;
22static bool adapter_thread_running;
23
24static std::mutex initialization_mutex;
25static std::thread detect_thread;
26static bool detect_thread_running = false;
27 16
28static libusb_context* libusb_ctx; 17 current_status = NO_ADAPTER_DETECTED;
18 libusb_init(&libusb_ctx);
29 19
30static u8 input_endpoint = 0; 20 StartScanThread();
21}
31 22
32static bool configuring = false; 23Adapter* Adapter::GetInstance() {
24 if (!adapter_instance) {
25 adapter_instance = new Adapter;
26 }
27 return adapter_instance;
28}
33 29
34GCPadStatus CheckStatus(int port, u8 adapter_payload[37]) { 30GCPadStatus Adapter::CheckStatus(int port, u8 adapter_payload[37]) {
35 GCPadStatus pad = {}; 31 GCPadStatus pad = {};
36 bool get_origin = false; 32 bool get_origin = false;
37 33
38 u8 type = adapter_payload[1 + (9 * port)] >> 4; 34 ControllerTypes type = ControllerTypes(adapter_payload[1 + (9 * port)] >> 4);
39 if (type) 35 if (type != ControllerTypes::None)
40 get_origin = true; 36 get_origin = true;
41 37
42 adapter_controllers_status[port] = type; 38 adapter_controllers_status[port] = type;
43 39
44 if (adapter_controllers_status[port] != ControllerTypes::CONTROLLER_NONE) { 40 if (adapter_controllers_status[port] != ControllerTypes::None) {
45 u8 b1 = adapter_payload[1 + (9 * port) + 1]; 41 u8 b1 = adapter_payload[1 + (9 * port) + 1];
46 u8 b2 = adapter_payload[1 + (9 * port) + 2]; 42 u8 b2 = adapter_payload[1 + (9 * port) + 2];
47 43
@@ -88,18 +84,17 @@ GCPadStatus CheckStatus(int port, u8 adapter_payload[37]) {
88 pad.button |= PAD_GET_ORIGIN; 84 pad.button |= PAD_GET_ORIGIN;
89 } 85 }
90 86
91 pad.stickX = adapter_payload[1 + (9 * port) + 3]; 87 pad.stick_x = adapter_payload[1 + (9 * port) + 3];
92 pad.stickY = adapter_payload[1 + (9 * port) + 4]; 88 pad.stick_y = adapter_payload[1 + (9 * port) + 4];
93 pad.substickX = adapter_payload[1 + (9 * port) + 5]; 89 pad.substick_x = adapter_payload[1 + (9 * port) + 5];
94 pad.substickY = adapter_payload[1 + (9 * port) + 6]; 90 pad.substick_y = adapter_payload[1 + (9 * port) + 6];
95 pad.triggerLeft = adapter_payload[1 + (9 * port) + 7]; 91 pad.trigger_left = adapter_payload[1 + (9 * port) + 7];
96 pad.triggerRight = adapter_payload[1 + (9 * port) + 8]; 92 pad.trigger_right = adapter_payload[1 + (9 * port) + 8];
97 } 93 }
98 return pad; 94 return pad;
99} 95}
100 96
101void PadToState(GCPadStatus pad, GCState& state) { 97void Adapter::PadToState(GCPadStatus pad, GCState& state) {
102 // std::lock_guard lock{s_mutex};
103 state.buttons.insert_or_assign(PAD_BUTTON_A, pad.button & PAD_BUTTON_A); 98 state.buttons.insert_or_assign(PAD_BUTTON_A, pad.button & PAD_BUTTON_A);
104 state.buttons.insert_or_assign(PAD_BUTTON_B, pad.button & PAD_BUTTON_B); 99 state.buttons.insert_or_assign(PAD_BUTTON_B, pad.button & PAD_BUTTON_B);
105 state.buttons.insert_or_assign(PAD_BUTTON_X, pad.button & PAD_BUTTON_X); 100 state.buttons.insert_or_assign(PAD_BUTTON_X, pad.button & PAD_BUTTON_X);
@@ -112,15 +107,15 @@ void PadToState(GCPadStatus pad, GCState& state) {
112 state.buttons.insert_or_assign(PAD_TRIGGER_Z, pad.button & PAD_TRIGGER_Z); 107 state.buttons.insert_or_assign(PAD_TRIGGER_Z, pad.button & PAD_TRIGGER_Z);
113 state.buttons.insert_or_assign(PAD_TRIGGER_L, pad.button & PAD_TRIGGER_L); 108 state.buttons.insert_or_assign(PAD_TRIGGER_L, pad.button & PAD_TRIGGER_L);
114 state.buttons.insert_or_assign(PAD_TRIGGER_R, pad.button & PAD_TRIGGER_R); 109 state.buttons.insert_or_assign(PAD_TRIGGER_R, pad.button & PAD_TRIGGER_R);
115 state.axes.insert_or_assign(STICK_X, pad.stickX); 110 state.axes.insert_or_assign(static_cast<u8>(PadAxes::StickX), pad.stick_x);
116 state.axes.insert_or_assign(STICK_Y, pad.stickY); 111 state.axes.insert_or_assign(static_cast<u8>(PadAxes::StickY), pad.stick_y);
117 state.axes.insert_or_assign(SUBSTICK_X, pad.substickX); 112 state.axes.insert_or_assign(static_cast<u8>(PadAxes::SubstickX), pad.substick_x);
118 state.axes.insert_or_assign(SUBSTICK_Y, pad.substickY); 113 state.axes.insert_or_assign(static_cast<u8>(PadAxes::SubstickY), pad.substick_y);
119 state.axes.insert_or_assign(TRIGGER_LEFT, pad.triggerLeft); 114 state.axes.insert_or_assign(static_cast<u8>(PadAxes::TriggerLeft), pad.trigger_left);
120 state.axes.insert_or_assign(TRIGGER_RIGHT, pad.triggerRight); 115 state.axes.insert_or_assign(static_cast<u8>(PadAxes::TriggerRight), pad.trigger_right);
121} 116}
122 117
123static void Read() { 118void Adapter::Read() {
124 LOG_INFO(Input, "GC Adapter Read() thread started"); 119 LOG_INFO(Input, "GC Adapter Read() thread started");
125 120
126 int payload_size_in; 121 int payload_size_in;
@@ -145,8 +140,9 @@ static void Read() {
145 LOG_ERROR(Input, "error reading payload (size: %d, type: %02x)", payload_size, 140 LOG_ERROR(Input, "error reading payload (size: %d, type: %02x)", payload_size,
146 controller_payload_copy[0]); 141 controller_payload_copy[0]);
147 } else { 142 } else {
148 for (int i = 0; i < 4; i++) 143 for (int port = 0; port < 4; port++) {
149 pad[i] = CheckStatus(i, controller_payload_copy); 144 pad[port] = CheckStatus(port, controller_payload_copy);
145 }
150 } 146 }
151 for (int port = 0; port < 4; port++) { 147 for (int port = 0; port < 4; port++) {
152 if (DeviceConnected(port) && configuring) { 148 if (DeviceConnected(port) && configuring) {
@@ -155,28 +151,36 @@ static void Read() {
155 } 151 }
156 152
157 // Accounting for a threshold here because of some controller variance 153 // Accounting for a threshold here because of some controller variance
158 if (pad[port].stickX > pad[port].MAIN_STICK_CENTER_X + pad[port].THRESHOLD || 154 if (pad[port].stick_x >
159 pad[port].stickX < pad[port].MAIN_STICK_CENTER_X - pad[port].THRESHOLD) { 155 pad_constants.MAIN_STICK_CENTER_X + pad_constants.THRESHOLD ||
160 pad[port].axis_which = STICK_X; 156 pad[port].stick_x <
161 pad[port].axis_value = pad[port].stickX; 157 pad_constants.MAIN_STICK_CENTER_X - pad_constants.THRESHOLD) {
158 pad[port].axis = GCAdapter::PadAxes::StickX;
159 pad[port].axis_value = pad[port].stick_x;
162 pad_queue[port].Push(pad[port]); 160 pad_queue[port].Push(pad[port]);
163 } 161 }
164 if (pad[port].stickY > pad[port].MAIN_STICK_CENTER_Y + pad[port].THRESHOLD || 162 if (pad[port].stick_y >
165 pad[port].stickY < pad[port].MAIN_STICK_CENTER_Y - pad[port].THRESHOLD) { 163 pad_constants.MAIN_STICK_CENTER_Y + pad_constants.THRESHOLD ||
166 pad[port].axis_which = STICK_Y; 164 pad[port].stick_y <
167 pad[port].axis_value = pad[port].stickY; 165 pad_constants.MAIN_STICK_CENTER_Y - pad_constants.THRESHOLD) {
166 pad[port].axis = GCAdapter::PadAxes::StickY;
167 pad[port].axis_value = pad[port].stick_y;
168 pad_queue[port].Push(pad[port]); 168 pad_queue[port].Push(pad[port]);
169 } 169 }
170 if (pad[port].substickX > pad[port].C_STICK_CENTER_X + pad[port].THRESHOLD || 170 if (pad[port].substick_x >
171 pad[port].substickX < pad[port].C_STICK_CENTER_X - pad[port].THRESHOLD) { 171 pad_constants.C_STICK_CENTER_X + pad_constants.THRESHOLD ||
172 pad[port].axis_which = SUBSTICK_X; 172 pad[port].substick_x <
173 pad[port].axis_value = pad[port].substickX; 173 pad_constants.C_STICK_CENTER_X - pad_constants.THRESHOLD) {
174 pad[port].axis = GCAdapter::PadAxes::SubstickX;
175 pad[port].axis_value = pad[port].substick_x;
174 pad_queue[port].Push(pad[port]); 176 pad_queue[port].Push(pad[port]);
175 } 177 }
176 if (pad[port].substickY > pad[port].C_STICK_CENTER_Y + pad[port].THRESHOLD || 178 if (pad[port].substick_y >
177 pad[port].substickY < pad[port].C_STICK_CENTER_Y - pad[port].THRESHOLD) { 179 pad_constants.C_STICK_CENTER_Y + pad_constants.THRESHOLD ||
178 pad[port].axis_which = SUBSTICK_Y; 180 pad[port].substick_y <
179 pad[port].axis_value = pad[port].substickY; 181 pad_constants.C_STICK_CENTER_Y - pad_constants.THRESHOLD) {
182 pad[port].axis = GCAdapter::PadAxes::SubstickY;
183 pad[port].axis_value = pad[port].substick_y;
180 pad_queue[port].Push(pad[port]); 184 pad_queue[port].Push(pad[port]);
181 } 185 }
182 } 186 }
@@ -186,7 +190,7 @@ static void Read() {
186 } 190 }
187} 191}
188 192
189static void ScanThreadFunc() { 193void Adapter::ScanThreadFunc() {
190 LOG_INFO(Input, "GC Adapter scanning thread started"); 194 LOG_INFO(Input, "GC Adapter scanning thread started");
191 195
192 while (detect_thread_running) { 196 while (detect_thread_running) {
@@ -198,20 +202,7 @@ static void ScanThreadFunc() {
198 } 202 }
199} 203}
200 204
201void Init() { 205void Adapter::StartScanThread() {
202
203 if (usb_adapter_handle != nullptr) {
204 return;
205 }
206 LOG_INFO(Input, "GC Adapter Initialization started");
207
208 current_status = NO_ADAPTER_DETECTED;
209 libusb_init(&libusb_ctx);
210
211 StartScanThread();
212}
213
214void StartScanThread() {
215 if (detect_thread_running) { 206 if (detect_thread_running) {
216 return; 207 return;
217 } 208 }
@@ -220,21 +211,21 @@ void StartScanThread() {
220 } 211 }
221 212
222 detect_thread_running = true; 213 detect_thread_running = true;
223 detect_thread = std::thread(ScanThreadFunc); 214 detect_thread = std::thread([=] { ScanThreadFunc(); });
224} 215}
225 216
226void StopScanThread() { 217void Adapter::StopScanThread() {
227 detect_thread.join(); 218 detect_thread.join();
228} 219}
229 220
230static void Setup() { 221void Adapter::Setup() {
231 // Reset the error status in case the adapter gets unplugged 222 // Reset the error status in case the adapter gets unplugged
232 if (current_status < 0) { 223 if (current_status < 0) {
233 current_status = NO_ADAPTER_DETECTED; 224 current_status = NO_ADAPTER_DETECTED;
234 } 225 }
235 226
236 for (int i = 0; i < 4; i++) { 227 for (int i = 0; i < 4; i++) {
237 adapter_controllers_status[i] = ControllerTypes::CONTROLLER_NONE; 228 adapter_controllers_status[i] = ControllerTypes::None;
238 } 229 }
239 230
240 libusb_device** devs; // pointer to list of connected usb devices 231 libusb_device** devs; // pointer to list of connected usb devices
@@ -250,7 +241,7 @@ static void Setup() {
250 } 241 }
251} 242}
252 243
253static bool CheckDeviceAccess(libusb_device* device) { 244bool Adapter::CheckDeviceAccess(libusb_device* device) {
254 libusb_device_descriptor desc; 245 libusb_device_descriptor desc;
255 int ret = libusb_get_device_descriptor(device, &desc); 246 int ret = libusb_get_device_descriptor(device, &desc);
256 if (ret) { 247 if (ret) {
@@ -300,7 +291,7 @@ static bool CheckDeviceAccess(libusb_device* device) {
300 return true; 291 return true;
301} 292}
302 293
303static void GetGCEndpoint(libusb_device* device) { 294void Adapter::GetGCEndpoint(libusb_device* device) {
304 libusb_config_descriptor* config = nullptr; 295 libusb_config_descriptor* config = nullptr;
305 libusb_get_config_descriptor(device, 0, &config); 296 libusb_get_config_descriptor(device, 0, &config);
306 for (u8 ic = 0; ic < config->bNumInterfaces; ic++) { 297 for (u8 ic = 0; ic < config->bNumInterfaces; ic++) {
@@ -318,18 +309,17 @@ static void GetGCEndpoint(libusb_device* device) {
318 309
319 adapter_thread_running = true; 310 adapter_thread_running = true;
320 current_status = ADAPTER_DETECTED; 311 current_status = ADAPTER_DETECTED;
321 312 adapter_input_thread = std::thread([=] { Read(); }); // Read input
322 adapter_input_thread = std::thread(Read); // Read input
323} 313}
324 314
325void Shutdown() { 315Adapter::~Adapter() {
326 StopScanThread(); 316 StopScanThread();
327 Reset(); 317 Reset();
328 318
329 current_status = NO_ADAPTER_DETECTED; 319 current_status = NO_ADAPTER_DETECTED;
330} 320}
331 321
332static void Reset() { 322void Adapter::Reset() {
333 std::unique_lock<std::mutex> lock(initialization_mutex, std::defer_lock); 323 std::unique_lock<std::mutex> lock(initialization_mutex, std::defer_lock);
334 if (!lock.try_lock()) { 324 if (!lock.try_lock()) {
335 return; 325 return;
@@ -343,7 +333,7 @@ static void Reset() {
343 } 333 }
344 334
345 for (int i = 0; i < 4; i++) { 335 for (int i = 0; i < 4; i++) {
346 adapter_controllers_status[i] = ControllerTypes::CONTROLLER_NONE; 336 adapter_controllers_status[i] = ControllerTypes::None;
347 } 337 }
348 338
349 current_status = NO_ADAPTER_DETECTED; 339 current_status = NO_ADAPTER_DETECTED;
@@ -355,20 +345,28 @@ static void Reset() {
355 } 345 }
356} 346}
357 347
358bool DeviceConnected(int port) { 348bool Adapter::DeviceConnected(int port) {
359 return adapter_controllers_status[port] != ControllerTypes::CONTROLLER_NONE; 349 return adapter_controllers_status[port] != ControllerTypes::None;
360} 350}
361 351
362void ResetDeviceType(int port) { 352void Adapter::ResetDeviceType(int port) {
363 adapter_controllers_status[port] = ControllerTypes::CONTROLLER_NONE; 353 adapter_controllers_status[port] = ControllerTypes::None;
364} 354}
365 355
366void BeginConfiguration() { 356void Adapter::BeginConfiguration() {
367 configuring = true; 357 configuring = true;
368} 358}
369 359
370void EndConfiguration() { 360void Adapter::EndConfiguration() {
371 configuring = false; 361 configuring = false;
372} 362}
373 363
364std::array<Common::SPSCQueue<GCPadStatus>, 4>& Adapter::GetPadQueue() {
365 return pad_queue;
366}
367
368std::array<GCState, 4>& Adapter::GetPadState() {
369 return state;
370}
371
374} // end of namespace GCAdapter 372} // end of namespace GCAdapter
diff --git a/src/input_common/gcadapter/gc_adapter.h b/src/input_common/gcadapter/gc_adapter.h
index 05ee73c65..3d5c41f9a 100644
--- a/src/input_common/gcadapter/gc_adapter.h
+++ b/src/input_common/gcadapter/gc_adapter.h
@@ -8,6 +8,9 @@
8#include <mutex> 8#include <mutex>
9#include <libusb.h> 9#include <libusb.h>
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/threadsafe_queue.h"
12
13namespace GCAdapter {
11 14
12enum { 15enum {
13 PAD_USE_ORIGIN = 0x0080, 16 PAD_USE_ORIGIN = 0x0080,
@@ -33,29 +36,38 @@ enum PadButton {
33 36
34}; 37};
35 38
36enum PadAxes { STICK_X, STICK_Y, SUBSTICK_X, SUBSTICK_Y, TRIGGER_LEFT, TRIGGER_RIGHT }; 39enum class PadAxes : u8 {
40 StickX,
41 StickY,
42 SubstickX,
43 SubstickY,
44 TriggerLeft,
45 TriggerRight,
46 Undefined,
47};
48const struct GCPadConstants {
49 const u8 MAIN_STICK_CENTER_X = 0x80;
50 const u8 MAIN_STICK_CENTER_Y = 0x80;
51 const u8 MAIN_STICK_RADIUS = 0x7f;
52 const u8 C_STICK_CENTER_X = 0x80;
53 const u8 C_STICK_CENTER_Y = 0x80;
54 const u8 C_STICK_RADIUS = 0x7f;
55
56 const u8 TRIGGER_CENTER = 20;
57 const u8 THRESHOLD = 10;
58} pad_constants;
37 59
38struct GCPadStatus { 60struct GCPadStatus {
39 u16 button; // Or-ed PAD_BUTTON_* and PAD_TRIGGER_* bits 61 u16 button; // Or-ed PAD_BUTTON_* and PAD_TRIGGER_* bits
40 u8 stickX; // 0 <= stickX <= 255 62 u8 stick_x; // 0 <= stick_x <= 255
41 u8 stickY; // 0 <= stickY <= 255 63 u8 stick_y; // 0 <= stick_y <= 255
42 u8 substickX; // 0 <= substickX <= 255 64 u8 substick_x; // 0 <= substick_x <= 255
43 u8 substickY; // 0 <= substickY <= 255 65 u8 substick_y; // 0 <= substick_y <= 255
44 u8 triggerLeft; // 0 <= triggerLeft <= 255 66 u8 trigger_left; // 0 <= trigger_left <= 255
45 u8 triggerRight; // 0 <= triggerRight <= 255 67 u8 trigger_right; // 0 <= trigger_right <= 255
46 bool isConnected{true}; 68
47
48 static const u8 MAIN_STICK_CENTER_X = 0x80;
49 static const u8 MAIN_STICK_CENTER_Y = 0x80;
50 static const u8 MAIN_STICK_RADIUS = 0x7f;
51 static const u8 C_STICK_CENTER_X = 0x80;
52 static const u8 C_STICK_CENTER_Y = 0x80;
53 static const u8 C_STICK_RADIUS = 0x7f;
54
55 static const u8 TRIGGER_CENTER = 20;
56 static const u8 THRESHOLD = 10;
57 u8 port; 69 u8 port;
58 u8 axis_which = 255; 70 PadAxes axis = PadAxes::Undefined;
59 u8 axis_value = 255; 71 u8 axis_value = 255;
60}; 72};
61 73
@@ -64,51 +76,88 @@ struct GCState {
64 std::unordered_map<int, u16> axes; 76 std::unordered_map<int, u16> axes;
65}; 77};
66 78
67namespace GCAdapter { 79enum class ControllerTypes { None, Wired, Wireless };
68enum ControllerTypes { CONTROLLER_NONE = 0, CONTROLLER_WIRED = 1, CONTROLLER_WIRELESS = 2 };
69 80
70enum { 81enum {
71 NO_ADAPTER_DETECTED = 0, 82 NO_ADAPTER_DETECTED = 0,
72 ADAPTER_DETECTED = 1, 83 ADAPTER_DETECTED = 1,
73}; 84};
74 85
75// Current adapter status: detected/not detected/in error (holds the error code) 86/// Singleton Adapter class
76static int current_status = NO_ADAPTER_DETECTED; 87class Adapter {
88public:
89 /// For retreiving the singleton instance
90 static Adapter* GetInstance();
91
92 /// Used for polling
93 void BeginConfiguration();
94 void EndConfiguration();
95
96 std::array<Common::SPSCQueue<GCPadStatus>, 4>& GetPadQueue();
97 std::array<GCState, 4>& GetPadState();
98
99private:
100 /// Singleton instance.
101 static Adapter* adapter_instance;
102
103 /// Initialize the GC Adapter capture and read sequence
104 Adapter();
77 105
78GCPadStatus CheckStatus(int port, u8 adapter_payload[37]); 106 /// Close the adapter read thread and release the adapter
79/// Initialize the GC Adapter capture and read sequence 107 ~Adapter();
80void Init();
81 108
82/// Close the adapter read thread and release the adapter 109 GCPadStatus CheckStatus(int port, u8 adapter_payload[37]);
83void Shutdown();
84 110
85/// Begin scanning for the GC Adapter. 111 void PadToState(GCPadStatus pad, GCState& state);
86void StartScanThread();
87 112
88/// Stop scanning for the adapter 113 void Read();
89void StopScanThread(); 114 void ScanThreadFunc();
115 /// Begin scanning for the GC Adapter.
116 void StartScanThread();
90 117
91/// Returns true if there is a device connected to port 118 /// Stop scanning for the adapter
92bool DeviceConnected(int port); 119 void StopScanThread();
93 120
94/// Resets status of device connected to port 121 /// Returns true if there is a device connected to port
95void ResetDeviceType(int port); 122 bool DeviceConnected(int port);
96 123
97/// Returns true if we successfully gain access to GC Adapter 124 /// Resets status of device connected to port
98bool CheckDeviceAccess(libusb_device* device); 125 void ResetDeviceType(int port);
99 126
100/// Captures GC Adapter endpoint address, 127 /// Returns true if we successfully gain access to GC Adapter
101void GetGCEndpoint(libusb_device* device); 128 bool CheckDeviceAccess(libusb_device* device);
102 129
103/// For shutting down, clear all data, join all threads, release usb 130 /// Captures GC Adapter endpoint address,
104void Reset(); 131 void GetGCEndpoint(libusb_device* device);
105 132
106/// For use in initialization, querying devices to find the adapter 133 /// For shutting down, clear all data, join all threads, release usb
107void Setup(); 134 void Reset();
108 135
109/// Used for polling 136 /// For use in initialization, querying devices to find the adapter
110void BeginConfiguration(); 137 void Setup();
111 138
112void EndConfiguration(); 139 int current_status = NO_ADAPTER_DETECTED;
140 libusb_device_handle* usb_adapter_handle = nullptr;
141 ControllerTypes adapter_controllers_status[4] = {ControllerTypes::None, ControllerTypes::None,
142 ControllerTypes::None, ControllerTypes::None};
143
144 std::mutex s_mutex;
145
146 std::thread adapter_input_thread;
147 bool adapter_thread_running;
148
149 std::mutex initialization_mutex;
150 std::thread detect_thread;
151 bool detect_thread_running = false;
152
153 libusb_context* libusb_ctx;
154
155 u8 input_endpoint = 0;
156
157 bool configuring = false;
158
159 std::array<Common::SPSCQueue<GCPadStatus>, 4> pad_queue;
160 std::array<GCState, 4> state;
161};
113 162
114} // end of namespace GCAdapter 163} // end of namespace GCAdapter
diff --git a/src/input_common/gcadapter/gc_poller.cpp b/src/input_common/gcadapter/gc_poller.cpp
index 51b3362d6..0e591baca 100644
--- a/src/input_common/gcadapter/gc_poller.cpp
+++ b/src/input_common/gcadapter/gc_poller.cpp
@@ -10,35 +10,34 @@
10#include "input_common/gcadapter/gc_adapter.h" 10#include "input_common/gcadapter/gc_adapter.h"
11#include "input_common/gcadapter/gc_poller.h" 11#include "input_common/gcadapter/gc_poller.h"
12 12
13// Using extern as to avoid multply defined symbols.
14extern Common::SPSCQueue<GCPadStatus> pad_queue[4];
15extern struct GCState state[4];
16
17namespace InputCommon { 13namespace InputCommon {
18 14
19class GCButton final : public Input::ButtonDevice { 15class GCButton final : public Input::ButtonDevice {
20public: 16public:
21 explicit GCButton(int port_, int button_, int axis_) : port(port_), button(button_) {} 17 explicit GCButton(int port_, int button_, int axis_, GCAdapter::Adapter* adapter)
18 : port(port_), button(button_), gcadapter(adapter) {}
22 19
23 ~GCButton() override; 20 ~GCButton() override;
24 21
25 bool GetStatus() const override { 22 bool GetStatus() const override {
26 return state[port].buttons.at(button); 23 return gcadapter->GetPadState()[port].buttons.at(button);
27 } 24 }
28 25
29private: 26private:
30 const int port; 27 const int port;
31 const int button; 28 const int button;
29 GCAdapter::Adapter* gcadapter;
32}; 30};
33 31
34class GCAxisButton final : public Input::ButtonDevice { 32class GCAxisButton final : public Input::ButtonDevice {
35public: 33public:
36 explicit GCAxisButton(int port_, int axis_, float threshold_, bool trigger_if_greater_) 34 explicit GCAxisButton(int port_, int axis_, float threshold_, bool trigger_if_greater_,
37 : port(port_), axis(axis_), threshold(threshold_), trigger_if_greater(trigger_if_greater_) { 35 GCAdapter::Adapter* adapter)
38 } 36 : port(port_), axis(axis_), threshold(threshold_), trigger_if_greater(trigger_if_greater_),
37 gcadapter(adapter) {}
39 38
40 bool GetStatus() const override { 39 bool GetStatus() const override {
41 const float axis_value = (state[port].axes.at(axis) - 128.0f) / 128.0f; 40 const float axis_value = (gcadapter->GetPadState()[port].axes.at(axis) - 128.0f) / 128.0f;
42 if (trigger_if_greater) { 41 if (trigger_if_greater) {
43 return axis_value > 0.10f; // TODO(ameerj) : Fix threshold. 42 return axis_value > 0.10f; // TODO(ameerj) : Fix threshold.
44 } 43 }
@@ -50,14 +49,15 @@ private:
50 const int axis; 49 const int axis;
51 float threshold; 50 float threshold;
52 bool trigger_if_greater; 51 bool trigger_if_greater;
52 GCAdapter::Adapter* gcadapter;
53}; 53};
54 54
55GCButtonFactory::GCButtonFactory() { 55GCButtonFactory::GCButtonFactory() {
56 GCAdapter::Init(); 56 adapter = GCAdapter::Adapter::GetInstance();
57} 57}
58 58
59GCButton::~GCButton() { 59GCButton::~GCButton() {
60 GCAdapter::Shutdown(); 60 // GCAdapter::Shutdown();
61} 61}
62 62
63std::unique_ptr<Input::ButtonDevice> GCButtonFactory::Create(const Common::ParamPackage& params) { 63std::unique_ptr<Input::ButtonDevice> GCButtonFactory::Create(const Common::ParamPackage& params) {
@@ -77,76 +77,76 @@ std::unique_ptr<Input::ButtonDevice> GCButtonFactory::Create(const Common::Param
77 trigger_if_greater = true; 77 trigger_if_greater = true;
78 LOG_ERROR(Input, "Unknown direction {}", direction_name); 78 LOG_ERROR(Input, "Unknown direction {}", direction_name);
79 } 79 }
80 return std::make_unique<GCAxisButton>(port, axis, threshold, trigger_if_greater); 80 return std::make_unique<GCAxisButton>(port, axis, threshold, trigger_if_greater, adapter);
81 } 81 }
82 82
83 std::unique_ptr<GCButton> button = 83 std::unique_ptr<GCButton> button =
84 std::make_unique<GCButton>(port, button_id, params.Get("axis", 0)); 84 std::make_unique<GCButton>(port, button_id, params.Get("axis", 0), adapter);
85 return std::move(button); 85 return std::move(button);
86} 86}
87 87
88Common::ParamPackage GCButtonFactory::GetNextInput() { 88Common::ParamPackage GCButtonFactory::GetNextInput() {
89 Common::ParamPackage params; 89 Common::ParamPackage params;
90 GCPadStatus pad; 90 GCAdapter::GCPadStatus pad;
91 for (int i = 0; i < 4; i++) { 91 for (int i = 0; i < 4; i++) {
92 while (pad_queue[i].Pop(pad)) { 92 while (adapter->GetPadQueue()[i].Pop(pad)) {
93 // This while loop will break on the earliest detected button 93 // This while loop will break on the earliest detected button
94 params.Set("engine", "gcpad"); 94 params.Set("engine", "gcpad");
95 params.Set("port", i); 95 params.Set("port", i);
96 // I was debating whether to keep these verbose for ease of reading 96 // I was debating whether to keep these verbose for ease of reading
97 // or to use a while loop shifting the bits to test and set the value. 97 // or to use a while loop shifting the bits to test and set the value.
98 if (pad.button & PAD_BUTTON_A) { 98 if (pad.button & GCAdapter::PAD_BUTTON_A) {
99 params.Set("button", PAD_BUTTON_A); 99 params.Set("button", GCAdapter::PAD_BUTTON_A);
100 break; 100 break;
101 } 101 }
102 if (pad.button & PAD_BUTTON_B) { 102 if (pad.button & GCAdapter::PAD_BUTTON_B) {
103 params.Set("button", PAD_BUTTON_B); 103 params.Set("button", GCAdapter::PAD_BUTTON_B);
104 break; 104 break;
105 } 105 }
106 if (pad.button & PAD_BUTTON_X) { 106 if (pad.button & GCAdapter::PAD_BUTTON_X) {
107 params.Set("button", PAD_BUTTON_X); 107 params.Set("button", GCAdapter::PAD_BUTTON_X);
108 break; 108 break;
109 } 109 }
110 if (pad.button & PAD_BUTTON_Y) { 110 if (pad.button & GCAdapter::PAD_BUTTON_Y) {
111 params.Set("button", PAD_BUTTON_Y); 111 params.Set("button", GCAdapter::PAD_BUTTON_Y);
112 break; 112 break;
113 } 113 }
114 if (pad.button & PAD_BUTTON_DOWN) { 114 if (pad.button & GCAdapter::PAD_BUTTON_DOWN) {
115 params.Set("button", PAD_BUTTON_DOWN); 115 params.Set("button", GCAdapter::PAD_BUTTON_DOWN);
116 break; 116 break;
117 } 117 }
118 if (pad.button & PAD_BUTTON_LEFT) { 118 if (pad.button & GCAdapter::PAD_BUTTON_LEFT) {
119 params.Set("button", PAD_BUTTON_LEFT); 119 params.Set("button", GCAdapter::PAD_BUTTON_LEFT);
120 break; 120 break;
121 } 121 }
122 if (pad.button & PAD_BUTTON_RIGHT) { 122 if (pad.button & GCAdapter::PAD_BUTTON_RIGHT) {
123 params.Set("button", PAD_BUTTON_RIGHT); 123 params.Set("button", GCAdapter::PAD_BUTTON_RIGHT);
124 break; 124 break;
125 } 125 }
126 if (pad.button & PAD_BUTTON_UP) { 126 if (pad.button & GCAdapter::PAD_BUTTON_UP) {
127 params.Set("button", PAD_BUTTON_UP); 127 params.Set("button", GCAdapter::PAD_BUTTON_UP);
128 break; 128 break;
129 } 129 }
130 if (pad.button & PAD_TRIGGER_L) { 130 if (pad.button & GCAdapter::PAD_TRIGGER_L) {
131 params.Set("button", PAD_TRIGGER_L); 131 params.Set("button", GCAdapter::PAD_TRIGGER_L);
132 break; 132 break;
133 } 133 }
134 if (pad.button & PAD_TRIGGER_R) { 134 if (pad.button & GCAdapter::PAD_TRIGGER_R) {
135 params.Set("button", PAD_TRIGGER_R); 135 params.Set("button", GCAdapter::PAD_TRIGGER_R);
136 break; 136 break;
137 } 137 }
138 if (pad.button & PAD_TRIGGER_Z) { 138 if (pad.button & GCAdapter::PAD_TRIGGER_Z) {
139 params.Set("button", PAD_TRIGGER_Z); 139 params.Set("button", GCAdapter::PAD_TRIGGER_Z);
140 break; 140 break;
141 } 141 }
142 if (pad.button & PAD_BUTTON_START) { 142 if (pad.button & GCAdapter::PAD_BUTTON_START) {
143 params.Set("button", PAD_BUTTON_START); 143 params.Set("button", GCAdapter::PAD_BUTTON_START);
144 break; 144 break;
145 } 145 }
146 // For Axis button implementation 146 // For Axis button implementation
147 if (pad.axis_which != 255) { 147 if (pad.axis != GCAdapter::PadAxes::Undefined) {
148 params.Set("axis", pad.axis_which); 148 params.Set("axis", static_cast<u8>(pad.axis));
149 params.Set("button", PAD_STICK); 149 params.Set("button", GCAdapter::PAD_STICK);
150 if (pad.axis_value > 128) { 150 if (pad.axis_value > 128) {
151 params.Set("direction", "+"); 151 params.Set("direction", "+");
152 params.Set("threshold", "0.5"); 152 params.Set("threshold", "0.5");
@@ -164,30 +164,30 @@ Common::ParamPackage GCButtonFactory::GetNextInput() {
164void GCButtonFactory::BeginConfiguration() { 164void GCButtonFactory::BeginConfiguration() {
165 polling = true; 165 polling = true;
166 for (int i = 0; i < 4; i++) { 166 for (int i = 0; i < 4; i++) {
167 pad_queue[i].Clear(); 167 adapter->GetPadQueue()[i].Clear();
168 } 168 }
169 GCAdapter::BeginConfiguration(); 169 adapter->BeginConfiguration();
170} 170}
171 171
172void GCButtonFactory::EndConfiguration() { 172void GCButtonFactory::EndConfiguration() {
173 polling = false; 173 polling = false;
174 for (int i = 0; i < 4; i++) { 174 for (int i = 0; i < 4; i++) {
175 pad_queue[i].Clear(); 175 adapter->GetPadQueue()[i].Clear();
176 } 176 }
177 GCAdapter::EndConfiguration(); 177 adapter->EndConfiguration();
178} 178}
179 179
180class GCAnalog final : public Input::AnalogDevice { 180class GCAnalog final : public Input::AnalogDevice {
181public: 181public:
182 GCAnalog(int port_, int axis_x_, int axis_y_, float deadzone_) 182 GCAnalog(int port_, int axis_x_, int axis_y_, float deadzone_, GCAdapter::Adapter* adapter)
183 : port(port_), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_) {} 183 : port(port_), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), gcadapter(adapter) {}
184 184
185 float GetAxis(int axis) const { 185 float GetAxis(int axis) const {
186 std::lock_guard lock{mutex}; 186 std::lock_guard lock{mutex};
187 // division is not by a perfect 128 to account for some variance in center location 187 // division is not by a perfect 128 to account for some variance in center location
188 // e.g. my device idled at 131 in X, 120 in Y, and full range of motion was in range 188 // e.g. my device idled at 131 in X, 120 in Y, and full range of motion was in range
189 // [20-230] 189 // [20-230]
190 return (state[port].axes.at(axis) - 128.0f) / 95.0f; 190 return (gcadapter->GetPadState()[port].axes.at(axis) - 128.0f) / 95.0f;
191 } 191 }
192 192
193 std::tuple<float, float> GetAnalog(int axis_x, int axis_y) const { 193 std::tuple<float, float> GetAnalog(int axis_x, int axis_y) const {
@@ -238,10 +238,13 @@ private:
238 const int axis_y; 238 const int axis_y;
239 const float deadzone; 239 const float deadzone;
240 mutable std::mutex mutex; 240 mutable std::mutex mutex;
241 GCAdapter::Adapter* gcadapter;
241}; 242};
242 243
243/// An analog device factory that creates analog devices from GC Adapter 244/// An analog device factory that creates analog devices from GC Adapter
244GCAnalogFactory::GCAnalogFactory(){}; 245GCAnalogFactory::GCAnalogFactory() {
246 adapter = GCAdapter::Adapter::GetInstance();
247};
245 248
246/** 249/**
247 * Creates analog device from joystick axes 250 * Creates analog device from joystick axes
@@ -257,35 +260,36 @@ std::unique_ptr<Input::AnalogDevice> GCAnalogFactory::Create(const Common::Param
257 const int axis_y = params.Get("axis_y", 1); 260 const int axis_y = params.Get("axis_y", 1);
258 const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f); 261 const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f);
259 262
260 return std::make_unique<GCAnalog>(port, axis_x, axis_y, deadzone); 263 return std::make_unique<GCAnalog>(port, axis_x, axis_y, deadzone, adapter);
261} 264}
262 265
263void GCAnalogFactory::BeginConfiguration() { 266void GCAnalogFactory::BeginConfiguration() {
264 polling = true; 267 polling = true;
265 for (int i = 0; i < 4; i++) { 268 for (int i = 0; i < 4; i++) {
266 pad_queue[i].Clear(); 269 adapter->GetPadQueue()[i].Clear();
267 } 270 }
268 GCAdapter::BeginConfiguration(); 271 adapter->BeginConfiguration();
269} 272}
270 273
271void GCAnalogFactory::EndConfiguration() { 274void GCAnalogFactory::EndConfiguration() {
272 polling = false; 275 polling = false;
273 for (int i = 0; i < 4; i++) { 276 for (int i = 0; i < 4; i++) {
274 pad_queue[i].Clear(); 277 adapter->GetPadQueue()[i].Clear();
275 } 278 }
276 GCAdapter::EndConfiguration(); 279 adapter->EndConfiguration();
277} 280}
278 281
279Common::ParamPackage GCAnalogFactory::GetNextInput() { 282Common::ParamPackage GCAnalogFactory::GetNextInput() {
280 GCPadStatus pad; 283 GCAdapter::GCPadStatus pad;
281 for (int i = 0; i < 4; i++) { 284 for (int i = 0; i < 4; i++) {
282 while (pad_queue[i].Pop(pad)) { 285 while (adapter->GetPadQueue()[i].Pop(pad)) {
283 if (pad.axis_which == 255 || std::abs((pad.axis_value - 128.0f) / 128.0f) < 0.1) { 286 if (pad.axis == GCAdapter::PadAxes::Undefined ||
287 std::abs((pad.axis_value - 128.0f) / 128.0f) < 0.1) {
284 continue; 288 continue;
285 } 289 }
286 // An analog device needs two axes, so we need to store the axis for later and wait for 290 // An analog device needs two axes, so we need to store the axis for later and wait for
287 // a second SDL event. The axes also must be from the same joystick. 291 // a second SDL event. The axes also must be from the same joystick.
288 const int axis = pad.axis_which; 292 const u8 axis = static_cast<u8>(pad.axis);
289 if (analog_x_axis == -1) { 293 if (analog_x_axis == -1) {
290 analog_x_axis = axis; 294 analog_x_axis = axis;
291 controller_number = i; 295 controller_number = i;
@@ -307,4 +311,5 @@ Common::ParamPackage GCAnalogFactory::GetNextInput() {
307 } 311 }
308 return params; 312 return params;
309} 313}
314
310} // namespace InputCommon 315} // namespace InputCommon
diff --git a/src/input_common/gcadapter/gc_poller.h b/src/input_common/gcadapter/gc_poller.h
index 43aa9e93a..29b8c0b7c 100644
--- a/src/input_common/gcadapter/gc_poller.h
+++ b/src/input_common/gcadapter/gc_poller.h
@@ -35,6 +35,7 @@ public:
35 } 35 }
36 36
37private: 37private:
38 GCAdapter::Adapter* adapter;
38 bool polling = false; 39 bool polling = false;
39}; 40};
40 41
@@ -54,9 +55,11 @@ public:
54 } 55 }
55 56
56private: 57private:
58 GCAdapter::Adapter* adapter;
57 int analog_x_axis = -1; 59 int analog_x_axis = -1;
58 int analog_y_axis = -1; 60 int analog_y_axis = -1;
59 int controller_number = -1; 61 int controller_number = -1;
60 bool polling = false; 62 bool polling = false;
61}; 63};
64
62} // namespace InputCommon 65} // namespace InputCommon
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index 7fc0e2db4..536e5c80a 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -2,11 +2,13 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <iostream>
5#include <memory> 6#include <memory>
6#include <thread> 7#include <thread>
7#include <libusb.h> 8#include <libusb.h>
8#include "common/param_package.h" 9#include "common/param_package.h"
9#include "input_common/analog_from_button.h" 10#include "input_common/analog_from_button.h"
11#include "input_common/gcadapter/gc_adapter.h"
10#include "input_common/gcadapter/gc_poller.h" 12#include "input_common/gcadapter/gc_poller.h"
11#include "input_common/keyboard.h" 13#include "input_common/keyboard.h"
12#include "input_common/main.h" 14#include "input_common/main.h"
diff --git a/src/input_common/main.h b/src/input_common/main.h
index 9e1528c88..c26222f21 100644
--- a/src/input_common/main.h
+++ b/src/input_common/main.h
@@ -32,10 +32,8 @@ class MotionEmu;
32/// Gets the motion emulation factory. 32/// Gets the motion emulation factory.
33MotionEmu* GetMotionEmu(); 33MotionEmu* GetMotionEmu();
34 34
35class GCButtonFactory;
36class GCAnalogFactory;
37
38GCButtonFactory* GetGCButtons(); 35GCButtonFactory* GetGCButtons();
36
39GCAnalogFactory* GetGCAnalogs(); 37GCAnalogFactory* GetGCAnalogs();
40 38
41/// Generates a serialized param package for creating a keyboard button device 39/// Generates a serialized param package for creating a keyboard button device
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp
index 4c9794ce2..da5227058 100644
--- a/src/input_common/udp/client.cpp
+++ b/src/input_common/udp/client.cpp
@@ -225,7 +225,8 @@ void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 clie
225 } else { 225 } else {
226 failure_callback(); 226 failure_callback();
227 } 227 }
228 }).detach(); 228 })
229 .detach();
229} 230}
230 231
231CalibrationConfigurationJob::CalibrationConfigurationJob( 232CalibrationConfigurationJob::CalibrationConfigurationJob(
@@ -279,7 +280,8 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
279 complete_event.Wait(); 280 complete_event.Wait();
280 socket.Stop(); 281 socket.Stop();
281 worker_thread.join(); 282 worker_thread.join();
282 }).detach(); 283 })
284 .detach();
283} 285}
284 286
285CalibrationConfigurationJob::~CalibrationConfigurationJob() { 287CalibrationConfigurationJob::~CalibrationConfigurationJob() {
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index c1a0c423b..c7d3f4510 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -262,25 +262,24 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
262 262
263 button->setContextMenuPolicy(Qt::CustomContextMenu); 263 button->setContextMenuPolicy(Qt::CustomContextMenu);
264 connect(button, &QPushButton::clicked, [=] { 264 connect(button, &QPushButton::clicked, [=] {
265 HandleClick( 265 HandleClick(button_map[button_id],
266 button_map[button_id], 266 [=](Common::ParamPackage params) {
267 [=](Common::ParamPackage params) { 267 // Workaround for ZL & ZR for analog triggers like on XBOX controllors.
268 // Workaround for ZL & ZR for analog triggers like on XBOX controllors. 268 // Analog triggers (from controllers like the XBOX controller) would not
269 // Analog triggers (from controllers like the XBOX controller) would not 269 // work due to a different range of their signals (from 0 to 255 on
270 // work due to a different range of their signals (from 0 to 255 on 270 // analog triggers instead of -32768 to 32768 on analog joysticks). The
271 // analog triggers instead of -32768 to 32768 on analog joysticks). The 271 // SDL driver misinterprets analog triggers as analog joysticks.
272 // SDL driver misinterprets analog triggers as analog joysticks. 272 // TODO: reinterpret the signal range for analog triggers to map the
273 // TODO: reinterpret the signal range for analog triggers to map the 273 // values correctly. This is required for the correct emulation of the
274 // values correctly. This is required for the correct emulation of the 274 // analog triggers of the GameCube controller.
275 // analog triggers of the GameCube controller. 275 if (button_id == Settings::NativeButton::ZL ||
276 if (button_id == Settings::NativeButton::ZL || 276 button_id == Settings::NativeButton::ZR) {
277 button_id == Settings::NativeButton::ZR) { 277 params.Set("direction", "+");
278 params.Set("direction", "+"); 278 params.Set("threshold", "0.5");
279 params.Set("threshold", "0.5"); 279 }
280 } 280 buttons_param[button_id] = std::move(params);
281 buttons_param[button_id] = std::move(params); 281 },
282 }, 282 InputCommon::Polling::DeviceType::Button);
283 InputCommon::Polling::DeviceType::Button);
284 }); 283 });
285 connect(button, &QPushButton::customContextMenuRequested, [=](const QPoint& menu_location) { 284 connect(button, &QPushButton::customContextMenuRequested, [=](const QPoint& menu_location) {
286 QMenu context_menu; 285 QMenu context_menu;
@@ -306,13 +305,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
306 305
307 analog_button->setContextMenuPolicy(Qt::CustomContextMenu); 306 analog_button->setContextMenuPolicy(Qt::CustomContextMenu);
308 connect(analog_button, &QPushButton::clicked, [=]() { 307 connect(analog_button, &QPushButton::clicked, [=]() {
309 HandleClick( 308 HandleClick(analog_map_buttons[analog_id][sub_button_id],
310 analog_map_buttons[analog_id][sub_button_id], 309 [=](const Common::ParamPackage& params) {
311 [=](const Common::ParamPackage& params) { 310 SetAnalogButton(params, analogs_param[analog_id],
312 SetAnalogButton(params, analogs_param[analog_id], 311 analog_sub_buttons[sub_button_id]);
313 analog_sub_buttons[sub_button_id]); 312 },
314 }, 313 InputCommon::Polling::DeviceType::Button);
315 InputCommon::Polling::DeviceType::Button);
316 }); 314 });
317 connect(analog_button, &QPushButton::customContextMenuRequested, 315 connect(analog_button, &QPushButton::customContextMenuRequested,
318 [=](const QPoint& menu_location) { 316 [=](const QPoint& menu_location) {