From ae38cef7b1ac0956acdf90974f47ff93948ffca6 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sat, 7 Jun 2025 10:29:55 +0200 Subject: [PATCH] input/macOs: Call hid_open_path on the main thread --- rpcs3/Input/ds3_pad_handler.cpp | 7 +----- rpcs3/Input/ds4_pad_handler.cpp | 8 +------ rpcs3/Input/dualsense_pad_handler.cpp | 8 +------ rpcs3/Input/hid_pad_handler.cpp | 33 ++++++++++++++++++++++++-- rpcs3/Input/hid_pad_handler.h | 1 + rpcs3/Input/ps_move_handler.cpp | 7 +----- rpcs3/Input/skateboard_pad_handler.cpp | 8 +------ 7 files changed, 37 insertions(+), 35 deletions(-) diff --git a/rpcs3/Input/ds3_pad_handler.cpp b/rpcs3/Input/ds3_pad_handler.cpp index 9e12bbd472..8fe5628236 100644 --- a/rpcs3/Input/ds3_pad_handler.cpp +++ b/rpcs3/Input/ds3_pad_handler.cpp @@ -513,17 +513,12 @@ PadHandlerBase::connection ds3_pad_handler::update_connection(const std::shared_ if (dev->hidDevice == nullptr) { -#ifdef ANDROID - if (hid_device* hid_dev = hid_libusb_wrap_sys_device(dev->path, -1)) -#else - if (hid_device* hid_dev = hid_open_path(dev->path.c_str())) -#endif + if (hid_device* hid_dev = dev->open()) { if (hid_set_nonblocking(hid_dev, 1) == -1) { ds3_log.error("Reconnecting Device %s: hid_set_nonblocking failed with error %s", dev->path, hid_error(hid_dev)); } - dev->hidDevice = hid_dev; } else { diff --git a/rpcs3/Input/ds4_pad_handler.cpp b/rpcs3/Input/ds4_pad_handler.cpp index 3ab7edc648..b7c1b95599 100644 --- a/rpcs3/Input/ds4_pad_handler.cpp +++ b/rpcs3/Input/ds4_pad_handler.cpp @@ -837,19 +837,13 @@ PadHandlerBase::connection ds4_pad_handler::update_connection(const std::shared_ if (dev->hidDevice == nullptr) { // try to reconnect -#ifdef ANDROID - if (hid_device* hid_dev = hid_libusb_wrap_sys_device(dev->path, -1)) -#else - if (hid_device* hid_dev = hid_open_path(dev->path.c_str())) -#endif + if (hid_device* hid_dev = dev->open()) { if (hid_set_nonblocking(hid_dev, 1) == -1) { ds4_log.error("Reconnecting Device %s: hid_set_nonblocking failed with error %s", dev->path, hid_error(hid_dev)); } - dev->hidDevice = hid_dev; - if (!dev->has_calib_data) { dev->has_calib_data = GetCalibrationData(dev); diff --git a/rpcs3/Input/dualsense_pad_handler.cpp b/rpcs3/Input/dualsense_pad_handler.cpp index 794c0bf4e7..c5ba4ea6cc 100644 --- a/rpcs3/Input/dualsense_pad_handler.cpp +++ b/rpcs3/Input/dualsense_pad_handler.cpp @@ -568,19 +568,13 @@ PadHandlerBase::connection dualsense_pad_handler::update_connection(const std::s if (dev->hidDevice == nullptr) { // try to reconnect -#ifdef ANDROID - if (hid_device* hid_dev = hid_libusb_wrap_sys_device(dev->path, -1)) -#else - if (hid_device* hid_dev = hid_open_path(dev->path.c_str())) -#endif + if (hid_device* hid_dev = dev->open()) { if (hid_set_nonblocking(hid_dev, 1) == -1) { dualsense_log.error("Reconnecting Device %s: hid_set_nonblocking failed with error %s", dev->path, hid_error(hid_dev)); } - dev->hidDevice = hid_dev; - if (!dev->has_calib_data) { dev->has_calib_data = get_calibration_data(dev); diff --git a/rpcs3/Input/hid_pad_handler.cpp b/rpcs3/Input/hid_pad_handler.cpp index 6f63ad008a..ee1c3d6c4f 100644 --- a/rpcs3/Input/hid_pad_handler.cpp +++ b/rpcs3/Input/hid_pad_handler.cpp @@ -67,7 +67,7 @@ public: { error_code = hid_init(); hid_darwin_set_open_exclusive(0); - }); + }, false); #else const int error_code = hid_init(); #endif @@ -86,6 +86,28 @@ private: std::mutex m_hid_mutex; }; +hid_device* HidDevice::open() +{ +#ifdef ANDROID + hidDevice = hid_libusb_wrap_sys_device(path, -1); +#elif defined(__APPLE__) + std::unique_lock static_lock(s_hid_mutex, std::defer_lock); + if (!static_lock.try_lock()) + { + // The enumeration thread is busy. If we lock and open the device, we might get input stutter on other devices. + return nullptr; + } + Emu.BlockingCallFromMainThread([this]() + { + hidDevice = hid_open_path(path.c_str()); + }, false); +#else + hidDevice = hid_open_path(path.data()); +#endif + + return hidDevice; +} + void HidDevice::close() { if (hidDevice) @@ -245,7 +267,7 @@ void hid_pad_handler::enumerate_devices() } hid_free_enumeration(head); #if defined(__APPLE__) - }); + }, false); #endif } #endif @@ -333,6 +355,13 @@ void hid_pad_handler::update_devices() #ifdef ANDROID if (hid_device* dev = hid_libusb_wrap_sys_device(path, -1)) +#elif defined(__APPLE__) + hid_device* dev = nullptr; + Emu.BlockingCallFromMainThread([&]() + { + dev = hid_open_path(path.c_str()); + }, false); + if (dev) #else if (hid_device* dev = hid_open_path(path.c_str())) #endif diff --git a/rpcs3/Input/hid_pad_handler.h b/rpcs3/Input/hid_pad_handler.h index 0bdfec1f6a..e495a6c29a 100644 --- a/rpcs3/Input/hid_pad_handler.h +++ b/rpcs3/Input/hid_pad_handler.h @@ -56,6 +56,7 @@ enum CalibIndex class HidDevice : public PadDevice { public: + hid_device* open(); void close(); hid_device* hidDevice{nullptr}; diff --git a/rpcs3/Input/ps_move_handler.cpp b/rpcs3/Input/ps_move_handler.cpp index 7eb74d3e96..8963b891a4 100644 --- a/rpcs3/Input/ps_move_handler.cpp +++ b/rpcs3/Input/ps_move_handler.cpp @@ -434,17 +434,12 @@ PadHandlerBase::connection ps_move_handler::update_connection(const std::shared_ move_device->hidDevice = dev; } #else -#ifdef ANDROID - if (hid_device* dev = hid_libusb_wrap_sys_device(move_device->path, -1)) -#else - if (hid_device* dev = hid_open_path(move_device->path.c_str())) -#endif + if (hid_device* dev = move_device->open()) { if (hid_set_nonblocking(dev, 1) == -1) { move_log.error("Reconnecting Device %s: hid_set_nonblocking failed with error %s", move_device->path, hid_error(dev)); } - move_device->hidDevice = dev; } #endif else diff --git a/rpcs3/Input/skateboard_pad_handler.cpp b/rpcs3/Input/skateboard_pad_handler.cpp index c9194adc24..124706b6de 100644 --- a/rpcs3/Input/skateboard_pad_handler.cpp +++ b/rpcs3/Input/skateboard_pad_handler.cpp @@ -239,22 +239,16 @@ PadHandlerBase::connection skateboard_pad_handler::update_connection(const std:: if (dev->hidDevice == nullptr) { // try to reconnect -#ifdef ANDROID - if (hid_device* hid_dev = hid_libusb_wrap_sys_device(dev->path, -1)) -#else - if (hid_device* hid_dev = hid_open_path(dev->path.c_str())) -#endif + if (hid_device* hid_dev = dev->open()) { if (hid_set_nonblocking(hid_dev, 1) == -1) { skateboard_log.error("Reconnecting Device %s: hid_set_nonblocking failed with error %s", dev->path, hid_error(hid_dev)); } - dev->hidDevice = hid_dev; } else { // nope, not there - skateboard_log.error("Device %s: disconnected", dev->path); return connection::disconnected; } }