diff --git a/rpcs3/Input/hid_pad_handler.cpp b/rpcs3/Input/hid_pad_handler.cpp index 447960ce1e..9d40dc777d 100644 --- a/rpcs3/Input/hid_pad_handler.cpp +++ b/rpcs3/Input/hid_pad_handler.cpp @@ -17,8 +17,58 @@ LOG_CHANNEL(hid_log, "HID"); -static std::mutex s_hid_mutex; // hid_pad_handler is created by pad_thread and pad_settings_dialog -static u8 s_hid_instances{0}; +struct hid_instance +{ +public: + hid_instance() = default; + ~hid_instance() + { + std::lock_guard lock(m_hid_mutex); + + // Only exit HIDAPI once on exit. HIDAPI uses a global state internally... + if (m_initialized) + { + hid_log.notice("Exiting HIDAPI..."); + + if (hid_exit() != 0) + { + hid_log.error("hid_exit failed!"); + } + } + } + + static hid_instance& get_instance() + { + static hid_instance instance {}; + return instance; + } + + bool initialize() + { + std::lock_guard lock(m_hid_mutex); + + // Only init HIDAPI once. HIDAPI uses a global state internally... + if (m_initialized) + { + return true; + } + + hid_log.notice("Initializing HIDAPI ..."); + + if (hid_init() != 0) + { + hid_log.fatal("hid_init error"); + return false; + } + + m_initialized = true; + return true; + } + +private: + bool m_initialized = false; + std::mutex m_hid_mutex; +}; void HidDevice::close() { @@ -33,8 +83,6 @@ template hid_pad_handler::hid_pad_handler(pad_handler type, std::vector ids) : PadHandlerBase(type), m_ids(std::move(ids)) { - std::scoped_lock lock(s_hid_mutex); - ensure(s_hid_instances++ < 255); }; template @@ -54,17 +102,6 @@ hid_pad_handler::~hid_pad_handler() controller.second->close(); } } - - std::scoped_lock lock(s_hid_mutex); - ensure(s_hid_instances-- > 0); - if (s_hid_instances == 0) - { - // Call hid_exit after all hid_pad_handlers are finished - if (hid_exit() != 0) - { - hid_log.error("hid_exit failed!"); - } - } } template @@ -73,9 +110,8 @@ bool hid_pad_handler::Init() if (m_is_init) return true; - const int res = hid_init(); - if (res != 0) - fmt::throw_exception("%s hidapi-init error.threadproc", m_type); + if (!hid_instance::get_instance().initialize()) + return false; #if defined(__APPLE__) hid_darwin_set_open_exclusive(0); diff --git a/rpcs3/Input/sdl_pad_handler.cpp b/rpcs3/Input/sdl_pad_handler.cpp index cc3b171428..28e10e285d 100644 --- a/rpcs3/Input/sdl_pad_handler.cpp +++ b/rpcs3/Input/sdl_pad_handler.cpp @@ -23,6 +23,12 @@ public: } } + static sdl_instance& get_instance() + { + static sdl_instance instance {}; + return instance; + } + bool initialize() { // Only init SDL once. SDL uses a global state internally... @@ -256,8 +262,7 @@ bool sdl_pad_handler::Init() if (m_is_init) return true; - static sdl_instance s_sdl_instance {}; - if (!s_sdl_instance.initialize()) + if (!sdl_instance::get_instance().initialize()) return false; if (g_cfg.io.load_sdl_mappings)