diff --git a/rpcs3/Input/ds3_pad_handler.cpp b/rpcs3/Input/ds3_pad_handler.cpp index 8fe5628236..2bc41ccead 100644 --- a/rpcs3/Input/ds3_pad_handler.cpp +++ b/rpcs3/Input/ds3_pad_handler.cpp @@ -259,7 +259,7 @@ void ds3_pad_handler::check_add_device(hid_device* hidDevice, hid_enumerated_dev if (res <= 0 || buf[0] != 0x0) { ds3_log.error("check_add_device: hid_get_feature_report 0x0 failed! result=%d, buf[0]=0x%x, error=%s", res, buf[0], hid_error(hidDevice)); - hid_close(hidDevice); + HidDevice::close(hidDevice); return; } } @@ -270,7 +270,7 @@ void ds3_pad_handler::check_add_device(hid_device* hidDevice, hid_enumerated_dev if (res < 0) { ds3_log.error("check_add_device: hid_init_sixaxis_usb failed! (result=%d, error=%s)", res, hid_error(hidDevice)); - hid_close(hidDevice); + HidDevice::close(hidDevice); return; } #endif @@ -281,7 +281,7 @@ void ds3_pad_handler::check_add_device(hid_device* hidDevice, hid_enumerated_dev if (hid_set_nonblocking(hidDevice, 1) == -1) { ds3_log.error("check_add_device: hid_set_nonblocking failed! Reason: %s", hid_error(hidDevice)); - hid_close(hidDevice); + HidDevice::close(hidDevice); return; } diff --git a/rpcs3/Input/ds4_pad_handler.cpp b/rpcs3/Input/ds4_pad_handler.cpp index b7c1b95599..ad7e88a4b1 100644 --- a/rpcs3/Input/ds4_pad_handler.cpp +++ b/rpcs3/Input/ds4_pad_handler.cpp @@ -589,7 +589,7 @@ void ds4_pad_handler::check_add_device(hid_device* hidDevice, hid_enumerated_dev if (!devinfo) { ds4_log.error("check_add_device: hid_get_device_info failed! error=%s", hid_error(hidDevice)); - hid_close(hidDevice); + HidDevice::close(hidDevice); return; } diff --git a/rpcs3/Input/dualsense_pad_handler.cpp b/rpcs3/Input/dualsense_pad_handler.cpp index c5ba4ea6cc..63c4b6d8b6 100644 --- a/rpcs3/Input/dualsense_pad_handler.cpp +++ b/rpcs3/Input/dualsense_pad_handler.cpp @@ -134,7 +134,7 @@ void dualsense_pad_handler::check_add_device(hid_device* hidDevice, hid_enumerat if (res < 0 || buf[0] != 0x09) { dualsense_log.error("check_add_device: hid_get_feature_report 0x09 failed! result=%d, buf[0]=0x%x, error=%s", res, buf[0], hid_error(hidDevice)); - hid_close(hidDevice); + HidDevice::close(hidDevice); return; } diff --git a/rpcs3/Input/hid_pad_handler.cpp b/rpcs3/Input/hid_pad_handler.cpp index ee1c3d6c4f..8b947b6887 100644 --- a/rpcs3/Input/hid_pad_handler.cpp +++ b/rpcs3/Input/hid_pad_handler.cpp @@ -21,6 +21,8 @@ LOG_CHANNEL(hid_log, "HID"); #ifdef ANDROID std::vector g_android_usb_devices; std::mutex g_android_usb_devices_mutex; +#elif defined(__APPLE__) +std::mutex g_hid_mutex; #endif struct hid_instance @@ -91,7 +93,7 @@ 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); + std::unique_lock static_lock(g_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. @@ -108,13 +110,45 @@ hid_device* HidDevice::open() return hidDevice; } +void HidDevice::close(hid_device* dev) +{ + if (!dev) return; + +#if defined(__APPLE__) + Emu.BlockingCallFromMainThread([dev]() + { + if (dev) + { + hid_close(dev); + } + }, false); +#else + hid_close(dev); +#endif +} + void HidDevice::close() { +#if defined(__APPLE__) + if (hidDevice) + { + Emu.BlockingCallFromMainThread([this]() + { + if (hidDevice) + { + hid_close(hidDevice); + hidDevice = nullptr; + } + }, false); + } +#else if (hidDevice) { hid_close(hidDevice); hidDevice = nullptr; } +#endif + #ifdef _WIN32 if (bt_device) { @@ -124,11 +158,6 @@ void HidDevice::close() #endif } -#if defined(__APPLE__) -template -std::mutex hid_pad_handler::s_hid_mutex; -#endif - template hid_pad_handler::hid_pad_handler(pad_handler type, std::vector ids) : PadHandlerBase(type), m_ids(std::move(ids)) @@ -142,7 +171,7 @@ hid_pad_handler::~hid_pad_handler() m_enumeration_thread.reset(); #if defined(__APPLE__) - std::lock_guard static_lock(s_hid_mutex); + std::lock_guard static_lock(g_hid_mutex); #endif for (auto& controller : m_controllers) @@ -241,7 +270,7 @@ void hid_pad_handler::enumerate_devices() { #if defined(__APPLE__) // Let's make sure hid_enumerate is only done one thread at a time - std::lock_guard static_lock(s_hid_mutex); + std::lock_guard static_lock(g_hid_mutex); Emu.BlockingCallFromMainThread([&]() { #endif @@ -317,7 +346,7 @@ void hid_pad_handler::update_devices() } #if defined(__APPLE__) - std::lock_guard static_lock(s_hid_mutex); + std::lock_guard static_lock(g_hid_mutex); #endif // Scrap devices that are not in the new list diff --git a/rpcs3/Input/hid_pad_handler.h b/rpcs3/Input/hid_pad_handler.h index e495a6c29a..544ba21eb5 100644 --- a/rpcs3/Input/hid_pad_handler.h +++ b/rpcs3/Input/hid_pad_handler.h @@ -57,6 +57,7 @@ class HidDevice : public PadDevice { public: hid_device* open(); + static void close(hid_device* dev); void close(); hid_device* hidDevice{nullptr}; @@ -110,10 +111,6 @@ protected: std::mutex m_enumeration_mutex; std::unique_ptr>> m_enumeration_thread; -#if defined(__APPLE__) - static std::mutex s_hid_mutex; -#endif - void enumerate_devices(); void update_devices(); std::shared_ptr get_hid_device(const std::string& padId); diff --git a/rpcs3/Input/ps_move_handler.cpp b/rpcs3/Input/ps_move_handler.cpp index 8963b891a4..d5c87f7a21 100644 --- a/rpcs3/Input/ps_move_handler.cpp +++ b/rpcs3/Input/ps_move_handler.cpp @@ -303,7 +303,7 @@ void ps_move_handler::check_add_device(hid_device* hidDevice, hid_enumerated_dev if (hid_set_nonblocking(hidDevice, 1) == -1) { move_log.error("check_add_device: hid_set_nonblocking failed! Reason: %s", hid_error(hidDevice)); - hid_close(hidDevice); + HidDevice::close(hidDevice); return; } #endif diff --git a/rpcs3/Input/skateboard_pad_handler.cpp b/rpcs3/Input/skateboard_pad_handler.cpp index 124706b6de..fdcc5be727 100644 --- a/rpcs3/Input/skateboard_pad_handler.cpp +++ b/rpcs3/Input/skateboard_pad_handler.cpp @@ -177,7 +177,7 @@ void skateboard_pad_handler::check_add_device(hid_device* hidDevice, hid_enumera if (hid_set_nonblocking(hidDevice, 1) == -1) { skateboard_log.error("check_add_device: hid_set_nonblocking failed! Reason: %s", hid_error(hidDevice)); - hid_close(hidDevice); + HidDevice::close(hidDevice); return; }