File indexing completed on 2024-05-19 05:39:21

0001 /*
0002     SPDX-FileCopyrightText: 2009 Benjamin K. Stuhl <bks24@cornell.edu>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include "udevqtdevice.h"
0008 #include "udevqt_p.h"
0009 
0010 #include <QByteArray>
0011 
0012 namespace UdevQt
0013 {
0014 DevicePrivate::DevicePrivate(struct udev_device *udev_, bool ref)
0015     : udev(udev_)
0016 {
0017     if (ref)
0018         udev_device_ref(udev);
0019 }
0020 
0021 DevicePrivate::~DevicePrivate()
0022 {
0023     udev_device_unref(udev);
0024 }
0025 
0026 DevicePrivate &DevicePrivate::operator=(const DevicePrivate &other)
0027 {
0028     udev_device_unref(udev);
0029     udev = udev_device_ref(other.udev);
0030     return *this;
0031 }
0032 
0033 QString DevicePrivate::decodePropertyValue(const QByteArray &encoded) const
0034 {
0035     QByteArray decoded;
0036     const int len = encoded.length();
0037 
0038     for (int i = 0; i < len; i++) {
0039         quint8 ch = encoded.at(i);
0040 
0041         if (ch == '\\') {
0042             if (i + 1 < len && encoded.at(i + 1) == '\\') {
0043                 decoded.append('\\');
0044                 i++;
0045                 continue;
0046             } else if (i + 3 < len && encoded.at(i + 1) == 'x') {
0047                 QByteArray hex = encoded.mid(i + 2, 2);
0048                 bool ok;
0049                 int code = hex.toInt(&ok, 16);
0050                 if (ok)
0051                     decoded.append(char(code));
0052                 i += 3;
0053                 continue;
0054             }
0055         } else {
0056             decoded.append(ch);
0057         }
0058     }
0059     return QString::fromUtf8(decoded);
0060 }
0061 
0062 Device::Device()
0063     : d(nullptr)
0064 {
0065 }
0066 
0067 Device::Device(const Device &other)
0068 {
0069     if (other.d) {
0070         d = new DevicePrivate(other.d->udev);
0071     } else {
0072         d = nullptr;
0073     }
0074 }
0075 
0076 Device::Device(DevicePrivate *devPrivate)
0077     : d(devPrivate)
0078 {
0079 }
0080 
0081 Device::~Device()
0082 {
0083     delete d;
0084 }
0085 
0086 Device &Device::operator=(const Device &other)
0087 {
0088     if (this == &other)
0089         return *this;
0090     if (!other.d) {
0091         delete d;
0092         d = nullptr;
0093         return *this;
0094     }
0095     if (!d) {
0096         d = new DevicePrivate(other.d->udev);
0097     } else {
0098         *d = *other.d;
0099     }
0100 
0101     return *this;
0102 }
0103 
0104 bool Device::isValid() const
0105 {
0106     return (d != nullptr);
0107 }
0108 
0109 QString Device::subsystem() const
0110 {
0111     if (!d)
0112         return QString();
0113 
0114     return QString::fromLatin1(udev_device_get_subsystem(d->udev));
0115 }
0116 
0117 QString Device::devType() const
0118 {
0119     if (!d)
0120         return QString();
0121 
0122     return QString::fromLatin1(udev_device_get_devtype(d->udev));
0123 }
0124 
0125 QString Device::name() const
0126 {
0127     if (!d)
0128         return QString();
0129 
0130     return QString::fromLatin1(udev_device_get_sysname(d->udev));
0131 }
0132 
0133 QString Device::sysfsPath() const
0134 {
0135     if (!d)
0136         return QString();
0137 
0138     return QString::fromLatin1(udev_device_get_syspath(d->udev));
0139 }
0140 
0141 int Device::sysfsNumber() const
0142 {
0143     if (!d)
0144         return -1;
0145 
0146     QString value = QString::fromLatin1(udev_device_get_sysnum(d->udev));
0147     bool success = false;
0148     int number = value.toInt(&success);
0149     if (success)
0150         return number;
0151     return -1;
0152 }
0153 
0154 QString Device::driver() const
0155 {
0156     if (!d)
0157         return QString();
0158 
0159     return QString::fromLatin1(udev_device_get_driver(d->udev));
0160 }
0161 
0162 QString Device::primaryDeviceFile() const
0163 {
0164     if (!d)
0165         return QString();
0166 
0167     return QString::fromLatin1(udev_device_get_devnode(d->udev));
0168 }
0169 
0170 QStringList Device::alternateDeviceSymlinks() const
0171 {
0172     if (!d)
0173         return QStringList();
0174 
0175     return listFromListEntry(udev_device_get_devlinks_list_entry(d->udev));
0176 }
0177 
0178 QStringList Device::deviceProperties() const
0179 {
0180     if (!d)
0181         return QStringList();
0182 
0183     return listFromListEntry(udev_device_get_properties_list_entry(d->udev));
0184 }
0185 
0186 QStringList Device::sysfsProperties() const
0187 {
0188     if (!d)
0189         return QStringList();
0190 
0191     return listFromListEntry(udev_device_get_sysattr_list_entry(d->udev));
0192 }
0193 
0194 Device Device::parent() const
0195 {
0196     if (!d)
0197         return Device();
0198 
0199     struct udev_device *p = udev_device_get_parent(d->udev);
0200 
0201     if (!p)
0202         return Device();
0203 
0204     return Device(new DevicePrivate(p));
0205 }
0206 
0207 QVariant Device::deviceProperty(const QString &name) const
0208 {
0209     if (!d)
0210         return QVariant();
0211 
0212     QByteArray propName = name.toLatin1();
0213     QString propValue = QString::fromLatin1(udev_device_get_property_value(d->udev, propName.constData()));
0214     if (!propValue.isEmpty()) {
0215         return QVariant::fromValue(propValue);
0216     }
0217     return QVariant();
0218 }
0219 
0220 QString Device::decodedDeviceProperty(const QString &name) const
0221 {
0222     if (!d)
0223         return QString();
0224 
0225     QByteArray propName = name.toLatin1();
0226     return d->decodePropertyValue(udev_device_get_property_value(d->udev, propName.constData()));
0227 }
0228 
0229 QVariant Device::sysfsProperty(const QString &name) const
0230 {
0231     if (!d)
0232         return QVariant();
0233 
0234     QByteArray propName = name.toLatin1();
0235     QString propValue = QString::fromLatin1(udev_device_get_sysattr_value(d->udev, propName.constData()));
0236     if (!propValue.isEmpty()) {
0237         return QVariant::fromValue(propValue);
0238     }
0239     return QVariant();
0240 }
0241 
0242 Device Device::ancestorOfType(const QString &subsys, const QString &devtype) const
0243 {
0244     if (!d)
0245         return Device();
0246 
0247     struct udev_device *p = udev_device_get_parent_with_subsystem_devtype(d->udev, subsys.toLatin1().constData(), devtype.toLatin1().constData());
0248 
0249     if (!p)
0250         return Device();
0251 
0252     return Device(new DevicePrivate(p));
0253 }
0254 
0255 }