diff options
Diffstat (limited to 'Source/Core/InputCommon/GCAdapter.cpp')
| -rw-r--r-- | Source/Core/InputCommon/GCAdapter.cpp | 57 |
1 files changed, 39 insertions, 18 deletions
diff --git a/Source/Core/InputCommon/GCAdapter.cpp b/Source/Core/InputCommon/GCAdapter.cpp index d52bdf561d..174e374bf8 100644 --- a/Source/Core/InputCommon/GCAdapter.cpp +++ b/Source/Core/InputCommon/GCAdapter.cpp @@ -9,6 +9,7 @@ #include "Common/Event.h" #include "Common/Flag.h" #include "Common/Logging/Log.h" +#include "Common/ScopeGuard.h" #include "Common/Thread.h" #include "Core/ConfigManager.h" #include "Core/Core.h" @@ -29,7 +30,14 @@ static void ResetRumbleLockNeeded(); static void Reset(); static void Setup(); -static bool s_detected = false; +enum +{ + NO_ADAPTER_DETECTED = 0, + ADAPTER_DETECTED = 1, +}; + +// Current adapter status: detected/not detected/in error (holds the error code) +static int s_status = NO_ADAPTER_DETECTED; static libusb_device_handle* s_handle = nullptr; static u8 s_controller_type[SerialInterface::MAX_SI_CHANNELS] = { ControllerTypes::CONTROLLER_NONE, ControllerTypes::CONTROLLER_NONE, @@ -54,7 +62,6 @@ static Common::Flag s_adapter_detect_thread_running; static std::function<void(void)> s_detect_callback; -static bool s_libusb_driver_not_supported = false; #if defined(__FreeBSD__) && __FreeBSD__ >= 11 static bool s_libusb_hotplug_enabled = true; #else @@ -120,6 +127,10 @@ static int HotplugCallback(libusb_context* ctx, libusb_device* dev, libusb_hotpl { if (s_handle != nullptr && libusb_get_device(s_handle) == dev) Reset(); + + // Reset a potential error status now that the adapter is unplugged + if (s_status < 0) + s_status = 0; } return 0; } @@ -158,7 +169,7 @@ static void ScanThreadFunc() { std::lock_guard<std::mutex> lk(s_init_mutex); Setup(); - if (s_detected && s_detect_callback != nullptr) + if (s_status == ADAPTER_DETECTED && s_detect_callback != nullptr) s_detect_callback(); } Common::SleepCurrentThread(500); @@ -184,7 +195,7 @@ void Init() s_last_init = CoreTiming::GetTicks(); } - s_libusb_driver_not_supported = false; + s_status = NO_ADAPTER_DETECTED; if (UseAdapter()) StartScanThread(); @@ -247,6 +258,9 @@ static bool CheckDeviceAccess(libusb_device* device) NOTICE_LOG(SERIALINTERFACE, "Found GC Adapter with Vendor: %X Product: %X Devnum: %d", desc.idVendor, desc.idProduct, 1); + // In case of failure, capture the libusb error code into the adapter status + Common::ScopeGuard status_guard([&ret] { s_status = ret; }); + u8 bus = libusb_get_bus_number(device); u8 port = libusb_get_device_address(device); ret = libusb_open(device, &s_handle); @@ -260,8 +274,6 @@ static bool CheckDeviceAccess(libusb_device* device) if (ret) { ERROR_LOG(SERIALINTERFACE, "libusb_open failed to open device with error = %d", ret); - if (ret == LIBUSB_ERROR_NOT_SUPPORTED) - s_libusb_driver_not_supported = true; return false; } @@ -291,6 +303,9 @@ static bool CheckDeviceAccess(libusb_device* device) return false; } + // Updating the adapter status will be done in AddGCAdapter + status_guard.Dismiss(); + return true; } @@ -323,7 +338,7 @@ static void AddGCAdapter(libusb_device* device) s_adapter_input_thread = std::thread(Read); s_adapter_output_thread = std::thread(Write); - s_detected = true; + s_status = ADAPTER_DETECTED; if (s_detect_callback != nullptr) s_detect_callback(); ResetRumbleLockNeeded(); @@ -338,7 +353,7 @@ void Shutdown() #endif Reset(); - s_libusb_driver_not_supported = false; + s_status = NO_ADAPTER_DETECTED; } static void Reset() @@ -346,7 +361,7 @@ static void Reset() std::unique_lock<std::mutex> lock(s_init_mutex, std::defer_lock); if (!lock.try_lock()) return; - if (!s_detected) + if (s_status != ADAPTER_DETECTED) return; if (s_adapter_thread_running.TestAndClear()) @@ -359,7 +374,7 @@ static void Reset() for (int i = 0; i < SerialInterface::MAX_SI_CHANNELS; i++) s_controller_type[i] = ControllerTypes::CONTROLLER_NONE; - s_detected = false; + s_status = NO_ADAPTER_DETECTED; if (s_handle) { @@ -377,7 +392,7 @@ GCPadStatus Input(int chan) if (!UseAdapter()) return {}; - if (s_handle == nullptr || !s_detected) + if (s_handle == nullptr || s_status != ADAPTER_DETECTED) return {}; int payload_size = 0; @@ -497,7 +512,7 @@ void ResetRumble() // being called while the libusb state is being reset static void ResetRumbleLockNeeded() { - if (!UseAdapter() || (s_handle == nullptr || !s_detected)) + if (!UseAdapter() || (s_handle == nullptr || s_status != ADAPTER_DETECTED)) { return; } @@ -527,14 +542,20 @@ void Output(int chan, u8 rumble_command) } } -bool IsDetected() +bool IsDetected(const char** error_message) { - return s_detected; -} + if (s_status >= 0) + { + if (error_message) + *error_message = nullptr; -bool IsDriverDetected() -{ - return !s_libusb_driver_not_supported; + return s_status == ADAPTER_DETECTED; + } + + if (error_message) + *error_message = libusb_strerror(static_cast<libusb_error>(s_status)); + + return false; } } // end of namespace GCAdapter |
