summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon/GCAdapter.cpp
diff options
context:
space:
mode:
authorVincent Duvert <vincent@duvert.net>2018-07-17 22:31:18 +0200
committerVincent Duvert <vincent@duvert.net>2019-05-29 18:28:24 +0200
commitb08e2ec959a8e54bcbca92816400119d798129ca (patch)
tree288c9b48b93b4767366ee69b72e0f7634a9e37e0 /Source/Core/InputCommon/GCAdapter.cpp
parent0165e5e703c791451d6e6f064f53fb0ff0d6b4c3 (diff)
GCAdapter: Report libusb open errors to the user
If opening the adapter fails, report the libusb error message in the GUI instead of “No Adapter Detected”. The error condition is removed when the adapter is unplugged.
Diffstat (limited to 'Source/Core/InputCommon/GCAdapter.cpp')
-rw-r--r--Source/Core/InputCommon/GCAdapter.cpp57
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