solid: UDev backend client review

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2021-06-13 03:28:37 +03:00
parent dbc5f9a9c8
commit 9ffcd227c4
3 changed files with 35 additions and 103 deletions

View file

@ -69,16 +69,10 @@ class Client : public QObject
{
Q_OBJECT
Q_PROPERTY(QStringList watchedSubsystems READ watchedSubsystems WRITE setWatchedSubsystems)
public:
Client(QObject *parent = 0);
Client(const QStringList &subsystemList, QObject *parent = 0);
~Client();
QStringList watchedSubsystems() const;
void setWatchedSubsystems(const QStringList &subsystemList);
DeviceList allDevices();
Device deviceBySysfsPath(const QString &sysfsPath);

View file

@ -47,25 +47,21 @@ class DevicePrivate
class ClientPrivate
{
public:
ClientPrivate(Client *q_);
ClientPrivate(Client *q_, const QStringList &subsystemList);
~ClientPrivate();
void setWatchedSubsystems(const QStringList &subsystemList);
void _uq_monitorReadyRead(int fd);
DeviceList deviceListFromEnumerate(struct udev_enumerate *en);
struct udev *udev;
struct udev_monitor *monitor;
Client *q;
QSocketNotifier *monitorNotifier;
QStringList watchedSubsystems;
};
inline QStringList listFromListEntry(struct udev_list_entry *list)
{
QStringList ret;
struct udev_list_entry *entry;
udev_list_entry_foreach(entry, list) {
ret << QString::fromLatin1(udev_list_entry_get_name(entry));
}

View file

@ -26,9 +26,26 @@
namespace UdevQt {
ClientPrivate::ClientPrivate(Client *q_)
ClientPrivate::ClientPrivate(Client *q_, const QStringList &subsystemList)
: udev(udev_new()), monitor(0), q(q_), monitorNotifier(0)
{
// create a listener
monitor = udev_monitor_new_from_netlink(udev, "udev");
if (!monitor) {
qWarning("UdevQt: unable to create udev monitor connection");
return;
}
// apply subsystem filters
foreach (const QString &subsysDevtype, subsystemList) {
udev_monitor_filter_add_match_subsystem_devtype(monitor, subsysDevtype.toLatin1().constData(), NULL);
}
// start the monitor receiving
udev_monitor_enable_receiving(monitor);
monitorNotifier = new QSocketNotifier(udev_monitor_get_fd(monitor), QSocketNotifier::Read);
QObject::connect(monitorNotifier, SIGNAL(activated(int)), q, SLOT(_uq_monitorReadyRead(int)));
}
ClientPrivate::~ClientPrivate()
@ -40,45 +57,6 @@ ClientPrivate::~ClientPrivate()
udev_monitor_unref(monitor);
}
void ClientPrivate::setWatchedSubsystems(const QStringList &subsystemList)
{
// create a listener
struct udev_monitor *newM = udev_monitor_new_from_netlink(udev, "udev");
if (!newM) {
qWarning("UdevQt: unable to create udev monitor connection");
return;
}
// apply our filters; an empty list means listen to everything
foreach (const QString& subsysDevtype, subsystemList) {
int ix = subsysDevtype.indexOf("/");
if (ix > 0) {
QByteArray subsystem = subsysDevtype.left(ix).toLatin1();
QByteArray devType = subsysDevtype.mid(ix + 1).toLatin1();
udev_monitor_filter_add_match_subsystem_devtype(newM, subsystem.constData(), devType.constData());
} else {
udev_monitor_filter_add_match_subsystem_devtype(newM, subsysDevtype.toLatin1().constData(), NULL);
}
}
// start the new monitor receiving
udev_monitor_enable_receiving(newM);
QSocketNotifier *sn = new QSocketNotifier(udev_monitor_get_fd(newM), QSocketNotifier::Read);
QObject::connect(sn, SIGNAL(activated(int)), q, SLOT(_uq_monitorReadyRead(int)));
// kill any previous monitor
delete monitorNotifier;
if (monitor)
udev_monitor_unref(monitor);
// and save our new one
monitor = newM;
monitorNotifier = sn;
watchedSubsystems = subsystemList;
}
void ClientPrivate::_uq_monitorReadyRead(int fd)
{
Q_UNUSED(fd);
@ -111,13 +89,26 @@ void ClientPrivate::_uq_monitorReadyRead(int fd)
}
}
DeviceList ClientPrivate::deviceListFromEnumerate(struct udev_enumerate *en)
Client::Client(const QStringList& subsystemList, QObject *parent)
: QObject(parent)
, d(new ClientPrivate(this, subsystemList))
{
}
Client::~Client()
{
delete d;
}
DeviceList Client::allDevices()
{
DeviceList ret;
struct udev_list_entry *list, *entry;
struct udev_enumerate *en = udev_enumerate_new(d->udev);
udev_enumerate_scan_devices(en);
list = udev_enumerate_get_list_entry(en);
struct udev_list_entry *entry;
struct udev_list_entry *list = udev_enumerate_get_list_entry(en);
udev_list_entry_foreach(entry, list) {
struct udev_device *ud = udev_device_new_from_syspath(udev_enumerate_get_udev(en),
udev_list_entry_get_name(entry));
@ -133,55 +124,6 @@ DeviceList ClientPrivate::deviceListFromEnumerate(struct udev_enumerate *en)
return ret;
}
Client::Client(QObject *parent)
: QObject(parent)
, d(new ClientPrivate(this))
{
}
Client::Client(const QStringList& subsystemList, QObject *parent)
: QObject(parent)
, d(new ClientPrivate(this))
{
setWatchedSubsystems(subsystemList);
}
Client::~Client()
{
delete d;
}
QStringList Client::watchedSubsystems() const
{
// we're watching a specific list
if (!d->watchedSubsystems.isEmpty())
return d->watchedSubsystems;
// we're not watching anything
if (!d->monitor)
return QStringList();
// we're watching everything: figure out what "everything" currently is
// we don't cache it, since it may be subject to change, depending on hotplug
struct udev_enumerate *en = udev_enumerate_new(d->udev);
udev_enumerate_scan_subsystems(en);
QStringList s = listFromListEntry(udev_enumerate_get_list_entry(en));
udev_enumerate_unref(en);
return s;
}
void Client::setWatchedSubsystems(const QStringList &subsystemList)
{
d->setWatchedSubsystems(subsystemList);
}
DeviceList Client::allDevices()
{
struct udev_enumerate *en = udev_enumerate_new(d->udev);
return d->deviceListFromEnumerate(en);
}
Device Client::deviceBySysfsPath(const QString &sysfsPath)
{
struct udev_device *ud = udev_device_new_from_syspath(d->udev, sysfsPath.toLatin1().constData());