Merge pull request #3805 from mathieui/gcadapter-unplug-crash
GCAdapter: improve thread safety
This commit is contained in:
commit
bb6604df76
|
@ -23,6 +23,9 @@ namespace GCAdapter
|
||||||
{
|
{
|
||||||
static bool CheckDeviceAccess(libusb_device* device);
|
static bool CheckDeviceAccess(libusb_device* device);
|
||||||
static void AddGCAdapter(libusb_device* device);
|
static void AddGCAdapter(libusb_device* device);
|
||||||
|
static void ResetRumbleLockNeeded();
|
||||||
|
static void Reset();
|
||||||
|
static void Setup();
|
||||||
|
|
||||||
static bool s_detected = false;
|
static bool s_detected = false;
|
||||||
static libusb_device_handle* s_handle = nullptr;
|
static libusb_device_handle* s_handle = nullptr;
|
||||||
|
@ -38,6 +41,7 @@ static std::atomic<int> s_controller_payload_size = {0};
|
||||||
static std::thread s_adapter_thread;
|
static std::thread s_adapter_thread;
|
||||||
static Common::Flag s_adapter_thread_running;
|
static Common::Flag s_adapter_thread_running;
|
||||||
|
|
||||||
|
static std::mutex s_init_mutex;
|
||||||
static std::thread s_adapter_detect_thread;
|
static std::thread s_adapter_detect_thread;
|
||||||
static Common::Flag s_adapter_detect_thread_running;
|
static Common::Flag s_adapter_detect_thread_running;
|
||||||
|
|
||||||
|
@ -78,8 +82,11 @@ static int HotplugCallback(libusb_context* ctx, libusb_device* dev, libusb_hotpl
|
||||||
if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)
|
if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)
|
||||||
{
|
{
|
||||||
if (s_handle == nullptr && CheckDeviceAccess(dev))
|
if (s_handle == nullptr && CheckDeviceAccess(dev))
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lk(s_init_mutex);
|
||||||
AddGCAdapter(dev);
|
AddGCAdapter(dev);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT)
|
else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT)
|
||||||
{
|
{
|
||||||
if (s_handle != nullptr && libusb_get_device(s_handle) == dev)
|
if (s_handle != nullptr && libusb_get_device(s_handle) == dev)
|
||||||
|
@ -116,6 +123,7 @@ static void ScanThreadFunc()
|
||||||
{
|
{
|
||||||
if (s_handle == nullptr)
|
if (s_handle == nullptr)
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::mutex> lk(s_init_mutex);
|
||||||
Setup();
|
Setup();
|
||||||
if (s_detected && s_detect_callback != nullptr)
|
if (s_detected && s_detect_callback != nullptr)
|
||||||
s_detect_callback();
|
s_detect_callback();
|
||||||
|
@ -178,7 +186,7 @@ void StopScanThread()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Setup()
|
static void Setup()
|
||||||
{
|
{
|
||||||
libusb_device** list;
|
libusb_device** list;
|
||||||
ssize_t cnt = libusb_get_device_list(s_libusb_context, &list);
|
ssize_t cnt = libusb_get_device_list(s_libusb_context, &list);
|
||||||
|
@ -307,7 +315,7 @@ static void AddGCAdapter(libusb_device* device)
|
||||||
s_detected = true;
|
s_detected = true;
|
||||||
if (s_detect_callback != nullptr)
|
if (s_detect_callback != nullptr)
|
||||||
s_detect_callback();
|
s_detect_callback();
|
||||||
ResetRumble();
|
ResetRumbleLockNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown()
|
void Shutdown()
|
||||||
|
@ -328,8 +336,11 @@ void Shutdown()
|
||||||
s_libusb_driver_not_supported = false;
|
s_libusb_driver_not_supported = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset()
|
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_detected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -443,10 +454,20 @@ bool UseAdapter()
|
||||||
|
|
||||||
void ResetRumble()
|
void ResetRumble()
|
||||||
{
|
{
|
||||||
if (!UseAdapter())
|
std::unique_lock<std::mutex> lock(s_init_mutex, std::defer_lock);
|
||||||
|
if (!lock.try_lock())
|
||||||
return;
|
return;
|
||||||
if (s_handle == nullptr || !s_detected)
|
ResetRumbleLockNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Needs to be called when s_init_mutex is locked in order to avoid
|
||||||
|
// being called while the libusb state is being reset
|
||||||
|
static void ResetRumbleLockNeeded()
|
||||||
|
{
|
||||||
|
if (!UseAdapter() || (s_handle == nullptr || !s_detected))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::fill(std::begin(s_controller_rumble), std::end(s_controller_rumble), 0);
|
std::fill(std::begin(s_controller_rumble), std::end(s_controller_rumble), 0);
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,7 @@ enum ControllerTypes
|
||||||
CONTROLLER_WIRELESS = 2
|
CONTROLLER_WIRELESS = 2
|
||||||
};
|
};
|
||||||
void Init();
|
void Init();
|
||||||
void Reset();
|
|
||||||
void ResetRumble();
|
void ResetRumble();
|
||||||
void Setup();
|
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
void SetAdapterCallback(std::function<void(void)> func);
|
void SetAdapterCallback(std::function<void(void)> func);
|
||||||
void StartScanThread();
|
void StartScanThread();
|
||||||
|
|
|
@ -24,6 +24,9 @@ extern JavaVM* g_java_vm;
|
||||||
|
|
||||||
namespace GCAdapter
|
namespace GCAdapter
|
||||||
{
|
{
|
||||||
|
static void Setup();
|
||||||
|
static void Reset();
|
||||||
|
|
||||||
// Java classes
|
// Java classes
|
||||||
static jclass s_adapter_class;
|
static jclass s_adapter_class;
|
||||||
|
|
||||||
|
@ -207,7 +210,7 @@ void Init()
|
||||||
StartScanThread();
|
StartScanThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Setup()
|
static void Setup()
|
||||||
{
|
{
|
||||||
s_fd = 0;
|
s_fd = 0;
|
||||||
s_detected = true;
|
s_detected = true;
|
||||||
|
@ -220,7 +223,7 @@ void Setup()
|
||||||
s_read_adapter_thread = std::thread(Read);
|
s_read_adapter_thread = std::thread(Read);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset()
|
static void Reset()
|
||||||
{
|
{
|
||||||
if (!s_detected)
|
if (!s_detected)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -9,9 +9,7 @@ namespace GCAdapter
|
||||||
{
|
{
|
||||||
|
|
||||||
void Init() {}
|
void Init() {}
|
||||||
void Reset() {}
|
|
||||||
void ResetRumble() {}
|
void ResetRumble() {}
|
||||||
void Setup() {}
|
|
||||||
void Shutdown() {}
|
void Shutdown() {}
|
||||||
void SetAdapterCallback(std::function<void(void)> func) {}
|
void SetAdapterCallback(std::function<void(void)> func) {}
|
||||||
void StartScanThread() {}
|
void StartScanThread() {}
|
||||||
|
|
Loading…
Reference in New Issue