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.
This commit is contained in:
parent
0165e5e703
commit
b08e2ec959
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue