Compare commits

...

5 commits

Author SHA1 Message Date
Megamouse
866daf2059 input/macOs: Call hid_close on the main thread
Some checks failed
Generate Translation Template / Generate Translation Template (push) Failing after 2m42s
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Has been skipped
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Has been skipped
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Has been cancelled
Build RPCS3 / RPCS3 Mac Intel (push) Has been cancelled
Build RPCS3 / RPCS3 Mac Apple Silicon (push) Has been cancelled
Build RPCS3 / RPCS3 Windows (push) Has been cancelled
2025-06-07 13:03:41 +02:00
Megamouse
ae38cef7b1 input/macOs: Call hid_open_path on the main thread 2025-06-07 13:03:41 +02:00
Megamouse
e36f55ea41 input/macOs: call hid_enumerate on the main thread 2025-06-07 13:03:41 +02:00
Megamouse
819d3dc7a6 input/macOs: Run hidapi pad handlers on a single thread 2025-06-07 13:03:41 +02:00
oltolm
ac99b2036d llvm: fix deprecation warnings 2025-06-07 12:46:48 +03:00
12 changed files with 204 additions and 90 deletions

View file

@ -434,7 +434,7 @@ struct llvm_value_t<T*> : llvm_value_t<T>
static llvm::Type* get_type(llvm::LLVMContext& context)
{
return llvm_value_t<T>::get_type(context)->getPointerTo();
return llvm::PointerType::getUnqual(context);
}
};

View file

@ -5760,7 +5760,7 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module<lv2_obj>& module
// Define some types
const auto _func = FunctionType::get(translator.get_type<void>(), {
translator.get_type<u8*>(), // Exec base
translator.GetContextType()->getPointerTo(), // PPU context
translator.get_type<u8*>(), // PPU context
translator.get_type<u64>(), // Segment address (for PRX)
translator.get_type<u8*>(), // Memory base
translator.get_type<u64>(), // r0

View file

@ -340,7 +340,7 @@ Function* PPUTranslator::GetSymbolResolver(const ppu_module<lv2_obj>& info)
const auto ftype = FunctionType::get(get_type<void>(), {
get_type<u8*>(), // Exec base
GetContextType()->getPointerTo(), // PPU context
m_ir->getPtrTy(), // PPU context
get_type<u64>(), // Segment address (for PRX)
get_type<u8*>(), // Memory base
get_type<u64>(), // r0
@ -380,7 +380,7 @@ Function* PPUTranslator::GetSymbolResolver(const ppu_module<lv2_obj>& info)
const auto addr_array = new GlobalVariable(*m_module, addr_array_type, false, GlobalValue::PrivateLinkage, ConstantDataArray::get(m_context, vec_addrs));
// Create an array of function pointers
const auto func_table_type = ArrayType::get(ftype->getPointerTo(), functions.size());
const auto func_table_type = ArrayType::get(m_ir->getPtrTy(), functions.size());
const auto init_func_table = ConstantArray::get(func_table_type, functions);
const auto func_table = new GlobalVariable(*m_module, func_table_type, false, GlobalVariable::PrivateLinkage, init_func_table);
@ -407,7 +407,7 @@ Function* PPUTranslator::GetSymbolResolver(const ppu_module<lv2_obj>& info)
const auto func_pc = ZExt(m_ir->CreateLoad(ptr_inst->getResultElementType(), ptr_inst), get_type<u64>());
ptr_inst = dyn_cast<GetElementPtrInst>(m_ir->CreateGEP(func_table->getValueType(), func_table, {m_ir->getInt64(0), index_value}));
assert(ptr_inst->getResultElementType() == ftype->getPointerTo());
assert(ptr_inst->getResultElementType() == m_ir->getPtrTy());
const auto faddr = m_ir->CreateLoad(ptr_inst->getResultElementType(), ptr_inst);
const auto faddr_int = m_ir->CreatePtrToInt(faddr, get_type<uptr>());
@ -612,7 +612,7 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect)
const auto pos = m_ir->CreateShl(indirect, 1);
const auto ptr = dyn_cast<GetElementPtrInst>(m_ir->CreateGEP(get_type<u8>(), m_exec, pos));
const auto val = m_ir->CreateLoad(get_type<u64>(), ptr);
callee = FunctionCallee(type, m_ir->CreateIntToPtr(val, type->getPointerTo()));
callee = FunctionCallee(type, m_ir->CreateIntToPtr(val, m_ir->getPtrTy()));
// Load new segment address
const auto seg_base_ptr = m_ir->CreateIntToPtr(m_ir->CreateAdd(
@ -2794,8 +2794,8 @@ void PPUTranslator::MFOCRF(ppu_opcode_t op)
else if (std::none_of(m_cr + 0, m_cr + 32, [](auto* p) { return p; }))
{
// MFCR (optimized)
Value* ln0 = m_ir->CreateIntToPtr(m_ir->CreatePtrToInt(m_ir->CreateStructGEP(m_thread_type, m_thread, 99), GetType<uptr>()), GetType<u8[16]>()->getPointerTo());
Value* ln1 = m_ir->CreateIntToPtr(m_ir->CreatePtrToInt(m_ir->CreateStructGEP(m_thread_type, m_thread, 115), GetType<uptr>()), GetType<u8[16]>()->getPointerTo());
Value* ln0 = m_ir->CreateIntToPtr(m_ir->CreatePtrToInt(m_ir->CreateStructGEP(m_thread_type, m_thread, 99), GetType<uptr>()), m_ir->getPtrTy());
Value* ln1 = m_ir->CreateIntToPtr(m_ir->CreatePtrToInt(m_ir->CreateStructGEP(m_thread_type, m_thread, 115), GetType<uptr>()), m_ir->getPtrTy());
ln0 = m_ir->CreateLoad(GetType<u8[16]>(), ln0);
ln1 = m_ir->CreateLoad(GetType<u8[16]>(), ln1);
@ -5384,7 +5384,7 @@ MDNode* PPUTranslator::CheckBranchProbability(u32 bo)
void PPUTranslator::build_interpreter()
{
#define BUILD_VEC_INST(i) { \
m_function = llvm::cast<llvm::Function>(m_module->getOrInsertFunction("op_" #i, get_type<void>(), m_thread_type->getPointerTo()).getCallee()); \
m_function = llvm::cast<llvm::Function>(m_module->getOrInsertFunction("op_" #i, get_type<void>(), m_ir->getPtrTy()).getCallee()); \
std::fill(std::begin(m_globals), std::end(m_globals), nullptr); \
std::fill(std::begin(m_locals), std::end(m_locals), nullptr); \
IRBuilder<> irb(BasicBlock::Create(m_context, "__entry", m_function)); \

View file

@ -2886,7 +2886,7 @@ public:
// Create interpreter table
const auto if_type = get_ftype<void, u8*, u8*, u32, u32, u8*, u32, u8*>();
m_function_table = new GlobalVariable(*m_module, ArrayType::get(if_type->getPointerTo(), 1ull << m_interp_magn), true, GlobalValue::InternalLinkage, nullptr);
m_function_table = new GlobalVariable(*m_module, ArrayType::get(m_ir->getPtrTy(), 1ull << m_interp_magn), true, GlobalValue::InternalLinkage, nullptr);
init_luts();
@ -2930,7 +2930,7 @@ public:
m_ir->CreateStore(m_ir->CreateCall(get_intrinsic<u64>(Intrinsic::read_register), {rsp_name}), native_sp);
// Decode (shift) and load function pointer
const auto first = m_ir->CreateLoad(if_type->getPointerTo(), m_ir->CreateGEP(if_type->getPointerTo(), m_interp_table, m_ir->CreateLShr(m_interp_op, 32u - m_interp_magn)));
const auto first = m_ir->CreateLoad(m_ir->getPtrTy(), m_ir->CreateGEP(m_ir->getPtrTy(), m_interp_table, m_ir->CreateLShr(m_interp_op, 32u - m_interp_magn)));
const auto call0 = m_ir->CreateCall(if_type, first, {m_lsptr, m_thread, m_interp_pc, m_interp_op, m_interp_table, m_interp_7f0, m_interp_regs});
call0->setCallingConv(CallingConv::GHC);
m_ir->CreateRetVoid();
@ -3074,7 +3074,7 @@ public:
const auto next_pc = itype & spu_itype::branch ? m_interp_pc : m_interp_pc_next;
const auto be32_op = m_ir->CreateLoad(get_type<u32>(), m_ir->CreateGEP(get_type<u8>(), m_lsptr, m_ir->CreateZExt(next_pc, get_type<u64>())));
const auto next_op = m_ir->CreateCall(get_intrinsic<u32>(Intrinsic::bswap), {be32_op});
const auto next_if = m_ir->CreateLoad(if_type->getPointerTo(), m_ir->CreateGEP(if_type->getPointerTo(), m_interp_table, m_ir->CreateLShr(next_op, 32u - m_interp_magn)));
const auto next_if = m_ir->CreateLoad(m_ir->getPtrTy(), m_ir->CreateGEP(m_ir->getPtrTy(), m_interp_table, m_ir->CreateLShr(next_op, 32u - m_interp_magn)));
llvm::cast<LoadInst>(next_if)->setVolatile(true);
if (!(itype & spu_itype::branch))
@ -3199,7 +3199,7 @@ public:
}
}
m_function_table->setInitializer(ConstantArray::get(ArrayType::get(if_type->getPointerTo(), 1ull << m_interp_magn), iptrs));
m_function_table->setInitializer(ConstantArray::get(ArrayType::get(m_ir->getPtrTy(), 1ull << m_interp_magn), iptrs));
m_function_table = nullptr;
for (auto& f : *_module)
@ -7808,7 +7808,7 @@ public:
m_ir->CreateStore(splat<u64[2]>(-1).eval(m_ir), m_ir->CreateGEP(get_type<u8>(), m_thread, stack0.value));
const auto targ = m_ir->CreateAdd(m_ir->CreateLShr(_ret, 32), get_segment_base());
const auto type = m_finfo->chunk->getFunctionType();
const auto fval = m_ir->CreateIntToPtr(targ, type->getPointerTo());
const auto fval = m_ir->CreateIntToPtr(targ, m_ir->getPtrTy());
tail_chunk({type, fval}, m_ir->CreateTrunc(m_ir->CreateLShr(link, 32), get_type<u32>()));
m_ir->SetInsertPoint(fail);
}

View file

@ -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;
}
@ -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
{

View file

@ -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;
}
@ -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);

View file

@ -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;
}
@ -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);

View file

@ -21,6 +21,8 @@ LOG_CHANNEL(hid_log, "HID");
#ifdef ANDROID
std::vector<android_usb_device> g_android_usb_devices;
std::mutex g_android_usb_devices_mutex;
#elif defined(__APPLE__)
std::mutex g_hid_mutex;
#endif
struct hid_instance
@ -61,9 +63,19 @@ public:
hid_log.notice("Initializing HIDAPI ...");
if (int errorCode = hid_init(); errorCode != 0)
#if defined(__APPLE__)
int error_code = 0;
Emu.BlockingCallFromMainThread([&error_code]()
{
hid_log.fatal("hid_init error %d: %s", errorCode, hid_error(nullptr));
error_code = hid_init();
hid_darwin_set_open_exclusive(0);
}, false);
#else
const int error_code = hid_init();
#endif
if (error_code != 0)
{
hid_log.fatal("hid_init error %d: %s", error_code, hid_error(nullptr));
return false;
}
@ -76,13 +88,67 @@ 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(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.
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(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)
{
@ -104,6 +170,10 @@ hid_pad_handler<Device>::~hid_pad_handler()
// Join thread
m_enumeration_thread.reset();
#if defined(__APPLE__)
std::lock_guard static_lock(g_hid_mutex);
#endif
for (auto& controller : m_controllers)
{
if (controller.second)
@ -122,10 +192,6 @@ bool hid_pad_handler<Device>::Init()
if (!hid_instance::get_instance().initialize())
return false;
#if defined(__APPLE__)
hid_darwin_set_open_exclusive(0);
#endif
for (usz i = 1; i <= MAX_GAMEPADS; i++) // Controllers 1-n in GUI
{
m_controllers.emplace(m_name_string + std::to_string(i), std::make_shared<Device>());
@ -186,9 +252,9 @@ void hid_pad_handler<Device>::enumerate_devices()
#ifdef ANDROID
{
std::lock_guard lock(g_android_usb_devices_mutex);
for (auto device : g_android_usb_devices)
for (const android_usb_device& device : g_android_usb_devices)
{
auto filter = [&](id_pair id)
const auto filter = [&](id_pair id)
{
return id.m_vid == device.vendorId && id.m_pid == device.productId;
};
@ -202,9 +268,14 @@ void hid_pad_handler<Device>::enumerate_devices()
#else
for (const auto& [vid, pid] : m_ids)
{
hid_device_info* dev_info = hid_enumerate(vid, pid);
hid_device_info* head = dev_info;
while (dev_info)
#if defined(__APPLE__)
// Let's make sure hid_enumerate is only done one thread at a time
std::lock_guard static_lock(g_hid_mutex);
Emu.BlockingCallFromMainThread([&]()
{
#endif
hid_device_info* head = hid_enumerate(vid, pid);
for (hid_device_info* dev_info = head; dev_info != nullptr; dev_info = dev_info->next)
{
if (!dev_info->path)
{
@ -212,7 +283,7 @@ void hid_pad_handler<Device>::enumerate_devices()
continue;
}
const std::string path = dev_info->path;
std::string path = dev_info->path;
device_paths.insert(path);
#ifdef _WIN32
@ -220,20 +291,17 @@ void hid_pad_handler<Device>::enumerate_devices()
if (m_type == pad_handler::move && path.find("&Col01#") != umax)
#endif
{
serials[path] = dev_info->serial_number ? std::wstring(dev_info->serial_number) : std::wstring();
serials[std::move(path)] = dev_info->serial_number ? std::wstring(dev_info->serial_number) : std::wstring();
}
dev_info = dev_info->next;
}
hid_free_enumeration(head);
#if defined(__APPLE__)
}, false);
#endif
}
#endif
hid_log.notice("%s enumeration found %d devices (%f ms)", m_type, device_paths.size(), timer.GetElapsedTimeInMilliSec());
std::lock_guard lock(m_enumeration_mutex);
m_new_enumerated_devices = device_paths;
m_enumerated_serials = std::move(serials);
#ifdef _WIN32
if (m_type == pad_handler::move)
{
@ -243,7 +311,7 @@ void hid_pad_handler<Device>::enumerate_devices()
// Filter paths. We only want the Col01 paths.
std::set<std::string> col01_paths;
for (const std::string& path : m_new_enumerated_devices)
for (const std::string& path : device_paths)
{
hid_log.trace("Found ps move device: %s", path);
@ -253,27 +321,38 @@ void hid_pad_handler<Device>::enumerate_devices()
}
}
m_new_enumerated_devices = std::move(col01_paths);
device_paths = std::move(col01_paths);
}
#endif
std::lock_guard lock(m_enumeration_mutex);
m_new_enumerated_devices = std::move(device_paths);
m_new_enumerated_serials = std::move(serials);
}
template <class Device>
void hid_pad_handler<Device>::update_devices()
{
std::lock_guard lock(m_enumeration_mutex);
if (m_last_enumerated_devices == m_new_enumerated_devices)
{
return;
std::lock_guard lock(m_enumeration_mutex);
if (m_enumerated_devices == m_new_enumerated_devices)
{
return;
}
m_enumerated_devices = std::move(m_new_enumerated_devices);
m_enumerated_serials = std::move(m_new_enumerated_serials);
}
m_last_enumerated_devices = m_new_enumerated_devices;
#if defined(__APPLE__)
std::lock_guard static_lock(g_hid_mutex);
#endif
// Scrap devices that are not in the new list
for (auto& controller : m_controllers)
{
if (controller.second && controller.second->path != hid_enumerated_device_default && !m_new_enumerated_devices.contains(controller.second->path))
if (controller.second && controller.second->path != hid_enumerated_device_default && !m_enumerated_devices.contains(controller.second->path))
{
controller.second->close();
cfg_pad* config = controller.second->config;
@ -285,7 +364,7 @@ void hid_pad_handler<Device>::update_devices()
bool warn_about_drivers = false;
// Find and add new devices
for (const auto& path : m_new_enumerated_devices)
for (const auto& path : m_enumerated_devices)
{
// Check if we have at least one virtual controller left
if (std::none_of(m_controllers.cbegin(), m_controllers.cend(), [](const auto& c) { return !c.second || !c.second->hidDevice; }))
@ -305,6 +384,13 @@ void hid_pad_handler<Device>::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

View file

@ -56,6 +56,8 @@ enum CalibIndex
class HidDevice : public PadDevice
{
public:
hid_device* open();
static void close(hid_device* dev);
void close();
hid_device* hidDevice{nullptr};
@ -102,9 +104,10 @@ protected:
// pseudo 'controller id' to keep track of unique controllers
std::map<std::string, std::shared_ptr<Device>> m_controllers;
std::set<hid_enumerated_device_type> m_last_enumerated_devices;
std::set<hid_enumerated_device_type> m_enumerated_devices;
std::set<hid_enumerated_device_type> m_new_enumerated_devices;
std::map<hid_enumerated_device_type, std::wstring> m_enumerated_serials;
std::map<hid_enumerated_device_type, std::wstring> m_new_enumerated_serials;
std::mutex m_enumeration_mutex;
std::unique_ptr<named_thread<std::function<void()>>> m_enumeration_thread;

View file

@ -443,14 +443,67 @@ void pad_thread::operator()()
input_log.notice("Starting pad threads...");
for (const auto& handler : m_handlers)
{
if (handler.first == pad_handler::null)
{
continue;
}
#if defined(__APPLE__)
// Let's keep hid handlers on the same thread
std::vector<std::shared_ptr<PadHandlerBase>> hid_handlers;
std::vector<std::shared_ptr<PadHandlerBase>> handlers;
threads.push_back(std::make_unique<named_thread<std::function<void()>>>(fmt::format("%s Thread", handler.second->m_type), [&handler = handler.second, &pad_mode]()
for (const auto& [type, handler] : m_handlers)
{
switch (type)
{
case pad_handler::null:
break;
case pad_handler::ds3:
case pad_handler::ds4:
case pad_handler::dualsense:
case pad_handler::skateboard:
case pad_handler::move:
hid_handlers.push_back(handler);
break;
default:
handlers.push_back(handler);
break;
}
}
if (!hid_handlers.empty())
{
threads.push_back(std::make_unique<named_thread<std::function<void()>>>("HID Thread", [handlers = std::move(hid_handlers)]()
{
while (thread_ctrl::state() != thread_state::aborting)
{
if (!pad::g_enabled || !is_input_allowed())
{
thread_ctrl::wait_for(30'000);
continue;
}
for (auto& handler : handlers)
{
handler->process();
}
u64 pad_sleep = g_cfg.io.pad_sleep;
if (Emu.IsPaused())
{
pad_sleep = std::max<u64>(pad_sleep, 30'000);
}
thread_ctrl::wait_for(pad_sleep);
}
}));
}
for (const auto& handler : handlers)
{
#else
for (const auto& [type, handler] : m_handlers)
{
if (type == pad_handler::null) continue;
#endif
threads.push_back(std::make_unique<named_thread<std::function<void()>>>(fmt::format("%s Thread", handler->m_type), [handler]()
{
while (thread_ctrl::state() != thread_state::aborting)
{

View file

@ -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
@ -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

View file

@ -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;
}
@ -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;
}
}