mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-02 21:11:25 +12:00
Compare commits
5 commits
46cce45b13
...
866daf2059
Author | SHA1 | Date | |
---|---|---|---|
|
866daf2059 | ||
|
ae38cef7b1 | ||
|
e36f55ea41 | ||
|
819d3dc7a6 | ||
|
ac99b2036d |
12 changed files with 204 additions and 90 deletions
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)); \
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue