diff options
| author | 2020-06-21 18:43:01 -0400 | |
|---|---|---|
| committer | 2020-06-21 21:17:07 -0400 | |
| commit | 121af3646dad0f80453d2ffffa688dd4435d3acc (patch) | |
| tree | 020971e22b4423f63a0a04da7fa4087bf85e2bb9 /src | |
| parent | Clang Formatting (diff) | |
| download | yuzu-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.cpp | 176 | ||||
| -rw-r--r-- | src/input_common/gcadapter/gc_adapter.h | 145 | ||||
| -rw-r--r-- | src/input_common/gcadapter/gc_poller.cpp | 125 | ||||
| -rw-r--r-- | src/input_common/gcadapter/gc_poller.h | 3 | ||||
| -rw-r--r-- | src/input_common/main.cpp | 2 | ||||
| -rw-r--r-- | src/input_common/main.h | 4 | ||||
| -rw-r--r-- | src/input_common/udp/client.cpp | 6 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_input_player.cpp | 50 |
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 | ||
| 9 | Common::SPSCQueue<GCPadStatus> pad_queue[4]; | ||
| 10 | struct GCState state[4]; | ||
| 11 | |||
| 12 | namespace GCAdapter { | 8 | namespace GCAdapter { |
| 9 | Adapter* Adapter::adapter_instance{nullptr}; | ||
| 13 | 10 | ||
| 14 | static libusb_device_handle* usb_adapter_handle = nullptr; | 11 | Adapter::Adapter() { |
| 15 | static 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"); | |
| 19 | static std::mutex s_mutex; | ||
| 20 | |||
| 21 | static std::thread adapter_input_thread; | ||
| 22 | static bool adapter_thread_running; | ||
| 23 | |||
| 24 | static std::mutex initialization_mutex; | ||
| 25 | static std::thread detect_thread; | ||
| 26 | static bool detect_thread_running = false; | ||
| 27 | 16 | ||
| 28 | static libusb_context* libusb_ctx; | 17 | current_status = NO_ADAPTER_DETECTED; |
| 18 | libusb_init(&libusb_ctx); | ||
| 29 | 19 | ||
| 30 | static u8 input_endpoint = 0; | 20 | StartScanThread(); |
| 21 | } | ||
| 31 | 22 | ||
| 32 | static bool configuring = false; | 23 | Adapter* Adapter::GetInstance() { |
| 24 | if (!adapter_instance) { | ||
| 25 | adapter_instance = new Adapter; | ||
| 26 | } | ||
| 27 | return adapter_instance; | ||
| 28 | } | ||
| 33 | 29 | ||
| 34 | GCPadStatus CheckStatus(int port, u8 adapter_payload[37]) { | 30 | GCPadStatus 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 | ||
| 101 | void PadToState(GCPadStatus pad, GCState& state) { | 97 | void 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 | ||
| 123 | static void Read() { | 118 | void 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 | ||
| 189 | static void ScanThreadFunc() { | 193 | void 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 | ||
| 201 | void Init() { | 205 | void 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 | |||
| 214 | void 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 | ||
| 226 | void StopScanThread() { | 217 | void Adapter::StopScanThread() { |
| 227 | detect_thread.join(); | 218 | detect_thread.join(); |
| 228 | } | 219 | } |
| 229 | 220 | ||
| 230 | static void Setup() { | 221 | void 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 | ||
| 253 | static bool CheckDeviceAccess(libusb_device* device) { | 244 | bool 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 | ||
| 303 | static void GetGCEndpoint(libusb_device* device) { | 294 | void 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 | ||
| 325 | void Shutdown() { | 315 | Adapter::~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 | ||
| 332 | static void Reset() { | 322 | void 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 | ||
| 358 | bool DeviceConnected(int port) { | 348 | bool 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 | ||
| 362 | void ResetDeviceType(int port) { | 352 | void Adapter::ResetDeviceType(int port) { |
| 363 | adapter_controllers_status[port] = ControllerTypes::CONTROLLER_NONE; | 353 | adapter_controllers_status[port] = ControllerTypes::None; |
| 364 | } | 354 | } |
| 365 | 355 | ||
| 366 | void BeginConfiguration() { | 356 | void Adapter::BeginConfiguration() { |
| 367 | configuring = true; | 357 | configuring = true; |
| 368 | } | 358 | } |
| 369 | 359 | ||
| 370 | void EndConfiguration() { | 360 | void Adapter::EndConfiguration() { |
| 371 | configuring = false; | 361 | configuring = false; |
| 372 | } | 362 | } |
| 373 | 363 | ||
| 364 | std::array<Common::SPSCQueue<GCPadStatus>, 4>& Adapter::GetPadQueue() { | ||
| 365 | return pad_queue; | ||
| 366 | } | ||
| 367 | |||
| 368 | std::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 | |||
| 13 | namespace GCAdapter { | ||
| 11 | 14 | ||
| 12 | enum { | 15 | enum { |
| 13 | PAD_USE_ORIGIN = 0x0080, | 16 | PAD_USE_ORIGIN = 0x0080, |
| @@ -33,29 +36,38 @@ enum PadButton { | |||
| 33 | 36 | ||
| 34 | }; | 37 | }; |
| 35 | 38 | ||
| 36 | enum PadAxes { STICK_X, STICK_Y, SUBSTICK_X, SUBSTICK_Y, TRIGGER_LEFT, TRIGGER_RIGHT }; | 39 | enum class PadAxes : u8 { |
| 40 | StickX, | ||
| 41 | StickY, | ||
| 42 | SubstickX, | ||
| 43 | SubstickY, | ||
| 44 | TriggerLeft, | ||
| 45 | TriggerRight, | ||
| 46 | Undefined, | ||
| 47 | }; | ||
| 48 | const 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 | ||
| 38 | struct GCPadStatus { | 60 | struct 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 | ||
| 67 | namespace GCAdapter { | 79 | enum class ControllerTypes { None, Wired, Wireless }; |
| 68 | enum ControllerTypes { CONTROLLER_NONE = 0, CONTROLLER_WIRED = 1, CONTROLLER_WIRELESS = 2 }; | ||
| 69 | 80 | ||
| 70 | enum { | 81 | enum { |
| 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 |
| 76 | static int current_status = NO_ADAPTER_DETECTED; | 87 | class Adapter { |
| 88 | public: | ||
| 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 | |||
| 99 | private: | ||
| 100 | /// Singleton instance. | ||
| 101 | static Adapter* adapter_instance; | ||
| 102 | |||
| 103 | /// Initialize the GC Adapter capture and read sequence | ||
| 104 | Adapter(); | ||
| 77 | 105 | ||
| 78 | GCPadStatus 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(); |
| 80 | void Init(); | ||
| 81 | 108 | ||
| 82 | /// Close the adapter read thread and release the adapter | 109 | GCPadStatus CheckStatus(int port, u8 adapter_payload[37]); |
| 83 | void Shutdown(); | ||
| 84 | 110 | ||
| 85 | /// Begin scanning for the GC Adapter. | 111 | void PadToState(GCPadStatus pad, GCState& state); |
| 86 | void StartScanThread(); | ||
| 87 | 112 | ||
| 88 | /// Stop scanning for the adapter | 113 | void Read(); |
| 89 | void 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 |
| 92 | bool 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 |
| 95 | void 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 |
| 98 | bool 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 |
| 101 | void 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, |
| 104 | void 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 |
| 107 | void Setup(); | 134 | void Reset(); |
| 108 | 135 | ||
| 109 | /// Used for polling | 136 | /// For use in initialization, querying devices to find the adapter |
| 110 | void BeginConfiguration(); | 137 | void Setup(); |
| 111 | 138 | ||
| 112 | void 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. | ||
| 14 | extern Common::SPSCQueue<GCPadStatus> pad_queue[4]; | ||
| 15 | extern struct GCState state[4]; | ||
| 16 | |||
| 17 | namespace InputCommon { | 13 | namespace InputCommon { |
| 18 | 14 | ||
| 19 | class GCButton final : public Input::ButtonDevice { | 15 | class GCButton final : public Input::ButtonDevice { |
| 20 | public: | 16 | public: |
| 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 | ||
| 29 | private: | 26 | private: |
| 30 | const int port; | 27 | const int port; |
| 31 | const int button; | 28 | const int button; |
| 29 | GCAdapter::Adapter* gcadapter; | ||
| 32 | }; | 30 | }; |
| 33 | 31 | ||
| 34 | class GCAxisButton final : public Input::ButtonDevice { | 32 | class GCAxisButton final : public Input::ButtonDevice { |
| 35 | public: | 33 | public: |
| 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 | ||
| 55 | GCButtonFactory::GCButtonFactory() { | 55 | GCButtonFactory::GCButtonFactory() { |
| 56 | GCAdapter::Init(); | 56 | adapter = GCAdapter::Adapter::GetInstance(); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | GCButton::~GCButton() { | 59 | GCButton::~GCButton() { |
| 60 | GCAdapter::Shutdown(); | 60 | // GCAdapter::Shutdown(); |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | std::unique_ptr<Input::ButtonDevice> GCButtonFactory::Create(const Common::ParamPackage& params) { | 63 | std::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 | ||
| 88 | Common::ParamPackage GCButtonFactory::GetNextInput() { | 88 | Common::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() { | |||
| 164 | void GCButtonFactory::BeginConfiguration() { | 164 | void 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 | ||
| 172 | void GCButtonFactory::EndConfiguration() { | 172 | void 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 | ||
| 180 | class GCAnalog final : public Input::AnalogDevice { | 180 | class GCAnalog final : public Input::AnalogDevice { |
| 181 | public: | 181 | public: |
| 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 |
| 244 | GCAnalogFactory::GCAnalogFactory(){}; | 245 | GCAnalogFactory::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 | ||
| 263 | void GCAnalogFactory::BeginConfiguration() { | 266 | void 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 | ||
| 271 | void GCAnalogFactory::EndConfiguration() { | 274 | void 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 | ||
| 279 | Common::ParamPackage GCAnalogFactory::GetNextInput() { | 282 | Common::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 | ||
| 37 | private: | 37 | private: |
| 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 | ||
| 56 | private: | 57 | private: |
| 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. |
| 33 | MotionEmu* GetMotionEmu(); | 33 | MotionEmu* GetMotionEmu(); |
| 34 | 34 | ||
| 35 | class GCButtonFactory; | ||
| 36 | class GCAnalogFactory; | ||
| 37 | |||
| 38 | GCButtonFactory* GetGCButtons(); | 35 | GCButtonFactory* GetGCButtons(); |
| 36 | |||
| 39 | GCAnalogFactory* GetGCAnalogs(); | 37 | GCAnalogFactory* 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 | ||
| 231 | CalibrationConfigurationJob::CalibrationConfigurationJob( | 232 | CalibrationConfigurationJob::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 | ||
| 285 | CalibrationConfigurationJob::~CalibrationConfigurationJob() { | 287 | CalibrationConfigurationJob::~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) { |