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