mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-03-10 19:47:40 +01:00
ControllerInterface: make evdev use PlatformPopulateDevices
Also fix evdev non thread safe acces to static variables
This commit is contained in:
parent
2aa941081e
commit
0718cfd7d7
@ -202,6 +202,9 @@ static int s_wakeup_eventfd;
|
|||||||
// There is no easy way to get the device name from only a dev node
|
// There is no easy way to get the device name from only a dev node
|
||||||
// during a device removed event, since libevdev can't work on removed devices;
|
// during a device removed event, since libevdev can't work on removed devices;
|
||||||
// sysfs is not stable, so this is probably the easiest way to get a name for a node.
|
// sysfs is not stable, so this is probably the easiest way to get a name for a node.
|
||||||
|
// This can, and will be modified by different thread, possibly concurrently,
|
||||||
|
// as devices can be destroyed by any thread at any time. As of now it's protected
|
||||||
|
// by ControllerInterface::m_devices_population_mutex.
|
||||||
static std::map<std::string, std::weak_ptr<evdevDevice>> s_devnode_objects;
|
static std::map<std::string, std::weak_ptr<evdevDevice>> s_devnode_objects;
|
||||||
|
|
||||||
static std::shared_ptr<evdevDevice>
|
static std::shared_ptr<evdevDevice>
|
||||||
@ -260,9 +263,13 @@ static void AddDeviceNode(const char* devnode)
|
|||||||
|
|
||||||
// Remove and re-add device as naming and inputs may have changed.
|
// Remove and re-add device as naming and inputs may have changed.
|
||||||
// This will also give it the correct index and invoke device change callbacks.
|
// This will also give it the correct index and invoke device change callbacks.
|
||||||
g_controller_interface.RemoveDevice([&evdev_device](const auto* device) {
|
// Make sure to force the device removal immediately (as they are shared ptrs and
|
||||||
return static_cast<const evdevDevice*>(device) == evdev_device.get();
|
// they could be kept alive, preventing us from re-creating the device)
|
||||||
});
|
g_controller_interface.RemoveDevice(
|
||||||
|
[&evdev_device](const auto* device) {
|
||||||
|
return static_cast<const evdevDevice*>(device) == evdev_device.get();
|
||||||
|
},
|
||||||
|
true);
|
||||||
|
|
||||||
g_controller_interface.AddDevice(evdev_device);
|
g_controller_interface.AddDevice(evdev_device);
|
||||||
}
|
}
|
||||||
@ -276,6 +283,8 @@ static void AddDeviceNode(const char* devnode)
|
|||||||
g_controller_interface.AddDevice(evdev_device);
|
g_controller_interface.AddDevice(evdev_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the devices failed to be added to g_controller_interface, it will be added here but then
|
||||||
|
// immediately removed in its destructor due to the shared ptr not having any references left
|
||||||
s_devnode_objects.emplace(devnode, std::move(evdev_device));
|
s_devnode_objects.emplace(devnode, std::move(evdev_device));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,23 +327,30 @@ static void HotplugThreadFunc()
|
|||||||
if (!devnode)
|
if (!devnode)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Use g_controller_interface.PlatformPopulateDevices() to protect access around
|
||||||
|
// s_devnode_objects. Note that even if we get these events at the same time as a
|
||||||
|
// a PopulateDevices() request (e.g. on start up, we might get all the add events
|
||||||
|
// for connected devices), this won't ever cause duplicate devices as AddDeviceNode()
|
||||||
|
// automatically removes the old one if it already existed
|
||||||
if (strcmp(action, "remove") == 0)
|
if (strcmp(action, "remove") == 0)
|
||||||
{
|
{
|
||||||
std::shared_ptr<evdevDevice> ptr;
|
g_controller_interface.PlatformPopulateDevices([&devnode] {
|
||||||
|
std::shared_ptr<evdevDevice> ptr;
|
||||||
|
|
||||||
const auto it = s_devnode_objects.find(devnode);
|
const auto it = s_devnode_objects.find(devnode);
|
||||||
if (it != s_devnode_objects.end())
|
if (it != s_devnode_objects.end())
|
||||||
ptr = it->second.lock();
|
ptr = it->second.lock();
|
||||||
|
|
||||||
// If we don't recognize this device, ptr will be null and no device will be removed.
|
// If we don't recognize this device, ptr will be null and no device will be removed.
|
||||||
|
|
||||||
g_controller_interface.RemoveDevice([&ptr](const auto* device) {
|
g_controller_interface.RemoveDevice([&ptr](const auto* device) {
|
||||||
return static_cast<const evdevDevice*>(device) == ptr.get();
|
return static_cast<const evdevDevice*>(device) == ptr.get();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (strcmp(action, "add") == 0)
|
else if (strcmp(action, "add") == 0)
|
||||||
{
|
{
|
||||||
AddDeviceNode(devnode);
|
g_controller_interface.PlatformPopulateDevices([&devnode] { AddDeviceNode(devnode); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NOTICE_LOG_FMT(CONTROLLERINTERFACE, "evdev hotplug thread stopped");
|
NOTICE_LOG_FMT(CONTROLLERINTERFACE, "evdev hotplug thread stopped");
|
||||||
@ -376,8 +392,15 @@ void Init()
|
|||||||
StartHotplugThread();
|
StartHotplugThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only call this when ControllerInterface::m_devices_population_mutex is locked
|
||||||
void PopulateDevices()
|
void PopulateDevices()
|
||||||
{
|
{
|
||||||
|
// Don't run if we are not initialized
|
||||||
|
if (!s_hotplug_thread_running.IsSet())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// We use udev to iterate over all /dev/input/event* devices.
|
// We use udev to iterate over all /dev/input/event* devices.
|
||||||
// Note: the Linux kernel is currently limited to just 32 event devices. If
|
// Note: the Linux kernel is currently limited to just 32 event devices. If
|
||||||
// this ever changes, hopefully udev will take care of this.
|
// this ever changes, hopefully udev will take care of this.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user