summaryrefslogtreecommitdiff
path: root/Source
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
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')
-rw-r--r--Source/Core/Core/Analytics.cpp4
-rw-r--r--Source/Core/DolphinQt/Config/Mapping/GCPadWiiUConfigDialog.cpp20
-rw-r--r--Source/Core/InputCommon/GCAdapter.cpp57
-rw-r--r--Source/Core/InputCommon/GCAdapter.h3
4 files changed, 60 insertions, 24 deletions
diff --git a/Source/Core/Core/Analytics.cpp b/Source/Core/Core/Analytics.cpp
index 4486a9708a..d83fb4762b 100644
--- a/Source/Core/Core/Analytics.cpp
+++ b/Source/Core/Core/Analytics.cpp
@@ -391,9 +391,9 @@ void DolphinAnalytics::MakePerGameBuilder()
// We grab enough to tell what percentage of our users are playing with keyboard/mouse, some kind
// of gamepad
// or the official gamecube adapter.
- builder.AddData("gcadapter-detected", GCAdapter::IsDetected());
+ builder.AddData("gcadapter-detected", GCAdapter::IsDetected(nullptr));
builder.AddData("has-controller", Pad::GetConfig()->IsControllerControlledByGamepadDevice(0) ||
- GCAdapter::IsDetected());
+ GCAdapter::IsDetected(nullptr));
m_per_game_builder = builder;
}
diff --git a/Source/Core/DolphinQt/Config/Mapping/GCPadWiiUConfigDialog.cpp b/Source/Core/DolphinQt/Config/Mapping/GCPadWiiUConfigDialog.cpp
index 82e3e41a21..85cd35fb79 100644
--- a/Source/Core/DolphinQt/Config/Mapping/GCPadWiiUConfigDialog.cpp
+++ b/Source/Core/DolphinQt/Config/Mapping/GCPadWiiUConfigDialog.cpp
@@ -28,9 +28,25 @@ void GCPadWiiUConfigDialog::CreateLayout()
{
setWindowTitle(tr("GameCube Adapter for Wii U at Port %1").arg(m_port + 1));
- const bool detected = GCAdapter::IsDetected();
+ const char* error_message = nullptr;
+ const bool detected = GCAdapter::IsDetected(&error_message);
+ QString status_text;
+
+ if (detected)
+ {
+ status_text = tr("Adapter Detected");
+ }
+ else if (error_message)
+ {
+ status_text = tr("Error Opening Adapter: %1").arg(QString::fromUtf8(error_message));
+ }
+ else
+ {
+ status_text = tr("No Adapter Detected");
+ }
+
m_layout = new QVBoxLayout();
- m_status_label = new QLabel(detected ? tr("Adapter Detected") : tr("No Adapter Detected"));
+ m_status_label = new QLabel(status_text);
m_rumble = new QCheckBox(tr("Enable Rumble"));
m_simulate_bongos = new QCheckBox(tr("Simulate DK Bongos"));
m_button_box = new QDialogButtonBox(QDialogButtonBox::Ok);
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
diff --git a/Source/Core/InputCommon/GCAdapter.h b/Source/Core/InputCommon/GCAdapter.h
index 02b15a3cd2..eb05335602 100644
--- a/Source/Core/InputCommon/GCAdapter.h
+++ b/Source/Core/InputCommon/GCAdapter.h
@@ -26,8 +26,7 @@ void StartScanThread();
void StopScanThread();
GCPadStatus Input(int chan);
void Output(int chan, u8 rumble_command);
-bool IsDetected();
-bool IsDriverDetected();
+bool IsDetected(const char** error_message);
bool DeviceConnected(int chan);
void ResetDeviceType(int chan);
bool UseAdapter();