mirror of
https://github.com/SFML/SFML.git
synced 2024-11-24 20:31:05 +08:00
Modernize management of Udev pointers
This commit is contained in:
parent
f911d01e01
commit
ee036b064c
@ -32,6 +32,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <libudev.h>
|
||||
#include <linux/joystick.h>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <poll.h>
|
||||
#include <string>
|
||||
@ -43,8 +44,34 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
udev* udevContext = nullptr;
|
||||
udev_monitor* udevMonitor = nullptr;
|
||||
struct UdevDeleter
|
||||
{
|
||||
void operator()(udev_device* device) const
|
||||
{
|
||||
udev_device_unref(device);
|
||||
}
|
||||
|
||||
void operator()(udev_monitor* monitor) const
|
||||
{
|
||||
udev_monitor_unref(monitor);
|
||||
}
|
||||
|
||||
void operator()(udev_enumerate* enumerate) const
|
||||
{
|
||||
udev_enumerate_unref(enumerate);
|
||||
}
|
||||
|
||||
void operator()(udev* context) const
|
||||
{
|
||||
udev_unref(context);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using UdevPtr = std::unique_ptr<T, UdevDeleter>;
|
||||
|
||||
UdevPtr<udev> udevContext;
|
||||
UdevPtr<udev_monitor> udevMonitor;
|
||||
|
||||
struct JoystickRecord
|
||||
{
|
||||
@ -181,7 +208,7 @@ void updatePluggedList(udev_device* udevDevice = nullptr)
|
||||
for (JoystickRecord& record : joystickList)
|
||||
record.plugged = false;
|
||||
|
||||
udev_enumerate* udevEnumerator = udev_enumerate_new(udevContext);
|
||||
const auto udevEnumerator = UdevPtr<udev_enumerate>(udev_enumerate_new(udevContext.get()));
|
||||
|
||||
if (!udevEnumerator)
|
||||
{
|
||||
@ -189,36 +216,30 @@ void updatePluggedList(udev_device* udevDevice = nullptr)
|
||||
return;
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
|
||||
result = udev_enumerate_add_match_subsystem(udevEnumerator, "input");
|
||||
|
||||
if (result < 0)
|
||||
if (udev_enumerate_add_match_subsystem(udevEnumerator.get(), "input") < 0)
|
||||
{
|
||||
sf::err() << "Error while adding udev enumerator match" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
result = udev_enumerate_scan_devices(udevEnumerator);
|
||||
|
||||
if (result < 0)
|
||||
if (udev_enumerate_scan_devices(udevEnumerator.get()) < 0)
|
||||
{
|
||||
sf::err() << "Error while enumerating udev devices" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
udev_list_entry* devices = udev_enumerate_get_list_entry(udevEnumerator);
|
||||
udev_list_entry* devices = udev_enumerate_get_list_entry(udevEnumerator.get());
|
||||
udev_list_entry* device = nullptr;
|
||||
|
||||
udev_list_entry_foreach(device, devices)
|
||||
{
|
||||
const char* syspath = udev_list_entry_get_name(device);
|
||||
udev_device* newUdevDevice = udev_device_new_from_syspath(udevContext, syspath);
|
||||
const char* syspath = udev_list_entry_get_name(device);
|
||||
const auto newUdevDevice = UdevPtr<udev_device>(udev_device_new_from_syspath(udevContext.get(), syspath));
|
||||
|
||||
if (newUdevDevice && isJoystick(newUdevDevice))
|
||||
if (newUdevDevice && isJoystick(newUdevDevice.get()))
|
||||
{
|
||||
// Since isJoystick returned true, this has to succeed
|
||||
const char* devnode = udev_device_get_devnode(newUdevDevice);
|
||||
const char* devnode = udev_device_get_devnode(newUdevDevice.get());
|
||||
|
||||
JoystickList::iterator recordIt;
|
||||
|
||||
@ -243,17 +264,13 @@ void updatePluggedList(udev_device* udevDevice = nullptr)
|
||||
joystickList.push_back(newRecord);
|
||||
}
|
||||
}
|
||||
|
||||
udev_device_unref(newUdevDevice);
|
||||
}
|
||||
|
||||
udev_enumerate_unref(udevEnumerator);
|
||||
}
|
||||
|
||||
bool hasMonitorEvent()
|
||||
{
|
||||
// This will not fail since we make sure udevMonitor is valid
|
||||
const int monitorFd = udev_monitor_get_fd(udevMonitor);
|
||||
const int monitorFd = udev_monitor_get_fd(udevMonitor.get());
|
||||
|
||||
pollfd fds{monitorFd, POLLIN, 0};
|
||||
|
||||
@ -316,7 +333,8 @@ unsigned int getJoystickVendorId(unsigned int index)
|
||||
return 0;
|
||||
}
|
||||
|
||||
udev_device* udevDevice = udev_device_new_from_syspath(udevContext, joystickList[index].systemPath.c_str());
|
||||
const auto udevDevice = UdevPtr<udev_device>(
|
||||
udev_device_new_from_syspath(udevContext.get(), joystickList[index].systemPath.c_str()));
|
||||
|
||||
if (!udevDevice)
|
||||
{
|
||||
@ -324,23 +342,12 @@ unsigned int getJoystickVendorId(unsigned int index)
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int id = 0;
|
||||
|
||||
// First try using udev
|
||||
id = getUdevAttributeUint(udevDevice, "ID_VENDOR_ID");
|
||||
|
||||
if (id)
|
||||
{
|
||||
udev_device_unref(udevDevice);
|
||||
if (const unsigned int id = getUdevAttributeUint(udevDevice.get(), "ID_VENDOR_ID"))
|
||||
return id;
|
||||
}
|
||||
|
||||
// Fall back to using USB attribute
|
||||
id = getUsbAttributeUint(udevDevice, "idVendor");
|
||||
|
||||
udev_device_unref(udevDevice);
|
||||
|
||||
if (id)
|
||||
if (const unsigned int id = getUsbAttributeUint(udevDevice.get(), "idVendor"))
|
||||
return id;
|
||||
|
||||
sf::err() << "Failed to get vendor ID of joystick " << joystickList[index].deviceNode << std::endl;
|
||||
@ -357,7 +364,8 @@ unsigned int getJoystickProductId(unsigned int index)
|
||||
return 0;
|
||||
}
|
||||
|
||||
udev_device* udevDevice = udev_device_new_from_syspath(udevContext, joystickList[index].systemPath.c_str());
|
||||
const auto udevDevice = UdevPtr<udev_device>(
|
||||
udev_device_new_from_syspath(udevContext.get(), joystickList[index].systemPath.c_str()));
|
||||
|
||||
if (!udevDevice)
|
||||
{
|
||||
@ -365,23 +373,12 @@ unsigned int getJoystickProductId(unsigned int index)
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int id = 0;
|
||||
|
||||
// First try using udev
|
||||
id = getUdevAttributeUint(udevDevice, "ID_MODEL_ID");
|
||||
|
||||
if (id)
|
||||
{
|
||||
udev_device_unref(udevDevice);
|
||||
if (const unsigned int id = getUdevAttributeUint(udevDevice.get(), "ID_MODEL_ID"))
|
||||
return id;
|
||||
}
|
||||
|
||||
// Fall back to using USB attribute
|
||||
id = getUsbAttributeUint(udevDevice, "idProduct");
|
||||
|
||||
udev_device_unref(udevDevice);
|
||||
|
||||
if (id)
|
||||
if (const unsigned int id = getUsbAttributeUint(udevDevice.get(), "idProduct"))
|
||||
return id;
|
||||
|
||||
sf::err() << "Failed to get product ID of joystick " << joystickList[index].deviceNode << std::endl;
|
||||
@ -412,16 +409,12 @@ std::string getJoystickName(unsigned int index)
|
||||
// Fall back to manual USB chain walk via udev
|
||||
if (udevContext)
|
||||
{
|
||||
udev_device* udevDevice = udev_device_new_from_syspath(udevContext, joystickList[index].systemPath.c_str());
|
||||
const auto udevDevice = UdevPtr<udev_device>(
|
||||
udev_device_new_from_syspath(udevContext.get(), joystickList[index].systemPath.c_str()));
|
||||
|
||||
if (udevDevice)
|
||||
{
|
||||
const char* product = getUsbAttribute(udevDevice, "product");
|
||||
udev_device_unref(udevDevice);
|
||||
|
||||
if (product)
|
||||
if (const char* product = getUsbAttribute(udevDevice.get(), "product"))
|
||||
return {product};
|
||||
}
|
||||
}
|
||||
|
||||
sf::err() << "Unable to get name for joystick " << devnode << std::endl;
|
||||
@ -436,7 +429,7 @@ namespace sf::priv
|
||||
////////////////////////////////////////////////////////////
|
||||
void JoystickImpl::initialize()
|
||||
{
|
||||
udevContext = udev_new();
|
||||
udevContext = UdevPtr<udev>(udev_new());
|
||||
|
||||
if (!udevContext)
|
||||
{
|
||||
@ -444,7 +437,7 @@ void JoystickImpl::initialize()
|
||||
return;
|
||||
}
|
||||
|
||||
udevMonitor = udev_monitor_new_from_netlink(udevContext, "udev");
|
||||
udevMonitor = UdevPtr<udev_monitor>(udev_monitor_new_from_netlink(udevContext.get(), "udev"));
|
||||
|
||||
if (!udevMonitor)
|
||||
{
|
||||
@ -452,27 +445,25 @@ void JoystickImpl::initialize()
|
||||
}
|
||||
else
|
||||
{
|
||||
int error = udev_monitor_filter_add_match_subsystem_devtype(udevMonitor, "input", nullptr);
|
||||
int error = udev_monitor_filter_add_match_subsystem_devtype(udevMonitor.get(), "input", nullptr);
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
err() << "Failed to add udev monitor filter, joystick connections and disconnections won't be notified: "
|
||||
<< error << std::endl;
|
||||
|
||||
udev_monitor_unref(udevMonitor);
|
||||
udevMonitor = nullptr;
|
||||
udevMonitor.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
error = udev_monitor_enable_receiving(udevMonitor);
|
||||
error = udev_monitor_enable_receiving(udevMonitor.get());
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
err() << "Failed to enable udev monitor, joystick connections and disconnections won't be notified: "
|
||||
<< error << std::endl;
|
||||
|
||||
udev_monitor_unref(udevMonitor);
|
||||
udevMonitor = nullptr;
|
||||
udevMonitor.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -486,18 +477,10 @@ void JoystickImpl::initialize()
|
||||
void JoystickImpl::cleanup()
|
||||
{
|
||||
// Unreference the udev monitor to destroy it
|
||||
if (udevMonitor)
|
||||
{
|
||||
udev_monitor_unref(udevMonitor);
|
||||
udevMonitor = nullptr;
|
||||
}
|
||||
udevMonitor.reset();
|
||||
|
||||
// Unreference the udev context to destroy it
|
||||
if (udevContext)
|
||||
{
|
||||
udev_unref(udevContext);
|
||||
udevContext = nullptr;
|
||||
}
|
||||
udevContext.reset();
|
||||
}
|
||||
|
||||
|
||||
@ -513,14 +496,11 @@ bool JoystickImpl::isConnected(unsigned int index)
|
||||
else if (hasMonitorEvent())
|
||||
{
|
||||
// Check if new joysticks were added/removed since last update
|
||||
udev_device* udevDevice = udev_monitor_receive_device(udevMonitor);
|
||||
const auto udevDevice = UdevPtr<udev_device>(udev_monitor_receive_device(udevMonitor.get()));
|
||||
|
||||
// If we can get the specific device, we check that,
|
||||
// otherwise just do a full scan if udevDevice == nullptr
|
||||
updatePluggedList(udevDevice);
|
||||
|
||||
if (udevDevice)
|
||||
udev_device_unref(udevDevice);
|
||||
updatePluggedList(udevDevice.get());
|
||||
}
|
||||
|
||||
if (index >= joystickList.size())
|
||||
|
Loading…
Reference in New Issue
Block a user