diff --git a/CMakeLists.txt b/CMakeLists.txt index c18d385..b6a4d3d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,160 +1,160 @@ cmake_minimum_required(VERSION 3.5) set(KF5_VERSION "5.71.0") # handled by release scripts project(Solid VERSION ${KF5_VERSION}) include(FeatureSummary) find_package(ECM 5.70.0 NO_MODULE) set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://commits.kde.org/extra-cmake-modules") feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) include(KDEInstallDirs) include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(KDECMakeSettings) include(ECMQtDeclareLoggingCategory) set(REQUIRED_QT_VERSION 5.12.0) find_package(Qt5 ${REQUIRED_QT_VERSION} CONFIG REQUIRED Xml Gui) if (NOT ANDROID) find_package(Qt5 ${REQUIRED_QT_VERSION} CONFIG REQUIRED DBus) endif() if(WIN32) find_package(Qt5 ${REQUIRED_QT_VERSION} CONFIG REQUIRED Network) endif() include(ECMGenerateExportHeader) include(CMakePackageConfigHelpers) include(ECMSetupVersion) include(ECMGenerateHeaders) include(ECMMarkNonGuiExecutable) include(ECMAddQch) find_package(FLEX REQUIRED) set_package_properties(FLEX PROPERTIES URL "http://flex.sourceforge.net" DESCRIPTION "Fast Lexical Analyzer" TYPE REQUIRED PURPOSE "Required for the Predicate parser" ) find_package(BISON REQUIRED) set_package_properties(BISON PROPERTIES URL "http://www.gnu.org/software/bison" DESCRIPTION "general-purpose parser generator" TYPE REQUIRED PURPOSE "Required for the Predicate parser" ) include(ECMPoQmTools) set(EXCLUDE_DEPRECATED_BEFORE_AND_AT 0 CACHE STRING "Control the range of deprecated API excluded from the build [default=0].") option(BUILD_QCH "Build API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)" OFF) add_feature_info(QCH ${BUILD_QCH} "API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)") ecm_setup_version(PROJECT VARIABLE_PREFIX SOLID VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/solid_version.h" PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5SolidConfigVersion.cmake" SOVERSION 5) # TODO: Remove these remove_definitions(-DQT_NO_CAST_FROM_ASCII) remove_definitions(-DQT_NO_CAST_FROM_BYTEARRAY) add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050d00) if (IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/po") ecm_install_po_files_as_qm(po) endif() option(WITH_NEW_SOLID_JOB "WIP: base Job class" Off) add_feature_info(Solid::Job WITH_NEW_SOLID_JOB "WIP: Base class for Solid Asynchronous apis") option(WITH_NEW_POWER_ASYNC_API "WIP: Asynchronous API for power management" Off) add_feature_info(Solid::PowerManagement WITH_NEW_POWER_ASYNC_API "WIP: Asynchronous API for power management") option(WITH_NEW_POWER_ASYNC_FREEDESKTOP "WIP: Freedesktop backend for the asynchronous api" Off) add_feature_info(Solid::PowerManagement WITH_NEW_POWER_ASYNC_FREEDESKTOP "WIP: Freedesktop backend for the asynchronous api") include(SolidBackendsMacros) add_device_backends_begin() add_device_backend(fakehw) if (CMAKE_SYSTEM_NAME MATCHES Linux) option(UDEV_DISABLED "Allows disabling UDev usage on Linux builds" OFF) if (NOT UDEV_DISABLED) find_package(UDev REQUIRED) set_package_properties(UDev PROPERTIES TYPE REQUIRED PURPOSE "Allows Solid to use UDev to provide information about devices on Linux" ) endif() if (UDev_FOUND) set(UDEV_FOUND TRUE) # for config-solid.h add_device_backend(udev) endif() add_device_backend(udisks2) add_device_backend(fstab) add_device_backend(upower) elseif (APPLE) find_package(IOKit REQUIRED) add_device_backend(iokit) elseif (WIN32) add_device_backend(win) elseif (NOT ANDROID) add_device_backend(upower) add_device_backend(fstab) - if (CMAKE_SYSTEM_NAME MATCHES FreeBSD) +# if (CMAKE_SYSTEM_NAME MATCHES FreeBSD) # FIXME: this should work on more Unix systems option(EXPERIMENTAL_BSDISKS "Use UDisks2/bsdisks backend instead of HAL to manage disk devices" OFF) - else () - set(EXPERIMENTAL_BSDISKS FALSE) - endif() - if(EXPERIMENTAL_BSDISKS) - add_device_backend(udisks2) - else() +# else () +# set(EXPERIMENTAL_BSDISKS TRUE) +# # endif() +# if(EXPERIMENTAL_BSDISKS) +# add_device_backend(udisks2) +# else() add_device_backend(hal) - endif() +# endif() endif() add_device_backends_cmake() add_subdirectory(src) if (TARGET Qt5::DBus AND BUILD_TESTING) add_subdirectory(autotests) endif() # create a Config.cmake and a ConfigVersion.cmake file and install them set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5Solid") if (BUILD_QCH) ecm_install_qch_export( TARGETS KF5Solid_QCH FILE KF5SolidQchTargets.cmake DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) set(PACKAGE_INCLUDE_QCHTARGETS "include(\"\${CMAKE_CURRENT_LIST_DIR}/KF5SolidQchTargets.cmake\")") endif() configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/KF5SolidConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/KF5SolidConfig.cmake" PATH_VARS KDE_INSTALL_DBUSINTERFACEDIR INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KF5SolidConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/KF5SolidConfigVersion.cmake" DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) install(EXPORT KF5SolidTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KF5SolidTargets.cmake NAMESPACE KF5:: ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/solid_version.h DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5} COMPONENT Devel ) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/src/solid/devices/backends/hal/halcdrom.cpp b/src/solid/devices/backends/hal/halcdrom.cpp index f34a27c..a42a6a4 100644 --- a/src/solid/devices/backends/hal/halcdrom.cpp +++ b/src/solid/devices/backends/hal/halcdrom.cpp @@ -1,195 +1,195 @@ /* SPDX-FileCopyrightText: 2006 Kevin Ottens SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "halcdrom.h" #include #include #include #include #include "halfstabhandling.h" using namespace Solid::Backends::Hal; Cdrom::Cdrom(HalDevice *device) : Storage(device), m_ejectInProgress(false) { connect(device, SIGNAL(conditionRaised(QString,QString)), this, SLOT(slotCondition(QString,QString))); m_device->registerAction("eject", this, SLOT(slotEjectRequested()), SLOT(slotEjectDone(int,QString))); } Cdrom::~Cdrom() { } Solid::OpticalDrive::MediumTypes Cdrom::supportedMedia() const { Solid::OpticalDrive::MediumTypes supported; - QMap map; - map[Solid::OpticalDrive::Cdr] = "storage.cdrom.cdr"; - map[Solid::OpticalDrive::Cdrw] = "storage.cdrom.cdrw"; - map[Solid::OpticalDrive::Dvd] = "storage.cdrom.dvd"; - map[Solid::OpticalDrive::Dvdr] = "storage.cdrom.dvdr"; - map[Solid::OpticalDrive::Dvdrw] = "storage.cdrom.dvdrw"; - map[Solid::OpticalDrive::Dvdram] = "storage.cdrom.dvdram"; - map[Solid::OpticalDrive::Dvdplusr] = "storage.cdrom.dvdplusr"; - map[Solid::OpticalDrive::Dvdplusrw] = "storage.cdrom.dvdplusrw"; - map[Solid::OpticalDrive::Dvdplusdl] = "storage.cdrom.dvdplusrdl"; - map[Solid::OpticalDrive::Dvdplusdlrw] = "storage.cdrom.dvdplusrwdl"; - map[Solid::OpticalDrive::Bd] = "storage.cdrom.bd"; - map[Solid::OpticalDrive::Bdr] = "storage.cdrom.bdr"; - map[Solid::OpticalDrive::Bdre] = "storage.cdrom.bdre"; - map[Solid::OpticalDrive::HdDvd] = "storage.cdrom.hddvd"; - map[Solid::OpticalDrive::HdDvdr] = "storage.cdrom.hddvdr"; - map[Solid::OpticalDrive::HdDvdrw] = "storage.cdrom.hddvdrw"; - - Q_FOREACH (const Solid::OpticalDrive::MediumType type, map.keys()) { - if (m_device->prop(map[type]).toBool()) { - supported |= type; + const QMap map = { + {Solid::OpticalDrive::Cdr, QStringLiteral("storage.cdrom.cdr")}, + {Solid::OpticalDrive::Cdrw, QStringLiteral("storage.cdrom.cdrw")}, + {Solid::OpticalDrive::Dvd, QStringLiteral("storage.cdrom.dvd")}, + {Solid::OpticalDrive::Dvdr, QStringLiteral("storage.cdrom.dvdr")}, + {Solid::OpticalDrive::Dvdrw, QStringLiteral("storage.cdrom.dvdrw")}, + {Solid::OpticalDrive::Dvdram, QStringLiteral("storage.cdrom.dvdram")}, + {Solid::OpticalDrive::Dvdplusr, QStringLiteral("storage.cdrom.dvdplusr")}, + {Solid::OpticalDrive::Dvdplusrw, QStringLiteral("storage.cdrom.dvdplusrw")}, + {Solid::OpticalDrive::Dvdplusdl, QStringLiteral("storage.cdrom.dvdplusrdl")}, + {Solid::OpticalDrive::Dvdplusdlrw, QStringLiteral("storage.cdrom.dvdplusrwdl")}, + {Solid::OpticalDrive::Bd, QStringLiteral("storage.cdrom.bd")}, + {Solid::OpticalDrive::Bdr, QStringLiteral("storage.cdrom.bdr")}, + {Solid::OpticalDrive::Bdre, QStringLiteral("storage.cdrom.bdre")}, + {Solid::OpticalDrive::HdDvd, QStringLiteral("storage.cdrom.hddvd")}, + {Solid::OpticalDrive::HdDvdr, QStringLiteral("storage.cdrom.hddvdr")}, + {Solid::OpticalDrive::HdDvdrw, QStringLiteral("storage.cdrom.hddvdrw")}}; + + for (auto it = map.cbegin(); it != map.cend(); ++it) { + if (m_device->prop(it.value()).toBool()) { + supported |= it.key(); } } return supported; } int Cdrom::readSpeed() const { return m_device->prop("storage.cdrom.read_speed").toInt(); } int Cdrom::writeSpeed() const { return m_device->prop("storage.cdrom.write_speed").toInt(); } QList Cdrom::writeSpeeds() const { QList speeds; - QStringList speed_strlist = m_device->prop("storage.cdrom.write_speeds").toStringList(); + const QStringList speed_strlist = m_device->prop("storage.cdrom.write_speeds").toStringList(); - Q_FOREACH (const QString &speed_str, speed_strlist) { + for (const QString &speed_str : speed_strlist) { speeds << speed_str.toInt(); } return speeds; } void Cdrom::slotCondition(const QString &name, const QString &/*reason */) { if (name == "EjectPressed") { emit ejectPressed(m_device->udi()); } } bool Cdrom::eject() { if (m_ejectInProgress) { return false; } m_ejectInProgress = true; m_device->broadcastActionRequested("eject"); if (FstabHandling::isInFstab(m_device->prop("block.device").toString())) { return callSystemEject(); } else { return callHalDriveEject(); } } void Cdrom::slotEjectRequested() { m_ejectInProgress = true; emit ejectRequested(m_device->udi()); } bool Cdrom::callHalDriveEject() { QString udi = m_device->udi(); QString interface = "org.freedesktop.Hal.Device.Storage"; // HACK: Eject doesn't work on cdrom drives when there's a mounted disc, // let's try to workaround this by calling a child volume... if (m_device->prop("storage.removable.media_available").toBool()) { QDBusInterface manager("org.freedesktop.Hal", "/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager", QDBusConnection::systemBus()); QDBusReply reply = manager.call("FindDeviceStringMatch", "info.parent", udi); if (reply.isValid()) { const QStringList udis = reply; if (!udis.isEmpty()) { udi = udis[0]; interface = "org.freedesktop.Hal.Device.Volume"; } } } QDBusConnection c = QDBusConnection::systemBus(); QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.Hal", udi, interface, "Eject"); msg << QStringList(); return c.callWithCallback(msg, this, SLOT(slotDBusReply(QDBusMessage)), SLOT(slotDBusError(QDBusError))); } bool Solid::Backends::Hal::Cdrom::callSystemEject() { const QString device = m_device->prop("block.device").toString(); m_process = FstabHandling::callSystemCommand("eject", device, this, SLOT(slotProcessFinished(int,QProcess::ExitStatus))); return m_process != nullptr; } void Cdrom::slotDBusReply(const QDBusMessage &/*reply*/) { m_ejectInProgress = false; m_device->broadcastActionDone("eject"); } void Cdrom::slotDBusError(const QDBusError &error) { m_ejectInProgress = false; // TODO: Better error reporting here m_device->broadcastActionDone("eject", Solid::UnauthorizedOperation, QString(error.name() + ": " + error.message())); } void Solid::Backends::Hal::Cdrom::slotProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) { Q_UNUSED(exitStatus); if (m_ejectInProgress) { m_ejectInProgress = false; if (exitCode == 0) { m_device->broadcastActionDone("eject"); } else { m_device->broadcastActionDone("eject", Solid::UnauthorizedOperation, m_process->readAllStandardError()); } } delete m_process; } void Cdrom::slotEjectDone(int error, const QString &errorString) { m_ejectInProgress = false; emit ejectDone(static_cast(error), errorString, m_device->udi()); } diff --git a/src/solid/devices/backends/hal/haldevice.cpp b/src/solid/devices/backends/hal/haldevice.cpp index f2ffb1b..48180a4 100644 --- a/src/solid/devices/backends/hal/haldevice.cpp +++ b/src/solid/devices/backends/hal/haldevice.cpp @@ -1,800 +1,799 @@ /* SPDX-FileCopyrightText: 2005-2007 Kevin Ottens SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "haldevice.h" #include #include #include #include #include #include #include #include "haldeviceinterface.h" #include "halgenericinterface.h" #include "halprocessor.h" #include "halblock.h" #include "halstorageaccess.h" #include "halstorage.h" #include "halcdrom.h" #include "halvolume.h" #include "halopticaldisc.h" #include "halcamera.h" #include "halportablemediaplayer.h" #include "halbattery.h" using namespace Solid::Backends::Hal; // Adapted from KLocale as Solid needs to be Qt-only static QString formatByteSize(double size) { // Per IEC 60027-2 // Binary prefixes //Tebi-byte TiB 2^40 1,099,511,627,776 bytes //Gibi-byte GiB 2^30 1,073,741,824 bytes //Mebi-byte MiB 2^20 1,048,576 bytes //Kibi-byte KiB 2^10 1,024 bytes QString s; // Gibi-byte if (size >= 1073741824.0) { size /= 1073741824.0; if (size > 1024) { // Tebi-byte s = HalDevice::tr("%1 TiB").arg(QLocale().toString(size / 1024.0, 'f', 1)); } else { s = HalDevice::tr("%1 GiB").arg(QLocale().toString(size, 'f', 1)); } } // Mebi-byte else if (size >= 1048576.0) { size /= 1048576.0; s = HalDevice::tr("%1 MiB").arg(QLocale().toString(size, 'f', 1)); } // Kibi-byte else if (size >= 1024.0) { size /= 1024.0; s = HalDevice::tr("%1 KiB").arg(QLocale().toString(size, 'f', 1)); } // Just byte else if (size > 0) { s = HalDevice::tr("%1 B").arg(QLocale().toString(size, 'f', 1)); } // Nothing else { s = HalDevice::tr("0 B"); } return s; } class Solid::Backends::Hal::HalDevicePrivate { public: HalDevicePrivate(const QString &udi) : device("org.freedesktop.Hal", udi, "org.freedesktop.Hal.Device", QDBusConnection::systemBus()), cacheSynced(false), parent(nullptr) { } void checkCache(const QString &key = QString()); QDBusInterface device; QMap cache; QMap capListCache; QSet invalidKeys; bool cacheSynced; HalDevice *parent; }; Q_DECLARE_METATYPE(ChangeDescription) const QDBusArgument &operator<<(QDBusArgument &arg, const ChangeDescription &change) { arg.beginStructure(); arg << change.key << change.added << change.removed; arg.endStructure(); return arg; } const QDBusArgument &operator>>(const QDBusArgument &arg, ChangeDescription &change) { arg.beginStructure(); arg >> change.key >> change.added >> change.removed; arg.endStructure(); return arg; } HalDevice::HalDevice(const QString &udi) : Device(), d(new HalDevicePrivate(udi)) { qDBusRegisterMetaType(); qDBusRegisterMetaType< QList >(); d->device.connection().connect("org.freedesktop.Hal", udi, "org.freedesktop.Hal.Device", "PropertyModified", this, SLOT(slotPropertyModified(int,QList))); d->device.connection().connect("org.freedesktop.Hal", udi, "org.freedesktop.Hal.Device", "Condition", this, SLOT(slotCondition(QString,QString))); } HalDevice::~HalDevice() { delete d->parent; delete d; } QString HalDevice::udi() const { return prop("info.udi").toString(); } QString HalDevice::parentUdi() const { return prop("info.parent").toString(); } QString HalDevice::vendor() const { const QString category = prop("info.category").toString(); if (category == QLatin1String("battery")) { return prop("battery.vendor").toString(); } else { return prop("info.vendor").toString(); } } QString HalDevice::product() const { return prop("info.product").toString(); } QString HalDevice::icon() const { QString category = prop("info.category").toString(); if (parentUdi().isEmpty()) { QString formfactor = prop("system.formfactor").toString(); if (formfactor == "laptop") { return "computer-laptop"; } else { return "computer"; } } else if (category == "storage" || category == "storage.cdrom") { if (prop("storage.drive_type").toString() == "floppy") { return "media-floppy"; } else if (prop("storage.drive_type").toString() == "cdrom") { return "drive-optical"; } else if (prop("storage.drive_type").toString() == "sd_mmc") { return "media-flash-sd-mmc"; } else if (prop("storage.hotpluggable").toBool()) { if (prop("storage.bus").toString() == "usb") { if (prop("storage.no_partitions_hint").toBool() || prop("storage.removable.media_size").toLongLong() < 4000000000LL) { return "drive-removable-media-usb-pendrive"; } else { return "drive-removable-media-usb"; } } return "drive-removable-media"; } return "drive-harddisk"; } else if (category == "volume" || category == "volume.disc") { QStringList capabilities = prop("info.capabilities").toStringList(); if (capabilities.contains("volume.disc")) { bool has_video = prop("volume.disc.is_vcd").toBool() || prop("volume.disc.is_svcd").toBool() || prop("volume.disc.is_videodvd").toBool(); bool has_audio = prop("volume.disc.has_audio").toBool(); bool recordable = prop("volume.disc.is_blank").toBool() || prop("volume.disc.is_appendable").toBool() || prop("volume.disc.is_rewritable").toBool(); if (has_video) { return "media-optical-video"; } else if (has_audio) { return "media-optical-audio"; } else if (recordable) { return "media-optical-recordable"; } else { return "media-optical"; } } else { if (!d->parent) { d->parent = new HalDevice(parentUdi()); } QString iconName = d->parent->icon(); if (!iconName.isEmpty()) { return iconName; } return "drive-harddisk"; } } else if (category == "camera") { return "camera-photo"; } else if (category == "input") { QStringList capabilities = prop("info.capabilities").toStringList(); if (capabilities.contains("input.mouse")) { return "input-mouse"; } else if (capabilities.contains("input.keyboard")) { return "input-keyboard"; } else if (capabilities.contains("input.joystick")) { return "input-gaming"; } else if (capabilities.contains("input.tablet")) { return "input-tablet"; } } else if (category == "portable_audio_player") { QStringList protocols = prop("portable_audio_player.access_method.protocols").toStringList(); if (protocols.contains("ipod")) { return "multimedia-player-apple-ipod"; } else { return "multimedia-player"; } } else if (category == "battery") { return "battery"; } else if (category == "processor") { return "cpu"; // FIXME: Doesn't follow icon spec } else if (category == "serial") { // TODO - a serial device can be a modem, or just // a COM port - need a new icon? return QLatin1String("modem"); } return QString(); } QStringList HalDevice::emblems() const { QStringList res; if (queryDeviceInterface(Solid::DeviceInterface::StorageAccess)) { bool isEncrypted = prop("volume.fsusage").toString() == "crypto"; const Hal::StorageAccess accessIface(const_cast(this)); if (accessIface.isAccessible()) { if (isEncrypted) { res << "emblem-encrypted-unlocked"; } else { res << "emblem-mounted"; } } else { if (isEncrypted) { res << "emblem-encrypted-locked"; } else { res << "emblem-unmounted"; } } } return res; } QString HalDevice::description() const { QString category = prop("info.category").toString(); if (category == "storage" || category == "storage.cdrom") { return storageDescription(); } else if (category == "volume" || category == "volume.disc") { return volumeDescription(); } else if (category == "net.80211") { return tr("WLAN Interface"); } else if (category == "net.80203") { return tr("Networking Interface"); } else { return product(); } } QVariant HalDevice::prop(const QString &key) const { d->checkCache(key); return d->cache.value(key); } void HalDevicePrivate::checkCache(const QString &key) { if (cacheSynced) { if (key.isEmpty()) { if (invalidKeys.isEmpty()) { return; } } else if (!invalidKeys.contains(key)) { return; } } QDBusReply reply = device.call("GetAllProperties"); if (reply.isValid()) { cache = reply; } else { qWarning() << Q_FUNC_INFO << " error: " << reply.error().name() << ", " << reply.error().message() << endl; cache = QVariantMap(); } invalidKeys.clear(); cacheSynced = true; //qDebug( )<< q << udi() << "failure"; } QMap HalDevice::allProperties() const { d->checkCache(); return d->cache; } bool HalDevice::propertyExists(const QString &key) const { d->checkCache(key); return d->cache.value(key).isValid(); } bool HalDevice::queryDeviceInterface(const Solid::DeviceInterface::Type &type) const { // Special cases not matching with HAL capabilities if (type == Solid::DeviceInterface::GenericInterface) { return true; } else if (type == Solid::DeviceInterface::StorageAccess) { return prop("org.freedesktop.Hal.Device.Volume.method_names").toStringList().contains("Mount") || prop("info.interfaces").toStringList().contains("org.freedesktop.Hal.Device.Volume.Crypto"); } else if (d->capListCache.contains(type)) { return d->capListCache.value(type); } - QStringList cap_list = DeviceInterface::toStringList(type); - - Q_FOREACH (const QString &cap, cap_list) { + const QStringList cap_list = DeviceInterface::toStringList(type); + for (const QString &cap : cap_list) { QDBusReply reply = d->device.call("QueryCapability", cap); if (!reply.isValid()) { qWarning() << Q_FUNC_INFO << " error: " << reply.error().name() << endl; return false; } if (reply) { d->capListCache.insert(type, true); return true; } } d->capListCache.insert(type, false); return false; } QObject *HalDevice::createDeviceInterface(const Solid::DeviceInterface::Type &type) { if (!queryDeviceInterface(type)) { return nullptr; } DeviceInterface *iface = nullptr; switch (type) { case Solid::DeviceInterface::GenericInterface: iface = new GenericInterface(this); break; case Solid::DeviceInterface::Processor: iface = new Processor(this); break; case Solid::DeviceInterface::Block: iface = new Block(this); break; case Solid::DeviceInterface::StorageAccess: iface = new StorageAccess(this); break; case Solid::DeviceInterface::StorageDrive: iface = new Storage(this); break; case Solid::DeviceInterface::OpticalDrive: iface = new Cdrom(this); break; case Solid::DeviceInterface::StorageVolume: iface = new Volume(this); break; case Solid::DeviceInterface::OpticalDisc: iface = new OpticalDisc(this); break; case Solid::DeviceInterface::Camera: iface = new Camera(this); break; case Solid::DeviceInterface::PortableMediaPlayer: iface = new PortableMediaPlayer(this); break; case Solid::DeviceInterface::Battery: iface = new Battery(this); break; case Solid::DeviceInterface::NetworkShare: break; case Solid::DeviceInterface::Unknown: case Solid::DeviceInterface::Last: break; } return iface; } void HalDevice::slotPropertyModified(int /*count */, const QList &changes) { QMap result; - Q_FOREACH (const ChangeDescription &change, changes) { + for (const ChangeDescription &change : changes) { QString key = change.key; bool added = change.added; bool removed = change.removed; Solid::GenericInterface::PropertyChange type = Solid::GenericInterface::PropertyModified; if (added) { type = Solid::GenericInterface::PropertyAdded; } else if (removed) { type = Solid::GenericInterface::PropertyRemoved; } result[key] = type; d->cache.remove(key); if (d->cache.isEmpty()) { d->cacheSynced = false; d->invalidKeys.clear(); } else { d->invalidKeys.insert(key); } } //qDebug() << this << "unsyncing the cache"; emit propertyChanged(result); } void HalDevice::slotCondition(const QString &condition, const QString &reason) { emit conditionRaised(condition, reason); } QString HalDevice::storageDescription() const { QString description; const Storage storageDrive(const_cast(this)); Solid::StorageDrive::DriveType drive_type = storageDrive.driveType(); bool drive_is_hotpluggable = storageDrive.isHotpluggable(); if (drive_type == Solid::StorageDrive::CdromDrive) { const Cdrom opticalDrive(const_cast(this)); Solid::OpticalDrive::MediumTypes mediumTypes = opticalDrive.supportedMedia(); QString first; QString second; first = tr("CD-ROM", "First item of %1%2 Drive sentence"); if (mediumTypes & Solid::OpticalDrive::Cdr) { first = tr("CD-R", "First item of %1%2 Drive sentence"); } if (mediumTypes & Solid::OpticalDrive::Cdrw) { first = tr("CD-RW", "First item of %1%2 Drive sentence"); } if (mediumTypes & Solid::OpticalDrive::Dvd) { second = tr("/DVD-ROM", "Second item of %1%2 Drive sentence"); } if (mediumTypes & Solid::OpticalDrive::Dvdplusr) { second = tr("/DVD+R", "Second item of %1%2 Drive sentence"); } if (mediumTypes & Solid::OpticalDrive::Dvdplusrw) { second = tr("/DVD+RW", "Second item of %1%2 Drive sentence"); } if (mediumTypes & Solid::OpticalDrive::Dvdr) { second = tr("/DVD-R", "Second item of %1%2 Drive sentence"); } if (mediumTypes & Solid::OpticalDrive::Dvdrw) { second = tr("/DVD-RW", "Second item of %1%2 Drive sentence"); } if (mediumTypes & Solid::OpticalDrive::Dvdram) { second = tr("/DVD-RAM", "Second item of %1%2 Drive sentence"); } if ((mediumTypes & Solid::OpticalDrive::Dvdr) && (mediumTypes & Solid::OpticalDrive::Dvdplusr)) { if (mediumTypes & Solid::OpticalDrive::Dvdplusdl) { second = trUtf8("/DVD±R DL", "Second item of %1%2 Drive sentence"); } else { second = trUtf8("/DVD±R", "Second item of %1%2 Drive sentence"); } } if ((mediumTypes & Solid::OpticalDrive::Dvdrw) && (mediumTypes & Solid::OpticalDrive::Dvdplusrw)) { if ((mediumTypes & Solid::OpticalDrive::Dvdplusdl) || (mediumTypes & Solid::OpticalDrive::Dvdplusdlrw)) { second = trUtf8("/DVD±RW DL", "Second item of %1%2 Drive sentence"); } else { second = trUtf8("/DVD±RW", "Second item of %1%2 Drive sentence"); } } if (mediumTypes & Solid::OpticalDrive::Bd) { second = tr("/BD-ROM", "Second item of %1%2 Drive sentence"); } if (mediumTypes & Solid::OpticalDrive::Bdr) { second = tr("/BD-R", "Second item of %1%2 Drive sentence"); } if (mediumTypes & Solid::OpticalDrive::Bdre) { second = tr("/BD-RE", "Second item of %1%2 Drive sentence"); } if (mediumTypes & Solid::OpticalDrive::HdDvd) { second = tr("/HD DVD-ROM", "Second item of %1%2 Drive sentence"); } if (mediumTypes & Solid::OpticalDrive::HdDvdr) { second = tr("/HD DVD-R", "Second item of %1%2 Drive sentence"); } if (mediumTypes & Solid::OpticalDrive::HdDvdrw) { second = tr("/HD DVD-RW", "Second item of %1%2 Drive sentence"); } if (drive_is_hotpluggable) { description = tr("External %1%2 Drive", "%1 is CD-ROM/CD-R/etc; %2 is '/DVD-ROM'/'/DVD-R'/etc (with leading slash)").arg(first).arg(second); } else { description = tr("%1%2 Drive", "%1 is CD-ROM/CD-R/etc; %2 is '/DVD-ROM'/'/DVD-R'/etc (with leading slash)").arg(first).arg(second); } return description; } if (drive_type == Solid::StorageDrive::Floppy) { if (drive_is_hotpluggable) { description = tr("External Floppy Drive"); } else { description = tr("Floppy Drive"); } return description; } bool drive_is_removable = storageDrive.isRemovable(); if (drive_type == Solid::StorageDrive::HardDisk && !drive_is_removable) { QString size_str = formatByteSize(prop("storage.size").toInt()); if (!size_str.isEmpty()) { if (drive_is_hotpluggable) { description = tr("%1 External Hard Drive", "%1 is the size").arg(size_str); } else { description = tr("%1 Hard Drive", "%1 is the size").arg(size_str); } } else { if (drive_is_hotpluggable) { description = tr("External Hard Drive"); } else { description = tr("Hard Drive"); } } return description; } QString vendormodel_str; QString model = prop("storage.model").toString(); QString vendor = prop("storage.vendor").toString(); if (vendor.isEmpty()) { if (!model.isEmpty()) { vendormodel_str = model; } } else { if (model.isEmpty()) { vendormodel_str = vendor; } else { vendormodel_str = tr("%1 %2", "%1 is the vendor, %2 is the model of the device").arg(vendor).arg(model); } } if (vendormodel_str.isEmpty()) { description = tr("Drive"); } else { description = vendormodel_str; } return description; } QString HalDevice::volumeDescription() const { QString description; QString volume_label = prop("volume.label").toString(); if (!volume_label.isEmpty()) { return volume_label; } if (!d->parent) { d->parent = new HalDevice(parentUdi()); } const Storage storageDrive(const_cast(d->parent)); Solid::StorageDrive::DriveType drive_type = storageDrive.driveType(); /* Handle media in optical drives */ if (drive_type == Solid::StorageDrive::CdromDrive) { const OpticalDisc disc(const_cast(this)); switch (disc.discType()) { case Solid::OpticalDisc::UnknownDiscType: case Solid::OpticalDisc::CdRom: description = tr("CD-ROM"); break; case Solid::OpticalDisc::CdRecordable: if (disc.isBlank()) { description = tr("Blank CD-R"); } else { description = tr("CD-R"); } break; case Solid::OpticalDisc::CdRewritable: if (disc.isBlank()) { description = tr("Blank CD-RW"); } else { description = tr("CD-RW"); } break; case Solid::OpticalDisc::DvdRom: description = tr("DVD-ROM"); break; case Solid::OpticalDisc::DvdRam: if (disc.isBlank()) { description = tr("Blank DVD-RAM"); } else { description = tr("DVD-RAM"); } break; case Solid::OpticalDisc::DvdRecordable: if (disc.isBlank()) { description = tr("Blank DVD-R"); } else { description = tr("DVD-R"); } break; case Solid::OpticalDisc::DvdPlusRecordableDuallayer: if (disc.isBlank()) { description = tr("Blank DVD+R Dual-Layer"); } else { description = tr("DVD+R Dual-Layer"); } break; case Solid::OpticalDisc::DvdRewritable: if (disc.isBlank()) { description = tr("Blank DVD-RW"); } else { description = tr("DVD-RW"); } break; case Solid::OpticalDisc::DvdPlusRecordable: if (disc.isBlank()) { description = tr("Blank DVD+R"); } else { description = tr("DVD+R"); } break; case Solid::OpticalDisc::DvdPlusRewritable: if (disc.isBlank()) { description = tr("Blank DVD+RW"); } else { description = tr("DVD+RW"); } break; case Solid::OpticalDisc::DvdPlusRewritableDuallayer: if (disc.isBlank()) { description = tr("Blank DVD+RW Dual-Layer"); } else { description = tr("DVD+RW Dual-Layer"); } break; case Solid::OpticalDisc::BluRayRom: description = tr("BD-ROM"); break; case Solid::OpticalDisc::BluRayRecordable: if (disc.isBlank()) { description = tr("Blank BD-R"); } else { description = tr("BD-R"); } break; case Solid::OpticalDisc::BluRayRewritable: if (disc.isBlank()) { description = tr("Blank BD-RE"); } else { description = tr("BD-RE"); } break; case Solid::OpticalDisc::HdDvdRom: description = tr("HD DVD-ROM"); break; case Solid::OpticalDisc::HdDvdRecordable: if (disc.isBlank()) { description = tr("Blank HD DVD-R"); } else { description = tr("HD DVD-R"); } break; case Solid::OpticalDisc::HdDvdRewritable: if (disc.isBlank()) { description = tr("Blank HD DVD-RW"); } else { description = tr("HD DVD-RW"); } break; } /* Special case for pure audio disc */ if (disc.availableContent() == Solid::OpticalDisc::Audio) { description = tr("Audio CD"); } return description; } bool drive_is_removable = storageDrive.isRemovable(); bool drive_is_hotpluggable = storageDrive.isHotpluggable(); bool drive_is_encrypted_container = prop("volume.fsusage").toString() == "crypto"; QString size_str = formatByteSize(prop("volume.size").toULongLong()); if (drive_is_encrypted_container) { if (!size_str.isEmpty()) { description = tr("%1 Encrypted Container", "%1 is the size").arg(size_str); } else { description = tr("Encrypted Container"); } } else if (drive_type == Solid::StorageDrive::HardDisk && !drive_is_removable) { if (!size_str.isEmpty()) { if (drive_is_hotpluggable) { description = tr("%1 External Hard Drive", "%1 is the size").arg(size_str); } else { description = tr("%1 Hard Drive", "%1 is the size").arg(size_str); } } else { if (drive_is_hotpluggable) { description = tr("External Hard Drive"); } else { description = tr("Hard Drive"); } } } else { if (drive_is_removable) { description = tr("%1 Removable Media", "%1 is the size").arg(size_str); } else { description = tr("%1 Media", "%1 is the size").arg(size_str); } } return description; } diff --git a/src/solid/devices/backends/hal/halmanager.cpp b/src/solid/devices/backends/hal/halmanager.cpp index 3731e26..c2cb746 100644 --- a/src/solid/devices/backends/hal/halmanager.cpp +++ b/src/solid/devices/backends/hal/halmanager.cpp @@ -1,163 +1,164 @@ /* SPDX-FileCopyrightText: 2005, 2006 Kevin Ottens SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "halmanager.h" #include "haldevice.h" #include "haldeviceinterface.h" #include #include #include #include using namespace Solid::Backends::Hal; class Solid::Backends::Hal::HalManagerPrivate { public: HalManagerPrivate() : manager("org.freedesktop.Hal", "/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager", QDBusConnection::systemBus()), cacheSynced(false) { } QDBusInterface manager; QList devicesCache; bool cacheSynced; QSet supportedInterfaces; }; HalManager::HalManager(QObject *parent) : DeviceManager(parent), d(new HalManagerPrivate()) { d->manager.connection().connect("org.freedesktop.Hal", "/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager", "DeviceAdded", this, SLOT(slotDeviceAdded(QString))); d->manager.connection().connect("org.freedesktop.Hal", "/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager", "DeviceRemoved", this, SLOT(slotDeviceRemoved(QString))); d->supportedInterfaces << Solid::DeviceInterface::GenericInterface << Solid::DeviceInterface::Processor << Solid::DeviceInterface::Block << Solid::DeviceInterface::StorageAccess << Solid::DeviceInterface::StorageDrive << Solid::DeviceInterface::OpticalDrive << Solid::DeviceInterface::StorageVolume << Solid::DeviceInterface::OpticalDisc << Solid::DeviceInterface::Camera << Solid::DeviceInterface::PortableMediaPlayer << Solid::DeviceInterface::Battery; } HalManager::~HalManager() { delete d; } QString HalManager::udiPrefix() const { return "/org/freedesktop/Hal"; } QSet HalManager::supportedInterfaces() const { return d->supportedInterfaces; } QStringList HalManager::allDevices() { if (d->cacheSynced) { return d->devicesCache; } QDBusReply reply = d->manager.call("GetAllDevices"); if (!reply.isValid()) { qWarning() << Q_FUNC_INFO << " error: " << reply.error().name() << endl; return QStringList(); } d->devicesCache = reply; d->cacheSynced = true; return reply; } bool HalManager::deviceExists(const QString &udi) { if (d->devicesCache.contains(udi)) { return true; } else if (d->cacheSynced) { return false; } QDBusReply reply = d->manager.call("DeviceExists", udi); if (!reply.isValid()) { qWarning() << Q_FUNC_INFO << " error: " << reply.error().name() << endl; return false; } if (reply) { d->devicesCache.append(udi); } return reply; } QStringList HalManager::devicesFromQuery(const QString &parentUdi, Solid::DeviceInterface::Type type) { if ((parentUdi.isEmpty()) && (type == Solid::DeviceInterface::Unknown)) { return allDevices(); } QStringList result; - Q_FOREACH (const QString &udi, allDevices()) { + const QStringList deviceList = allDevices(); + for (const QString &udi : deviceList) { HalDevice device(udi); if ((!parentUdi.isEmpty()) && (parentUdi != device.parentUdi())) { continue; } if ((type != Solid::DeviceInterface::Unknown) && (!device.queryDeviceInterface(type))) { continue; } result << udi; } return result; } QObject *HalManager::createDevice(const QString &udi) { if (deviceExists(udi)) { return new HalDevice(udi); } else { return nullptr; } } void HalManager::slotDeviceAdded(const QString &udi) { d->devicesCache.append(udi); emit deviceAdded(udi); } void HalManager::slotDeviceRemoved(const QString &udi) { d->devicesCache.removeAll(udi); emit deviceRemoved(udi); } diff --git a/src/solid/devices/backends/hal/halopticaldisc.cpp b/src/solid/devices/backends/hal/halopticaldisc.cpp index 06c646a..30cd614 100644 --- a/src/solid/devices/backends/hal/halopticaldisc.cpp +++ b/src/solid/devices/backends/hal/halopticaldisc.cpp @@ -1,105 +1,105 @@ /* SPDX-FileCopyrightText: 2006 Kevin Ottens SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "halopticaldisc.h" using namespace Solid::Backends::Hal; OpticalDisc::OpticalDisc(HalDevice *device) : Volume(device) { } OpticalDisc::~OpticalDisc() { } Solid::OpticalDisc::ContentTypes OpticalDisc::availableContent() const { Solid::OpticalDisc::ContentTypes content; - QMap map; - map[Solid::OpticalDisc::Audio] = "volume.disc.has_audio"; - map[Solid::OpticalDisc::Data] = "volume.disc.has_data"; - map[Solid::OpticalDisc::VideoCd] = "volume.disc.is_vcd"; - map[Solid::OpticalDisc::SuperVideoCd] = "volume.disc.is_svcd"; - map[Solid::OpticalDisc::VideoDvd] = "volume.disc.is_videodvd"; - map[Solid::OpticalDisc::VideoBluRay] = "volume.disc.is_blurayvideo"; - - Q_FOREACH (const Solid::OpticalDisc::ContentType type, map.keys()) { - if (m_device->prop(map[type]).toBool()) { - content |= type; + const QMap map = { + {Solid::OpticalDisc::Audio, QStringLiteral("volume.disc.has_audio")}, + {Solid::OpticalDisc::Data, QStringLiteral("volume.disc.has_data")}, + {Solid::OpticalDisc::VideoCd, QStringLiteral("volume.disc.is_vcd")}, + {Solid::OpticalDisc::SuperVideoCd, QStringLiteral("volume.disc.is_svcd")}, + {Solid::OpticalDisc::VideoDvd, QStringLiteral("volume.disc.is_videodvd")}, + {Solid::OpticalDisc::VideoBluRay, QStringLiteral("volume.disc.is_blurayvideo")}}; + + for (auto it = map.cbegin(); it != map.cend(); ++it) { + if (m_device->prop(it.value()).toBool()) { + content |= it.key(); } } return content; } Solid::OpticalDisc::DiscType OpticalDisc::discType() const { QString type = m_device->prop("volume.disc.type").toString(); if (type == "cd_rom") { return Solid::OpticalDisc::CdRom; } else if (type == "cd_r") { return Solid::OpticalDisc::CdRecordable; } else if (type == "cd_rw") { return Solid::OpticalDisc::CdRewritable; } else if (type == "dvd_rom") { return Solid::OpticalDisc::DvdRom; } else if (type == "dvd_ram") { return Solid::OpticalDisc::DvdRam; } else if (type == "dvd_r") { return Solid::OpticalDisc::DvdRecordable; } else if (type == "dvd_rw") { return Solid::OpticalDisc::DvdRewritable; } else if (type == "dvd_plus_r") { return Solid::OpticalDisc::DvdPlusRecordable; } else if (type == "dvd_plus_rw") { return Solid::OpticalDisc::DvdPlusRewritable; } else if (type == "dvd_plus_r_dl") { return Solid::OpticalDisc::DvdPlusRecordableDuallayer; } else if (type == "dvd_plus_rw_dl") { return Solid::OpticalDisc::DvdPlusRewritableDuallayer; } else if (type == "bd_rom") { return Solid::OpticalDisc::BluRayRom; } else if (type == "bd_r") { return Solid::OpticalDisc::BluRayRecordable; } else if (type == "bd_re") { return Solid::OpticalDisc::BluRayRewritable; } else if (type == "hddvd_rom") { return Solid::OpticalDisc::HdDvdRom; } else if (type == "hddvd_r") { return Solid::OpticalDisc::HdDvdRecordable; } else if (type == "hddvd_rw") { return Solid::OpticalDisc::HdDvdRewritable; } else { return Solid::OpticalDisc::UnknownDiscType; } } bool OpticalDisc::isAppendable() const { return m_device->prop("volume.disc.is_appendable").toBool(); } bool OpticalDisc::isBlank() const { return m_device->prop("volume.disc.is_blank").toBool(); } bool OpticalDisc::isRewritable() const { return m_device->prop("volume.disc.is_rewritable").toBool(); } qulonglong OpticalDisc::capacity() const { return m_device->prop("volume.disc.capacity").toULongLong(); } diff --git a/src/solid/devices/backends/iokit/iokitmanager.cpp b/src/solid/devices/backends/iokit/iokitmanager.cpp index 561b9f8..71ff27a 100644 --- a/src/solid/devices/backends/iokit/iokitmanager.cpp +++ b/src/solid/devices/backends/iokit/iokitmanager.cpp @@ -1,229 +1,229 @@ /* SPDX-FileCopyrightText: 2009 Harald Fernengel SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "iokitmanager.h" #include "iokitdevice.h" #include #include #include #include #include namespace Solid { namespace Backends { namespace IOKit { class IOKitManagerPrivate { public: inline IOKitManagerPrivate() : port(nullptr), source(nullptr) {} IONotificationPortRef port; CFRunLoopSourceRef source; static const char *typeToName(Solid::DeviceInterface::Type type); static QStringList devicesFromRegistry(io_iterator_t it); QSet supportedInterfaces; }; // gets all registry paths from an iterator QStringList IOKitManagerPrivate::devicesFromRegistry(io_iterator_t it) { QStringList result; io_object_t obj; io_string_t pathName; while ((obj = IOIteratorNext(it))) { kern_return_t ret = IORegistryEntryGetPath(obj, kIOServicePlane, pathName); if (ret != KERN_SUCCESS) { qWarning() << Q_FUNC_INFO << "IORegistryEntryGetPath failed"; continue; } result += QString::fromUtf8(pathName); ret = IOObjectRelease(obj); if (ret != KERN_SUCCESS) { // very unlikely to happen - keep it a qDebug just in case. // compiler will nuke this code in release builds. qDebug() << Q_FUNC_INFO << "Unable to release object reference"; } } IOObjectRelease(it); return result; } const char *IOKitManagerPrivate::typeToName(Solid::DeviceInterface::Type type) { switch (type) { case Solid::DeviceInterface::Unknown: return 0; case Solid::DeviceInterface::Processor: return "AppleACPICPU"; case Solid::DeviceInterface::Battery: return "AppleSmartBattery"; //Solid::DeviceInterface::GenericInterface: //Solid::DeviceInterface::Block: case Solid::DeviceInterface::StorageAccess: case Solid::DeviceInterface::StorageDrive: case Solid::DeviceInterface::StorageVolume: return "IOMedia"; case Solid::DeviceInterface::OpticalDrive: case Solid::DeviceInterface::OpticalDisc: return "IOCDMedia"; //Solid::DeviceInterface::Camera: //Solid::DeviceInterface::PortableMediaPlayer: } return 0; } IOKitManager::IOKitManager(QObject *parent) : Solid::Ifaces::DeviceManager(parent), d(new IOKitManagerPrivate) { d->port = IONotificationPortCreate(kIOMasterPortDefault); if (!d->port) { qWarning() << Q_FUNC_INFO << "Unable to create notification port"; return; } d->source = IONotificationPortGetRunLoopSource(d->port); if (!d->source) { qWarning() << Q_FUNC_INFO << "Unable to create notification source"; return; } CFRunLoopAddSource(CFRunLoopGetCurrent(), d->source, kCFRunLoopDefaultMode); d->supportedInterfaces << Solid::DeviceInterface::GenericInterface << Solid::DeviceInterface::Processor << Solid::DeviceInterface::Block << Solid::DeviceInterface::StorageAccess << Solid::DeviceInterface::StorageDrive << Solid::DeviceInterface::OpticalDrive << Solid::DeviceInterface::StorageVolume << Solid::DeviceInterface::OpticalDisc << Solid::DeviceInterface::Camera << Solid::DeviceInterface::PortableMediaPlayer << Solid::DeviceInterface::Battery; } IOKitManager::~IOKitManager() { if (d->source) { CFRunLoopRemoveSource(CFRunLoopGetCurrent(), d->source, kCFRunLoopDefaultMode); } if (d->port) { IONotificationPortDestroy(d->port); } delete d; } QString IOKitManager::udiPrefix() const { return QString(); //FIXME: We should probably use a prefix there... has to be tested on Mac } QSet IOKitManager::supportedInterfaces() const { return d->supportedInterfaces; } QStringList IOKitManager::allDevices() { // use an IORegistry Iterator to iterate over all devices in the service plane io_iterator_t it; kern_return_t ret = IORegistryCreateIterator( kIOMasterPortDefault, kIOServicePlane, kIORegistryIterateRecursively, &it); if (ret != KERN_SUCCESS) { qWarning() << Q_FUNC_INFO << "unable to create iterator"; return QStringList(); } return IOKitManagerPrivate::devicesFromRegistry(it); } QStringList IOKitManager::devicesFromQuery(const QString &parentUdi, Solid::DeviceInterface::Type type) { QStringList result; if (type == Solid::DeviceInterface::Unknown) { // match all device interfaces result = allDevices(); } else { const char *deviceClassName = IOKitManagerPrivate::typeToName(type); if (!deviceClassName) { return QStringList(); } CFMutableDictionaryRef matchingDict = IOServiceMatching(deviceClassName); if (!matchingDict) { return QStringList(); } io_iterator_t it = 0; // note - IOServiceGetMatchingServices dereferences the dict kern_return_t ret = IOServiceGetMatchingServices( kIOMasterPortDefault, matchingDict, &it); result = IOKitManagerPrivate::devicesFromRegistry(it); } // if the parentUdi is an empty string, return all matches if (parentUdi.isEmpty()) { return result; } // return only matches that start with the parent's UDI QStringList filtered; - Q_FOREACH (const QString &udi, result) { + for (const QString &udi : qAsConst(result)) { if (udi.startsWith(parentUdi)) { filtered += udi; } } return filtered; } QObject *IOKitManager::createDevice(const QString &udi) { io_registry_entry_t entry = IORegistryEntryFromPath( kIOMasterPortDefault, udi.toLocal8Bit().constData()); // we have to do IOObjectConformsTo - comparing the class names is not good enough //if (IOObjectConformsTo(entry, kIOEthernetInterfaceClass)) { //} if (entry == MACH_PORT_NULL) { return 0; } return new IOKitDevice(udi, entry); } } } } // namespaces diff --git a/src/solid/devices/backends/iokit/iokitopticaldrive.cpp b/src/solid/devices/backends/iokit/iokitopticaldrive.cpp index 86b28b0..7f5bd1f 100644 --- a/src/solid/devices/backends/iokit/iokitopticaldrive.cpp +++ b/src/solid/devices/backends/iokit/iokitopticaldrive.cpp @@ -1,343 +1,344 @@ /* SPDX-FileCopyrightText: 2017 René J.V. Bertin SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "iokitopticaldrive.h" #include #include #ifdef EJECT_USING_DISKARBITRATION // for QCFType: #include #else #include #endif #include #include #include using namespace Solid::Backends::IOKit; class IOKitOpticalDrive::Private { public: Private(const IOKitDevice *device, const QVariantMap &devCharMap) : m_device(device) , m_deviceCharacteristics(devCharMap) { } virtual ~Private() { } QVariant property(const QString &key) const { return m_deviceCharacteristics.value(key); } const IOKitDevice *m_device; const QVariantMap m_deviceCharacteristics; static const QMap cdTypeMap; static const QMap dvdTypeMap; static const QMap bdTypeMap; #ifdef EJECT_USING_DISKARBITRATION // DiskArbitration-based ejection based on the implementation in libcdio's osx.c // in turn based on VideoLAN (VLC) code. // Not activated by default ATM because I have only been able to test it with the // solid-hardware5 utility and that one remains stuck after a successful return // from IOKitOpticalDrive::eject(). It does so too when using the hdiutil external // utility which cannot be due to using QProcess (to the best of my knowledge). // NB: the full-fledged approach using a cancel sourc ref (cancel_signal) etc. may // well be too complicated. typedef struct DAContext { const IOKitDevice *device; int success; bool completed; DASessionRef session; CFRunLoopRef runloop; CFRunLoopSourceRef cancel_signal; } DAContext; static void cancelEjectRunloop(void*) {}; static void daEjectCallback(DADiskRef disk, DADissenterRef dissenter, void *context) { Q_UNUSED(disk); DAContext *daContext = static_cast(context); if (dissenter) { CFStringRef status = DADissenterGetStatusString(dissenter); if (status){ qWarning() << "Warning while ejecting" << daContext->device->property("BSD Name").toString() << ":" << QString::fromCFString(status); CFRelease( status ); } } daContext->success = dissenter ? false : true; daContext->completed = TRUE; CFRunLoopSourceSignal(daContext->cancel_signal); CFRunLoopWakeUp(daContext->runloop); } static void daUnmountCallback(DADiskRef disk, DADissenterRef dissenter, void *context) { DAContext *daContext = (DAContext *)context; if (!dissenter) { DADiskEject(disk, kDADiskEjectOptionDefault, daEjectCallback, context); daContext->success = (daContext->success == -1 ? true : daContext->success); } else { daContext->success = false; daContext->completed = true; CFRunLoopSourceSignal(daContext->cancel_signal); CFRunLoopWakeUp(daContext->runloop); } } bool eject(double timeoutSeconds) { CFDictionaryRef description = nullptr; CFRunLoopSourceContext cancelRunLoopSourceContext = { .perform = cancelEjectRunloop }; DAContext daContext = {m_device, -1 , false, 0, CFRunLoopGetCurrent(), 0}; QCFType cancel = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &cancelRunLoopSourceContext); if (!(daContext.cancel_signal = cancel)) { qWarning() << Q_FUNC_INFO << "failed to create cancel runloop source"; return false; } QCFType session = DASessionCreate(kCFAllocatorDefault); if (!(daContext.session = session)) { qWarning() << Q_FUNC_INFO << "failed to create DiskArbitration session"; return false; } const QString devName = m_device->property(QStringLiteral("BSD Name")).toString(); QCFType daRef = DADiskCreateFromBSDName(kCFAllocatorDefault, daContext.session, devName.toStdString().c_str()); if (!daRef) { qWarning() << Q_FUNC_INFO << "failed to create DiskArbitration reference for" << devName; return false; } description = DADiskCopyDescription(daRef); if (description ){ DASessionScheduleWithRunLoop(daContext.session, daContext.runloop, kCFRunLoopDefaultMode); CFRunLoopAddSource(daContext.runloop, daContext.cancel_signal, kCFRunLoopDefaultMode); if (CFDictionaryGetValueIfPresent(description, kDADiskDescriptionVolumePathKey, nullptr)) { DADiskUnmount(daRef, kDADiskUnmountOptionWhole, daUnmountCallback, &daContext); } DADiskEject(daRef, kDADiskEjectOptionDefault, daEjectCallback, &daContext); daContext.success = (daContext.success == -1 ? true : daContext.success); while (!daContext.completed) { if (CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeoutSeconds, true) == kCFRunLoopRunTimedOut) { break; } } if (daContext.completed) { qWarning() << Q_FUNC_INFO << "ejected" << devName; } else{ qWarning() << Q_FUNC_INFO << "timeout ejecting" << devName; } CFRunLoopRemoveSource(daContext.runloop, daContext.cancel_signal, kCFRunLoopDefaultMode); DASessionSetDispatchQueue(daContext.session, 0); DASessionUnscheduleFromRunLoop(daContext.session, daContext.runloop, kCFRunLoopDefaultMode); CFRelease(description); } else { qWarning() << Q_FUNC_INFO << "failed to fetch DiskArbitration description for" << devName; } return daContext.success == -1 ? false : daContext.success; } #endif //EJECT_USING_DISKARBITRATION }; const QMap IOKitOpticalDrive::Private::cdTypeMap = { {Solid::OpticalDrive::Cdr, kCDFeaturesWriteOnceMask}, {Solid::OpticalDrive::Cdrw, kCDFeaturesReWriteableMask}}; const QMap IOKitOpticalDrive::Private::dvdTypeMap = { {Solid::OpticalDrive::Dvd, kDVDFeaturesReadStructuresMask}, {Solid::OpticalDrive::Dvdr, kDVDFeaturesWriteOnceMask}, {Solid::OpticalDrive::Dvdrw, kDVDFeaturesReWriteableMask}, {Solid::OpticalDrive::Dvdram, kDVDFeaturesRandomWriteableMask}, {Solid::OpticalDrive::Dvdplusr, kDVDFeaturesPlusRMask}, {Solid::OpticalDrive::Dvdplusrw, kDVDFeaturesPlusRWMask}, // not supported: // {Solid::OpticalDrive::Dvdplusdl, "dvdplusrdl"} // {Solid::OpticalDrive::Dvdplusdlrw, "dvdplusrwdl"} {Solid::OpticalDrive::HdDvd, kDVDFeaturesHDReadMask}, {Solid::OpticalDrive::HdDvdr, kDVDFeaturesHDRMask}, {Solid::OpticalDrive::HdDvdrw, kDVDFeaturesHDRWMask}}; const QMap IOKitOpticalDrive::Private::bdTypeMap = { {Solid::OpticalDrive::Bd, kBDFeaturesReadMask}, {Solid::OpticalDrive::Bdr, kBDFeaturesWriteMask}}; // also Solid::OpticalDrive::Bdre IOKitOpticalDrive::IOKitOpticalDrive(IOKitDevice *device) : IOKitStorage(device) { // walk up the IOKit chain to find the parent that has the "Device Characteristics" property // In the examples I've seen this is always the 2nd parent but if ever that turns out // to be non-guaranteed we'll need to do a true walk. IOKitDevice ioDVDServices(IOKitDevice(device->parentUdi()).parentUdi()); QVariantMap devCharMap; if (!ioDVDServices.iOKitPropertyExists(QStringLiteral("Device Characteristics"))) { qWarning() << Q_FUNC_INFO << "Grandparent of" << m_device->udi() << "doesn't have the \"Device Characteristics\" but is" << ioDVDServices.udi(); } else { const QVariant devCharVar = ioDVDServices.property(QStringLiteral("Device Characteristics")); devCharMap = devCharVar.toMap(); } d = new Private(device, devCharMap); } IOKitOpticalDrive::~IOKitOpticalDrive() { } // // Example properties: QMap(("BSD Major", QVariant(int, 1)) // ("BSD Minor", QVariant(int, 12)) // ("BSD Name", QVariant(QString, "disk3")) // ("BSD Unit", QVariant(int, 3)) // ("Content", QVariant(QString, "CD_partition_scheme")) // ("Content Hint", QVariant(QString, "")) // ("Ejectable", QVariant(bool, true)) // ("IOBusyInterest", QVariant(QString, "IOCommand is not serializable")) // ("IOGeneralInterest", QVariant(QString, "IOCommand is not serializable")) // ("IOMediaIcon", QVariant(QVariantMap, QMap(("CFBundleIdentifier", QVariant(QString, "com.apple.iokit.IOCDStorageFamily")) // ("IOBundleResourceFile", QVariant(QString, "CD.icns"))))) // ("Leaf", QVariant(bool, false)) // ("Open", QVariant(bool, true)) // ("Preferred Block Size", QVariant(qlonglong, 2352)) // ("Removable", QVariant(bool, true)) // ("Size", QVariant(qlonglong, 750932448)) // ("TOC", QVariant(QByteArray, "\x00\xA7\x01\x01\x01\x10\x00\xA0\x00\x00\x00\x00\x01\x00\x00\x01\x12\x00\xA1\x00\x00\x00\x00\f\x00\x00\x01\x12\x00\xA2\x00\x00\x00\x00""F:J\x01\x12\x00\x01\x00\x00\x00\x00\x00\x02\x00\x01\x12\x00\x02\x00\x00\x00\x00\x07/\b\x01\x12\x00\x03\x00\x00\x00\x00\x12\b\x0E\x01\x12\x00\x04\x00\x00\x00\x00\x17\x12""0\x01\x12\x00\x05\x00\x00\x00\x00\x1B+ \x01\x12\x00\x06\x00\x00\x00\x00 \x11\n\x01\x12\x00\x07\x00\x00\x00\x00!-\n\x01\x12\x00\b\x00\x00\x00\x00'\f\x1F\x01\x12\x00\t\x00\x00\x00\x00-\x13;\x01\x12\x00\n\x00\x00\x00\x00""4%\x1E\x01\x12\x00\x0B\x00\x00\x00\x00""62 \x01\x12\x00\f\x00\x00\x00\x00""C\x06""E")) // ("Type", QVariant(QString, "CD-ROM")) // ("Whole", QVariant(bool, true)) // ("Writable", QVariant(bool, false)) // ("className", QVariant(QString, "IOCDMedia"))) // // related useful entry: QMap(("Device Characteristics", QVariant(QVariantMap, QMap(("Async Notification", QVariant(bool, false)) // ("BD Features", QVariant(int, 0)) // ("CD Features", QVariant(int, 2047)) // ("DVD Features", QVariant(int, 503)) // ("Fast Spindown", QVariant(bool, true)) // ("Loading Mechanism", QVariant(QString, "Slot")) // ("Low Power Polling", QVariant(bool, false)) // ("Power Off", QVariant(bool, true)) // ("Product Name", QVariant(QString, "DVD-R UJ-8A8")) // ("Product Revision Level", QVariant(QString, "HA13")) // ("Vendor Name", QVariant(QString, "MATSHITA"))))) // ("IOCFPlugInTypes", QVariant(QVariantMap, QMap(("97ABCF2C-23CC-11D5-A0E8-003065704866", QVariant(QString, "IOSCSIArchitectureModelFamily.kext/Contents/PlugIns/SCSITaskUserClient.kext/Contents/PlugIns/SCSITaskLib.plugin"))))) // ("IOGeneralInterest", QVariant(QString, "IOCommand is not serializable")) // ("IOMatchCategory", QVariant(QString, "SCSITaskUserClientIniter")) // ("IOMinimumSegmentAlignmentByteCount", QVariant(qlonglong, 4)) // ("IOUserClientClass", QVariant(QString, "SCSITaskUserClient")) // ("Protocol Characteristics", QVariant(QVariantMap, QMap(("AHCI Port Number", QVariant(qlonglong, 0)) // ("ATAPI", QVariant(bool, true)) // ("Physical Interconnect", QVariant(QString, "SATA")) // ("Physical Interconnect Location", QVariant(QString, "Internal")) // ("Port Speed", QVariant(QString, "1.5 Gigabit")) // ("Read Time Out Duration", QVariant(qlonglong, 15000)) // ("Retry Count", QVariant(qlonglong, 1)) // ("Write Time Out Duration", QVariant(qlonglong, 15000))))) // ("SCSITaskDeviceCategory", QVariant(QString, "SCSITaskAuthoringDevice")) // ("SCSITaskUserClient GUID", QVariant(QByteArray, "\x00]\x0F""F\x80\xFF\xFF\xFFg\xB6\xAB\x1B\x00\x00\x00\x00")) // ("className", QVariant(QString, "IODVDServices")) // ("device-type", QVariant(QString, "DVD"))) // // QMap(("CFBundleIdentifier", QVariant(QString, "com.apple.iokit.IODVDStorageFamily")) // ("IOClass", QVariant(QString, "IODVDBlockStorageDriver")) // ("IOGeneralInterest", QVariant(QString, "IOCommand is not serializable")) // ("IOMatchCategory", QVariant(QString, "IODefaultMatchCategory")) // ("IOProbeScore", QVariant(int, 0)) // ("IOPropertyMatch", QVariant(QVariantMap, QMap(("device-type", QVariant(QString, "DVD"))))) // ("IOProviderClass", QVariant(QString, "IODVDBlockStorageDevice")) // ("Statistics", QVariant(QVariantMap, QMap(("Bytes (Read)", QVariant(qlonglong, 578020608)) // ("Bytes (Write)", QVariant(qlonglong, 0)) // ("Errors (Read)", QVariant(qlonglong, 0)) // ("Errors (Write)", QVariant(qlonglong, 0)) // ("Latency Time (Read)", QVariant(qlonglong, 0)) // ("Latency Time (Write)", QVariant(qlonglong, 0)) // ("Operations (Read)", QVariant(qlonglong, 18475)) // ("Operations (Write)", QVariant(qlonglong, 0)) // ("Retries (Read)", QVariant(qlonglong, 0)) // ("Retries (Write)", QVariant(qlonglong, 0)) // ("Total Time (Read)", QVariant(qlonglong, 219944025102)) // ("Total Time (Write)", QVariant(qlonglong, 0))))) // ("className", QVariant(QString, "IODVDBlockStorageDriver"))) Solid::OpticalDrive::MediumTypes IOKitOpticalDrive::supportedMedia() const { Solid::OpticalDrive::MediumTypes supported; uint32_t cdFeatures = d->property(QStringLiteral("CD Features")).toInt(); uint32_t dvdFeatures = d->property(QStringLiteral("DVD Features")).toInt(); uint32_t bdFeatures = d->property(QStringLiteral("BD Features")).toInt(); qDebug() << Q_FUNC_INFO << "cdFeatures" << cdFeatures << "dvdFeatures" << dvdFeatures << "bdFeatures" << bdFeatures; - foreach (const Solid::OpticalDrive::MediumType type, d->cdTypeMap.keys()) { - if (cdFeatures & d->cdTypeMap[type]) { - supported |= type; + for (auto it = d->cdTypeMap.cbegin(); it != d->cdTypeMap.cend(); ++it) { + if (cdFeatures & it.value()) { + supported |= it.key(); } } - foreach (const Solid::OpticalDrive::MediumType type, d->dvdTypeMap.keys()) { - if (dvdFeatures & d->dvdTypeMap[type]) { - supported |= type; + for (auto it = d->dvdTypeMap.cbegin(); it != d->dvdTypeMap.cend(); ++it) { + if (dvdFeatures & it.value()) { + supported |= it.key(); } } - foreach (const Solid::OpticalDrive::MediumType type, d->bdTypeMap.keys()) { - if (bdFeatures & d->bdTypeMap[type]) { - supported |= type; - if (d->bdTypeMap[type] == kBDFeaturesWriteMask) { + for (auto it = d->bdTypeMap.cbegin(); it != d->bdTypeMap.cend(); ++it) { + const uint32_t value = it.value(); + if (bdFeatures & value) { + supported |= it.key(); + if (value == kBDFeaturesWriteMask) { supported |= Solid::OpticalDrive::Bdre; } } } return supported; } int IOKitOpticalDrive::readSpeed() const { return 0; } int IOKitOpticalDrive::writeSpeed() const { return 0; } QList IOKitOpticalDrive::writeSpeeds() const { return {}; } bool IOKitOpticalDrive::eject() { #ifdef EJECT_USING_DISKARBITRATION // give the devices 30 seconds to eject int error = !d->eject(30.0); #else QProcess ejectJob; int error = ejectJob.execute(QStandardPaths::findExecutable(QStringLiteral("hdiutil")), {QStringLiteral("detach"), QStringLiteral("-verbose"), QStringLiteral("/dev/") + m_device->property(QStringLiteral("BSD Name")).toString()}); if (error) { qWarning() << "hdiutil returned" << error << "trying to eject" << m_device->product(); } #endif //EJECT_USING_DISKARBITRATION if (error) { emit ejectDone(Solid::ErrorType::OperationFailed, QVariant(), m_device->udi()); return false; } else { emit ejectDone(Solid::ErrorType::NoError, QVariant(), m_device->udi()); return true; } } diff --git a/src/solid/devices/backends/iokit/iokitstorageaccess.cpp b/src/solid/devices/backends/iokit/iokitstorageaccess.cpp index 77886e3..4f70918 100644 --- a/src/solid/devices/backends/iokit/iokitstorageaccess.cpp +++ b/src/solid/devices/backends/iokit/iokitstorageaccess.cpp @@ -1,95 +1,95 @@ /* SPDX-FileCopyrightText: 2017 René J.V. Bertin SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "iokitstorageaccess.h" #include #include using namespace Solid::Backends::IOKit; IOKitStorageAccess::IOKitStorageAccess(IOKitDevice *device) : DeviceInterface(device) , daDict(new DADictionary(device)) { connect(device, SIGNAL(propertyChanged(QMap)), this, SLOT(onPropertyChanged(QMap))); } IOKitStorageAccess::IOKitStorageAccess(const IOKitDevice *device) : DeviceInterface(device) , daDict(new DADictionary(device)) { connect(device, SIGNAL(propertyChanged(QMap)), this, SLOT(onPropertyChanged(QMap))); } IOKitStorageAccess::~IOKitStorageAccess() { delete daDict; } bool IOKitStorageAccess::isAccessible() const { filePath(); const QVariant isMounted = m_device->property(QStringLiteral("isMounted")); return isMounted.isValid() && isMounted.toBool(); } QString IOKitStorageAccess::filePath() const { // mount points can change (but can they between invocations of filePath()?) QString mountPoint; if (const CFURLRef urlRef = daDict->cfUrLRefForKey(kDADiskDescriptionVolumePathKey)) { const CFStringRef mpRef = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle); mountPoint = QString::fromCFString(mpRef); CFRelease(mpRef); m_device->setProperty("mountPoint", QVariant(mountPoint)); bool isMounted = !mountPoint.isEmpty(); const QString isMountedKey = QStringLiteral("isMounted"); const QVariant wasMounted = m_device->property(isMountedKey); if (wasMounted.isValid() && wasMounted.toBool() != isMounted) { IOKitStorageAccess(m_device).onPropertyChanged(QMap{{isMountedKey,isMounted}}); } m_device->setProperty("isMounted", QVariant(isMounted)); } return mountPoint; } bool IOKitStorageAccess::isIgnored() const { if (m_device->iOKitPropertyExists(QStringLiteral("Open"))) { // ignore storage volumes that aren't mounted bool isIgnored = m_device->property(QStringLiteral("Open")).toBool() == false; m_device->setProperty("isIgnored", QVariant(isIgnored)); return isIgnored; } const QVariant isIgnored = m_device->property(QStringLiteral("isIgnored")); return isIgnored.isValid() && isIgnored.toBool(); } bool IOKitStorageAccess::setup() { // TODO? return false; } bool IOKitStorageAccess::teardown() { // TODO? return false; } void IOKitStorageAccess::onPropertyChanged(const QMap &changes) { - Q_FOREACH (const QString &property, changes.keys()) { - if (property == QStringLiteral("isMounted")) { + for (auto it = changes.cbegin(); it != changes.cend(); ++it) { + if (it.key() == QLatin1String("isMounted")) { emit accessibilityChanged(m_device->property(QStringLiteral("isMounted")).toBool(), m_device->udi()); } } } diff --git a/src/solid/devices/backends/shared/udevqtclient.cpp b/src/solid/devices/backends/shared/udevqtclient.cpp index 3bac24f..e363742 100644 --- a/src/solid/devices/backends/shared/udevqtclient.cpp +++ b/src/solid/devices/backends/shared/udevqtclient.cpp @@ -1,276 +1,276 @@ /* SPDX-FileCopyrightText: 2009 Benjamin K. Stuhl SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "udevqtclient.h" #include "udevqt_p.h" #include #include namespace UdevQt { ClientPrivate::ClientPrivate(Client *q_) : udev(nullptr), monitor(nullptr), q(q_), monitorNotifier(nullptr) { } ClientPrivate::~ClientPrivate() { udev_unref(udev); delete monitorNotifier; if (monitor) { udev_monitor_unref(monitor); } } void ClientPrivate::init(const QStringList &subsystemList, ListenToWhat what) { udev = udev_new(); if (what != ListenToNone) { setWatchedSubsystems(subsystemList); } } 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 - Q_FOREACH (const QString &subsysDevtype, subsystemList) { + for (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(), nullptr); } } // 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); monitorNotifier->setEnabled(false); struct udev_device *dev = udev_monitor_receive_device(monitor); monitorNotifier->setEnabled(true); if (!dev) { return; } Device device(new DevicePrivate(dev, false)); QByteArray action(udev_device_get_action(dev)); if (action == "add") { emit q->deviceAdded(device); } else if (action == "remove") { emit q->deviceRemoved(device); } else if (action == "change") { emit q->deviceChanged(device); } else if (action == "online") { emit q->deviceOnlined(device); } else if (action == "offline") { emit q->deviceOfflined(device); } else if (action == "bind") { emit q->deviceBound(device); } else if (action == "unbind") { emit q->deviceUnbound(device); } else { qWarning("UdevQt: unhandled device action \"%s\"", action.constData()); } } DeviceList ClientPrivate::deviceListFromEnumerate(struct udev_enumerate *en) { DeviceList ret; struct udev_list_entry *list, *entry; udev_enumerate_scan_devices(en); 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)); if (!ud) { continue; } ret << Device(new DevicePrivate(ud, false)); } udev_enumerate_unref(en); return ret; } Client::Client(QObject *parent) : QObject(parent) , d(new ClientPrivate(this)) { d->init(QStringList(), ClientPrivate::ListenToNone); } Client::Client(const QStringList &subsystemList, QObject *parent) : QObject(parent) , d(new ClientPrivate(this)) { d->init(subsystemList, ClientPrivate::ListenToList); } 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::devicesByProperty(const QString &property, const QVariant &value) { struct udev_enumerate *en = udev_enumerate_new(d->udev); if (value.isValid()) { udev_enumerate_add_match_property(en, property.toLatin1().constData(), value.toString().toLatin1().constData()); } else { udev_enumerate_add_match_property(en, property.toLatin1().constData(), nullptr); } return d->deviceListFromEnumerate(en); } DeviceList Client::allDevices() { struct udev_enumerate *en = udev_enumerate_new(d->udev); return d->deviceListFromEnumerate(en); } DeviceList Client::devicesBySubsystem(const QString &subsystem) { struct udev_enumerate *en = udev_enumerate_new(d->udev); udev_enumerate_add_match_subsystem(en, subsystem.toLatin1().constData()); return d->deviceListFromEnumerate(en); } DeviceList Client::devicesBySubsystemsAndProperties(const QStringList &subsystems, const QVariantMap &properties) { struct udev_enumerate *en = udev_enumerate_new(d->udev); for (const QString &subsystem : subsystems) { udev_enumerate_add_match_subsystem(en, subsystem.toLatin1().constData()); } for (auto it = properties.begin(), end = properties.end(); it != end; ++it) { if (it.value().isValid()) { udev_enumerate_add_match_property(en, it.key().toLatin1().constData(), it.value().toString().toLatin1().constData()); } else { udev_enumerate_add_match_property(en, it.key().toLatin1().constData(), nullptr); } } return d->deviceListFromEnumerate(en); } Device Client::deviceByDeviceFile(const QString &deviceFile) { QT_STATBUF sb; if (QT_STAT(deviceFile.toLatin1().constData(), &sb) != 0) { return Device(); } struct udev_device *ud = nullptr; if (S_ISBLK(sb.st_mode)) { ud = udev_device_new_from_devnum(d->udev, 'b', sb.st_rdev); } else if (S_ISCHR(sb.st_mode)) { ud = udev_device_new_from_devnum(d->udev, 'c', sb.st_rdev); } if (!ud) { return Device(); } return Device(new DevicePrivate(ud, false)); } Device Client::deviceBySysfsPath(const QString &sysfsPath) { struct udev_device *ud = udev_device_new_from_syspath(d->udev, sysfsPath.toLatin1().constData()); if (!ud) { return Device(); } return Device(new DevicePrivate(ud, false)); } Device Client::deviceBySubsystemAndName(const QString &subsystem, const QString &name) { struct udev_device *ud = udev_device_new_from_subsystem_sysname(d->udev, subsystem.toLatin1().constData(), name.toLatin1().constData()); if (!ud) { return Device(); } return Device(new DevicePrivate(ud, false)); } } #include "moc_udevqtclient.cpp" diff --git a/src/solid/devices/backends/udev/cpuinfo.cpp b/src/solid/devices/backends/udev/cpuinfo.cpp index 2ee8c44..92158cb 100644 --- a/src/solid/devices/backends/udev/cpuinfo.cpp +++ b/src/solid/devices/backends/udev/cpuinfo.cpp @@ -1,115 +1,115 @@ /* SPDX-FileCopyrightText: 2010 Alex Merry SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "cpuinfo.h" #include #include #include namespace Solid { namespace Backends { namespace UDev { class CpuInfo { public: CpuInfo(); QString extractCpuInfoLine(int processorNumber, const QString ®ExpStr); QString extractInfoLine(const QString ®ExpStr); private: QStringList cpuInfo; }; QString extractCpuVendor(int processorNumber) { CpuInfo info; QString vendor = info.extractCpuInfoLine(processorNumber, "vendor_id\\s+:\\s+(\\S.+)"); if (vendor.isEmpty()) { vendor = info.extractInfoLine("Hardware\\s+:\\s+(\\S.+)"); } return vendor; } QString extractCpuModel(int processorNumber) { CpuInfo info; QString model = info.extractCpuInfoLine(processorNumber, "model name\\s+:\\s+(\\S.+)"); if (model.isEmpty()) { model = info.extractInfoLine("Processor\\s+:\\s+(\\S.+)"); } return model; } int extractCurrentCpuSpeed(int processorNumber) { CpuInfo info; int speed = info.extractCpuInfoLine(processorNumber, "cpu MHz\\s+:\\s+(\\d+).*").toInt(); return speed; } CpuInfo::CpuInfo() { QFile cpuInfoFile("/proc/cpuinfo"); if (!cpuInfoFile.open(QIODevice::ReadOnly)) { return; } #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) cpuInfo = QString(cpuInfoFile.readAll()).split('\n', QString::SkipEmptyParts); #else cpuInfo = QString(cpuInfoFile.readAll()).split('\n', Qt::SkipEmptyParts); #endif } QString CpuInfo::extractCpuInfoLine(int processorNumber, const QString ®ExpStr) { const QRegularExpression processorRegExp( QRegularExpression::anchoredPattern(QStringLiteral("processor\\s+:\\s+(\\d+)"))); const QRegularExpression regExp(QRegularExpression::anchoredPattern(regExpStr)); int line = 0; while (line < cpuInfo.size()) { QRegularExpressionMatch match; if ((match = processorRegExp.match(cpuInfo.at(line))).hasMatch()) { int recordProcNum = match.captured(1).toInt(); if (recordProcNum == processorNumber) { ++line; while (line < cpuInfo.size()) { if ((match = regExp.match(cpuInfo.at(line))).hasMatch()) { return match.captured(1); } ++line; } } } ++line; } return QString(); } QString CpuInfo::extractInfoLine(const QString ®ExpStr) { const QRegularExpression regExp(QRegularExpression::anchoredPattern(regExpStr)); - foreach (const QString &line, cpuInfo) { + for (const QString &line : qAsConst(cpuInfo)) { QRegularExpressionMatch match = regExp.match(line); if (match.hasMatch()) { return match.captured(1); } } return QString(); } } } } diff --git a/src/solid/devices/backends/udev/udevdevice.cpp b/src/solid/devices/backends/udev/udevdevice.cpp index 89600be..b1555c8 100644 --- a/src/solid/devices/backends/udev/udevdevice.cpp +++ b/src/solid/devices/backends/udev/udevdevice.cpp @@ -1,226 +1,227 @@ /* SPDX-FileCopyrightText: 2010 Rafael Fernández López SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "udevdevice.h" #include "udevgenericinterface.h" #include "udevprocessor.h" #include "udevcamera.h" #include "udevportablemediaplayer.h" #include "udevblock.h" #include "cpuinfo.h" #include #include using namespace Solid::Backends::UDev; UDevDevice::UDevDevice(const UdevQt::Device device) : Solid::Ifaces::Device() , m_device(device) { } UDevDevice::~UDevDevice() { } QString UDevDevice::udi() const { return devicePath(); } QString UDevDevice::parentUdi() const { return UDEV_UDI_PREFIX; } QString UDevDevice::vendor() const { QString vendor = m_device.sysfsProperty("manufacturer").toString(); if (vendor.isEmpty()) { if (queryDeviceInterface(Solid::DeviceInterface::Processor)) { // sysfs doesn't have anything useful here vendor = extractCpuVendor(deviceNumber()); } if (vendor.isEmpty()) { vendor = m_device.deviceProperty("ID_VENDOR").toString().replace('_', ' '); } } return vendor; } QString UDevDevice::product() const { QString product = m_device.sysfsProperty("product").toString(); if (product.isEmpty()) { if (queryDeviceInterface(Solid::DeviceInterface::Processor)) { // sysfs doesn't have anything useful here product = extractCpuModel(deviceNumber()); } if (product.isEmpty()) { product = m_device.deviceProperty("ID_MODEL").toString().replace('_', ' '); } } return product; } QString UDevDevice::icon() const { if (parentUdi().isEmpty()) { return QLatin1String("computer"); } if (queryDeviceInterface(Solid::DeviceInterface::Processor)) { return QLatin1String("cpu"); } else if (queryDeviceInterface(Solid::DeviceInterface::PortableMediaPlayer)) { // TODO: check out special cases like iPod return QLatin1String("multimedia-player"); } else if (queryDeviceInterface(Solid::DeviceInterface::Camera)) { return QLatin1String("camera-photo"); } return QString(); } QStringList UDevDevice::emblems() const { return QStringList(); } QString UDevDevice::description() const { if (parentUdi().isEmpty()) { return tr("Computer"); } if (queryDeviceInterface(Solid::DeviceInterface::Processor)) { return tr("Processor"); } else if (queryDeviceInterface(Solid::DeviceInterface::PortableMediaPlayer)) { /* * HACK: As Media player is very generic return the device product instead * until we can return the Name. */ const PortableMediaPlayer *player = new PortableMediaPlayer(const_cast(this)); if (player->supportedProtocols().contains("mtp")) { return product(); } else { // TODO: check out special cases like iPod return tr("Portable Media Player"); } } else if (queryDeviceInterface(Solid::DeviceInterface::Camera)) { return tr("Camera"); } return QString(); } bool UDevDevice::queryDeviceInterface(const Solid::DeviceInterface::Type &type) const { switch (type) { case Solid::DeviceInterface::GenericInterface: return true; case Solid::DeviceInterface::Processor: return m_device.subsystem() == QLatin1String("cpu"); case Solid::DeviceInterface::Camera: return m_device.subsystem() == QLatin1String("usb") && property("ID_GPHOTO2").isValid(); case Solid::DeviceInterface::PortableMediaPlayer: return m_device.subsystem() == QLatin1String("usb") && property("ID_MEDIA_PLAYER").isValid(); case Solid::DeviceInterface::Block: return !property("MAJOR").toString().isEmpty(); default: return false; } } QObject *UDevDevice::createDeviceInterface(const Solid::DeviceInterface::Type &type) { if (!queryDeviceInterface(type)) { return nullptr; } switch (type) { case Solid::DeviceInterface::GenericInterface: return new GenericInterface(this); case Solid::DeviceInterface::Processor: return new Processor(this); case Solid::DeviceInterface::Camera: return new Camera(this); case Solid::DeviceInterface::PortableMediaPlayer: return new PortableMediaPlayer(this); case Solid::DeviceInterface::Block: return new Block(this); default: qFatal("Shouldn't happen"); return nullptr; } } QString UDevDevice::device() const { return devicePath(); } QVariant UDevDevice::property(const QString &key) const { const QVariant res = m_device.deviceProperty(key); if (res.isValid()) { return res; } return m_device.sysfsProperty(key); } QMap UDevDevice::allProperties() const { QMap res; - Q_FOREACH (const QString &prop, m_device.deviceProperties()) { + const QStringList properties = m_device.deviceProperties(); + for (const QString &prop : properties) { res[prop] = property(prop); } return res; } bool UDevDevice::propertyExists(const QString &key) const { return m_device.deviceProperties().contains(key); } QString UDevDevice::systemAttribute(const char *attribute) const { return m_device.sysfsProperty(attribute).toString(); } QString UDevDevice::deviceName() const { return m_device.sysfsPath(); } int UDevDevice::deviceNumber() const { return m_device.sysfsNumber(); } QString UDevDevice::devicePath() const { return QString(UDEV_UDI_PREFIX) + deviceName(); } UdevQt::Device UDevDevice::udevDevice() { return m_device; } diff --git a/src/solid/devices/backends/udev/udevmanager.cpp b/src/solid/devices/backends/udev/udevmanager.cpp index ebd781c..abfbf6f 100644 --- a/src/solid/devices/backends/udev/udevmanager.cpp +++ b/src/solid/devices/backends/udev/udevmanager.cpp @@ -1,247 +1,249 @@ /* SPDX-FileCopyrightText: 2010 Rafael Fernández López SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "udevmanager.h" #include "udev.h" #include "udevdevice.h" #include "../shared/rootdevice.h" #include #include #include using namespace Solid::Backends::UDev; using namespace Solid::Backends::Shared; class UDevManager::Private { public: Private(); ~Private(); bool isOfInterest(const QString &udi, const UdevQt::Device &device); bool checkOfInterest(const UdevQt::Device &device); UdevQt::Client *m_client; QStringList m_devicesOfInterest; QSet m_supportedInterfaces; }; UDevManager::Private::Private() { QStringList subsystems; subsystems << "processor"; subsystems << "cpu"; subsystems << "sound"; subsystems << "tty"; subsystems << "dvb"; subsystems << "net"; subsystems << "usb"; subsystems << "input"; m_client = new UdevQt::Client(subsystems); } UDevManager::Private::~Private() { delete m_client; } bool UDevManager::Private::isOfInterest(const QString &udi, const UdevQt::Device &device) { if (m_devicesOfInterest.contains(udi)) { return true; } bool isOfInterest = checkOfInterest(device); if (isOfInterest) { m_devicesOfInterest.append(udi); } return isOfInterest; } bool UDevManager::Private::checkOfInterest(const UdevQt::Device &device) { const QString subsystem = device.subsystem(); #ifdef UDEV_DETAILED_OUTPUT qDebug() << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"; qDebug() << "Path:" << device.sysfsPath(); qDebug() << "Properties:" << device.deviceProperties(); - Q_FOREACH (const QString &key, device.deviceProperties()) { + + const QStringList properties = device.deviceProperties(); + for (const QString &key : properties) { qDebug() << "\t" << key << ":" << device.deviceProperty(key).toString(); } qDebug() << "Driver:" << device.driver(); qDebug() << "Subsystem:" << subsystem; qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"; #endif if (subsystem == QLatin1String("cpu")) { // Linux ACPI reports processor slots, rather than processors. // Empty slots will not have a system device associated with them. return QFile::exists(device.sysfsPath() + "/sysdev") || QFile::exists(device.sysfsPath() + "/cpufreq") || QFile::exists(device.sysfsPath() + "/topology/core_id"); } if (subsystem == QLatin1String("sound") && device.deviceProperty("SOUND_FORM_FACTOR").toString() != "internal") { return true; } if (subsystem == QLatin1String("tty")) { QString path = device.deviceProperty("DEVPATH").toString(); int lastSlash = path.length() - path.lastIndexOf(QLatin1String("/")) - 1; QByteArray lastElement = path.right(lastSlash).toLatin1(); if (lastElement.startsWith("tty") && !path.startsWith("/devices/virtual")) { return true; } } if (subsystem == QLatin1String("input")) { if (device.deviceProperty("ID_INPUT_MOUSE").toInt() == 1 || device.deviceProperty("ID_INPUT_TOUCHPAD").toInt() == 1 || device.deviceProperty("ID_INPUT_TABLET").toInt() == 1 || device.deviceProperty("ID_INPUT_TOUCHSCREEN").toInt() == 1) { return true; } } return subsystem == QLatin1String("dvb") || subsystem == QLatin1String("net") || (!device.deviceProperty("ID_MEDIA_PLAYER").toString().isEmpty() && device.parent().deviceProperty("ID_MEDIA_PLAYER").toString().isEmpty()) || // media-player-info recognized devices (device.deviceProperty("ID_GPHOTO2").toInt() == 1 && device.parent().deviceProperty("ID_GPHOTO2").toInt() != 1); // GPhoto2 cameras } UDevManager::UDevManager(QObject *parent) : Solid::Ifaces::DeviceManager(parent), d(new Private) { connect(d->m_client, SIGNAL(deviceAdded(UdevQt::Device)), this, SLOT(slotDeviceAdded(UdevQt::Device))); connect(d->m_client, SIGNAL(deviceRemoved(UdevQt::Device)), this, SLOT(slotDeviceRemoved(UdevQt::Device))); d->m_supportedInterfaces << Solid::DeviceInterface::GenericInterface << Solid::DeviceInterface::Processor << Solid::DeviceInterface::Camera << Solid::DeviceInterface::PortableMediaPlayer << Solid::DeviceInterface::Block ; } UDevManager::~UDevManager() { delete d; } QString UDevManager::udiPrefix() const { return QString::fromLatin1(UDEV_UDI_PREFIX); } QSet UDevManager::supportedInterfaces() const { return d->m_supportedInterfaces; } QStringList UDevManager::allDevices() { QStringList res; const UdevQt::DeviceList deviceList = d->m_client->allDevices(); - Q_FOREACH (const UdevQt::Device &device, deviceList) { + for (const UdevQt::Device &device : deviceList) { if (d->isOfInterest(udiPrefix() + device.sysfsPath(), device)) { res << udiPrefix() + device.sysfsPath(); } } return res; } QStringList UDevManager::devicesFromQuery(const QString &parentUdi, Solid::DeviceInterface::Type type) { QStringList result; if (!parentUdi.isEmpty()) { const UdevQt::DeviceList deviceList = d->m_client->allDevices(); for (const UdevQt::Device &dev : deviceList) { UDevDevice device(dev); if (device.queryDeviceInterface(type) && d->isOfInterest(udiPrefix() + dev.sysfsPath(), dev) && device.parentUdi() == parentUdi) { result << udiPrefix() + dev.sysfsPath(); } } return result; } if (type == DeviceInterface::Unknown) { return allDevices(); } UdevQt::DeviceList deviceList; // Already limit the number of devices we query and have to create wrapper items for here if (type == Solid::DeviceInterface::Processor) { deviceList = d->m_client->devicesBySubsystem(QStringLiteral("processor")) + d->m_client->devicesBySubsystem(QStringLiteral("cpu")); } else if (type == Solid::DeviceInterface::Camera) { deviceList = d->m_client->devicesBySubsystemsAndProperties({ QStringLiteral("usb"), }, { {QStringLiteral("ID_GPHOTO2"), QStringLiteral("*")} // match any }); } else if (type == Solid::DeviceInterface::PortableMediaPlayer) { deviceList = d->m_client->devicesBySubsystemsAndProperties({ QStringLiteral("usb"), }, { {QStringLiteral("ID_MEDIA_PLAYER"), QStringLiteral("*")} // match any }); } else { deviceList = d->m_client->allDevices(); } for (const UdevQt::Device &dev : qAsConst(deviceList)) { UDevDevice device(dev); if (device.queryDeviceInterface(type) && d->isOfInterest(udiPrefix() + dev.sysfsPath(), dev)) { result << udiPrefix() + dev.sysfsPath(); } } return result; } QObject *UDevManager::createDevice(const QString &udi_) { if (udi_ == udiPrefix()) { RootDevice *const device = new RootDevice(UDEV_UDI_PREFIX); device->setProduct(tr("Devices")); device->setDescription(tr("Devices declared in your system")); device->setIcon("computer"); return device; } const QString udi = udi_.right(udi_.size() - udiPrefix().size()); UdevQt::Device device = d->m_client->deviceBySysfsPath(udi); if (d->isOfInterest(udi_, device) || QFile::exists(udi)) { return new UDevDevice(device); } return nullptr; } void UDevManager::slotDeviceAdded(const UdevQt::Device &device) { if (d->isOfInterest(udiPrefix() + device.sysfsPath(), device)) { emit deviceAdded(udiPrefix() + device.sysfsPath()); } } void UDevManager::slotDeviceRemoved(const UdevQt::Device &device) { if (d->isOfInterest(udiPrefix() + device.sysfsPath(), device)) { emit deviceRemoved(udiPrefix() + device.sysfsPath()); d->m_devicesOfInterest.removeAll(udiPrefix() + device.sysfsPath()); } } diff --git a/src/solid/devices/backends/udisks2/udisksdevicebackend.cpp b/src/solid/devices/backends/udisks2/udisksdevicebackend.cpp index 80a9076..7287d83 100644 --- a/src/solid/devices/backends/udisks2/udisksdevicebackend.cpp +++ b/src/solid/devices/backends/udisks2/udisksdevicebackend.cpp @@ -1,243 +1,244 @@ /* SPDX-FileCopyrightText: 2010 Michael Zanetti SPDX-FileCopyrightText: 2010-2012 Lukáš Tinkl SPDX-FileCopyrightText: 2012 Dan Vrátil SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "udisksdevicebackend.h" #include "udisks_debug.h" #include #include #include #include "solid/deviceinterface.h" #include "solid/genericinterface.h" using namespace Solid::Backends::UDisks2; /* Static cache for DeviceBackends for all UDIs */ QThreadStorage> DeviceBackend::s_backends; DeviceBackend *DeviceBackend::backendForUDI(const QString &udi, bool create) { DeviceBackend *backend = nullptr; if (udi.isEmpty()) { return backend; } backend = s_backends.localData().value(udi); if (!backend && create) { backend = new DeviceBackend(udi); s_backends.localData().insert(udi, backend); } return backend; } void DeviceBackend::destroyBackend(const QString &udi) { delete s_backends.localData().take(udi); } DeviceBackend::DeviceBackend(const QString &udi) : m_udi(udi) { //qDebug() << "Creating backend for device" << m_udi; m_device = new QDBusInterface(UD2_DBUS_SERVICE, m_udi, QString(), // no interface, we aggregate them QDBusConnection::systemBus(), this); if (m_device->isValid()) { QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, m_udi, DBUS_INTERFACE_PROPS, "PropertiesChanged", this, SLOT(slotPropertiesChanged(QString,QVariantMap,QStringList))); QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, UD2_DBUS_PATH, DBUS_INTERFACE_MANAGER, "InterfacesAdded", this, SLOT(slotInterfacesAdded(QDBusObjectPath,VariantMapMap))); QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, UD2_DBUS_PATH, DBUS_INTERFACE_MANAGER, "InterfacesRemoved", this, SLOT(slotInterfacesRemoved(QDBusObjectPath,QStringList))); initInterfaces(); } } DeviceBackend::~DeviceBackend() { //qDebug() << "Destroying backend for device" << m_udi; } void DeviceBackend::initInterfaces() { m_interfaces.clear(); const QString xmlData = introspect(); if (xmlData.isEmpty()) { qCDebug(UDISKS2) << m_udi << "has no interfaces!"; return; } QDomDocument dom; dom.setContent(xmlData); QDomNodeList ifaceNodeList = dom.elementsByTagName("interface"); for (int i = 0; i < ifaceNodeList.count(); i++) { QDomElement ifaceElem = ifaceNodeList.item(i).toElement(); /* Accept only org.freedesktop.UDisks2.* interfaces so that when the device is unplugged, * m_interfaces goes empty and we can easily verify that the device is gone. */ if (!ifaceElem.isNull() && ifaceElem.attribute("name").startsWith(UD2_DBUS_SERVICE)) { m_interfaces.append(ifaceElem.attribute("name")); } } //qDebug() << m_udi << "has interfaces:" << m_interfaces; } QStringList DeviceBackend::interfaces() const { return m_interfaces; } const QString &DeviceBackend::udi() const { return m_udi; } QVariant DeviceBackend::prop(const QString &key) const { checkCache(key); return m_propertyCache.value(key); } bool DeviceBackend::propertyExists(const QString &key) const { checkCache(key); /* checkCache() will put an invalid QVariant in cache when the property * does not exist, so check for validity, not for an actual presence. */ return m_propertyCache.value(key).isValid(); } QVariantMap DeviceBackend::allProperties() const { QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, m_udi, DBUS_INTERFACE_PROPS, "GetAll"); - Q_FOREACH (const QString &iface, m_interfaces) { + for (const QString &iface : qAsConst(m_interfaces)) { call.setArguments(QVariantList() << iface); QDBusPendingReply reply = QDBusConnection::systemBus().call(call); if (reply.isValid()) { auto props = reply.value(); // Can not use QMap<>::unite(), as it allows multiple values per key for (auto it = props.cbegin(); it != props.cend(); ++it) { m_propertyCache.insert(it.key(), it.value()); } } else { qCWarning(UDISKS2) << "Error getting props:" << reply.error().name() << reply.error().message(); } //qDebug() << "After iface" << iface << ", cache now contains" << m_propertyCache.size() << "items"; } return m_propertyCache; } void DeviceBackend::invalidateProperties() { m_propertyCache.clear(); } QString DeviceBackend::introspect() const { QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, m_udi, DBUS_INTERFACE_INTROSPECT, "Introspect"); QDBusPendingReply reply = QDBusConnection::systemBus().call(call); if (reply.isValid()) { return reply.value(); } else { return QString(); } } void DeviceBackend::checkCache(const QString &key) const { if (m_propertyCache.isEmpty()) { // recreate the cache allProperties(); } if (m_propertyCache.contains(key)) { return; } QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, m_udi, DBUS_INTERFACE_PROPS, "Get"); /* * Interface is set to an empty string as in this QDBusInterface is a meta-object of multiple interfaces on the same path * The DBus properties also interface supports this, and will find the appropriate interface if none is explicitly set. * This matches what QDBusAbstractInterface would do */ call.setArguments(QVariantList() << QString() << key); QDBusPendingReply reply = QDBusConnection::systemBus().call(call); /* We don't check for error here and store the item in the cache anyway so next time we don't have to * do the DBus call to find out it does not exist but just check whether * prop(key).isValid() */ m_propertyCache.insert(key, reply.value()); } void DeviceBackend::slotPropertiesChanged(const QString &ifaceName, const QVariantMap &changedProps, const QStringList &invalidatedProps) { if (!ifaceName.startsWith(UD2_DBUS_SERVICE)) { return; } //qDebug() << m_udi << "'s interface" << ifaceName << "changed props:"; QMap changeMap; - Q_FOREACH (const QString &key, invalidatedProps) { + for (const QString &key : invalidatedProps) { m_propertyCache.remove(key); changeMap.insert(key, Solid::GenericInterface::PropertyModified); //qDebug() << "\t invalidated:" << key; } QMapIterator i(changedProps); while (i.hasNext()) { i.next(); const QString key = i.key(); m_propertyCache.insert(key, i.value()); // replace the value changeMap.insert(key, Solid::GenericInterface::PropertyModified); //qDebug() << "\t modified:" << key << ":" << m_propertyCache.value(key); } emit propertyChanged(changeMap); emit changed(); } void DeviceBackend::slotInterfacesAdded(const QDBusObjectPath &object_path, const VariantMapMap &interfaces_and_properties) { if (object_path.path() != m_udi) { return; } - Q_FOREACH (const QString &iface, interfaces_and_properties.keys()) { + for (auto it = interfaces_and_properties.cbegin(); it != interfaces_and_properties.cend(); ++it) { + const QString &iface = it.key(); /* Don't store generic DBus interfaces */ if (iface.startsWith(UD2_DBUS_SERVICE)) { m_interfaces.append(iface); } } } void DeviceBackend::slotInterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces) { if (object_path.path() != m_udi) { return; } - Q_FOREACH (const QString &iface, interfaces) { + for (const QString &iface : interfaces) { m_interfaces.removeAll(iface); } // We don't know which property belongs to which interface, so remove all m_propertyCache.clear(); if (!m_interfaces.isEmpty()) { allProperties(); } } diff --git a/src/solid/devices/backends/udisks2/udisksmanager.cpp b/src/solid/devices/backends/udisks2/udisksmanager.cpp index ca2630a..299afa4 100644 --- a/src/solid/devices/backends/udisks2/udisksmanager.cpp +++ b/src/solid/devices/backends/udisks2/udisksmanager.cpp @@ -1,306 +1,307 @@ /* SPDX-FileCopyrightText: 2012 Lukáš Tinkl SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "udisksmanager.h" #include "udisksdevicebackend.h" #include "udisks_debug.h" #include #include #include #include #include #include "../shared/rootdevice.h" using namespace Solid::Backends::UDisks2; using namespace Solid::Backends::Shared; Manager::Manager(QObject *parent) : Solid::Ifaces::DeviceManager(parent), m_manager(UD2_DBUS_SERVICE, UD2_DBUS_PATH, QDBusConnection::systemBus()) { m_supportedInterfaces << Solid::DeviceInterface::GenericInterface << Solid::DeviceInterface::Block << Solid::DeviceInterface::StorageAccess << Solid::DeviceInterface::StorageDrive << Solid::DeviceInterface::OpticalDrive << Solid::DeviceInterface::OpticalDisc << Solid::DeviceInterface::StorageVolume; qDBusRegisterMetaType >(); qDBusRegisterMetaType(); qDBusRegisterMetaType(); qDBusRegisterMetaType(); bool serviceFound = m_manager.isValid(); if (!serviceFound) { // find out whether it will be activated automatically QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListActivatableNames"); QDBusReply reply = QDBusConnection::systemBus().call(message); if (reply.isValid() && reply.value().contains(UD2_DBUS_SERVICE)) { QDBusConnection::systemBus().interface()->startService(UD2_DBUS_SERVICE); serviceFound = true; } } if (serviceFound) { connect(&m_manager, SIGNAL(InterfacesAdded(QDBusObjectPath,VariantMapMap)), this, SLOT(slotInterfacesAdded(QDBusObjectPath,VariantMapMap))); connect(&m_manager, SIGNAL(InterfacesRemoved(QDBusObjectPath,QStringList)), this, SLOT(slotInterfacesRemoved(QDBusObjectPath,QStringList))); } } Manager::~Manager() { while (!m_deviceCache.isEmpty()) { QString udi = m_deviceCache.takeFirst(); DeviceBackend::destroyBackend(udi); } } QObject *Manager::createDevice(const QString &udi) { if (udi == udiPrefix()) { RootDevice *root = new RootDevice(udi); root->setProduct(tr("Storage")); root->setDescription(tr("Storage devices")); root->setIcon("server-database"); // Obviously wasn't meant for that, but maps nicely in oxygen icon set :-p return root; } else if (deviceCache().contains(udi)) { return new Device(udi); } else { return nullptr; } } QStringList Manager::devicesFromQuery(const QString &parentUdi, Solid::DeviceInterface::Type type) { QStringList result; + const QStringList deviceList = deviceCache(); if (!parentUdi.isEmpty()) { - Q_FOREACH (const QString &udi, deviceCache()) { + for (const QString &udi : deviceList) { Device device(udi); if (device.queryDeviceInterface(type) && device.parentUdi() == parentUdi) { result << udi; } } return result; } else if (type != Solid::DeviceInterface::Unknown) { - Q_FOREACH (const QString &udi, deviceCache()) { + for (const QString &udi : deviceList) { Device device(udi); if (device.queryDeviceInterface(type)) { result << udi; } } return result; } return deviceCache(); } QStringList Manager::allDevices() { introspect("/org/freedesktop/UDisks2/block_devices", true /*checkOptical*/); introspect("/org/freedesktop/UDisks2/drives"); return m_deviceCache; } void Manager::introspect(const QString &path, bool checkOptical) { QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, path, DBUS_INTERFACE_INTROSPECT, "Introspect"); QDBusPendingReply reply = QDBusConnection::systemBus().call(call); if (reply.isValid()) { QDomDocument dom; dom.setContent(reply.value()); QDomNodeList nodeList = dom.documentElement().elementsByTagName("node"); for (int i = 0; i < nodeList.count(); i++) { QDomElement nodeElem = nodeList.item(i).toElement(); if (!nodeElem.isNull() && nodeElem.hasAttribute("name")) { const QString udi = path + "/" + nodeElem.attribute("name"); if (checkOptical) { Device device(udi); if (device.mightBeOpticalDisc()) { QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, udi, DBUS_INTERFACE_PROPS, "PropertiesChanged", this, SLOT(slotMediaChanged(QDBusMessage))); if (!device.isOpticalDisc()) { // skip empty CD disc continue; } } } m_deviceCache.append(udi); } } } else { qCWarning(UDISKS2) << "Failed enumerating UDisks2 objects:" << reply.error().name() << "\n" << reply.error().message(); } } QSet< Solid::DeviceInterface::Type > Manager::supportedInterfaces() const { return m_supportedInterfaces; } QString Manager::udiPrefix() const { return UD2_UDI_DISKS_PREFIX; } void Manager::slotInterfacesAdded(const QDBusObjectPath &object_path, const VariantMapMap &interfaces_and_properties) { const QString udi = object_path.path(); /* Ignore jobs */ if (udi.startsWith(UD2_DBUS_PATH_JOBS)) { return; } qCDebug(UDISKS2) << udi << "has new interfaces:" << interfaces_and_properties.keys(); // If device gained an org.freedesktop.UDisks2.Block interface, we // should check if it is an optical drive, in order to properly // register mediaChanged event handler with newly-plugged external // drives if (interfaces_and_properties.contains("org.freedesktop.UDisks2.Block")) { Device device(udi); if (device.mightBeOpticalDisc()) { QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, udi, DBUS_INTERFACE_PROPS, "PropertiesChanged", this, SLOT(slotMediaChanged(QDBusMessage))); } } updateBackend(udi); // new device, we don't know it yet if (!m_deviceCache.contains(udi)) { m_deviceCache.append(udi); emit deviceAdded(udi); } // re-emit in case of 2-stage devices like N9 or some Android phones else if (m_deviceCache.contains(udi) && interfaces_and_properties.keys().contains(UD2_DBUS_INTERFACE_FILESYSTEM)) { emit deviceAdded(udi); } } void Manager::slotInterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces) { const QString udi = object_path.path(); if (udi.isEmpty()) { return; } /* Ignore jobs */ if (udi.startsWith(UD2_DBUS_PATH_JOBS)) { return; } qCDebug(UDISKS2) << udi << "lost interfaces:" << interfaces; /* * Determine left interfaces. The device backend may have processed the * InterfacesRemoved signal already, but the result set is the same * independent if the backend or the manager processes the signal first. */ Device device(udi); const QStringList ifaceList = device.interfaces(); #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) QSet leftInterfaces = ifaceList.toSet(); leftInterfaces.subtract(interfaces.toSet()); #else QSet leftInterfaces(ifaceList.begin(), ifaceList.end()); leftInterfaces.subtract(QSet(interfaces.begin(), interfaces.end())); #endif if (leftInterfaces.isEmpty()) { // remove the device if the last interface is removed emit deviceRemoved(udi); m_deviceCache.removeAll(udi); DeviceBackend::destroyBackend(udi); } else { /* * Changes in the interface composition may change if a device * matches a Predicate. We have to do a remove-and-readd cycle * as there is no dedicated signal for Predicate reevaluation. */ emit deviceRemoved(udi); emit deviceAdded(udi); } } void Manager::slotMediaChanged(const QDBusMessage &msg) { const QVariantMap properties = qdbus_cast(msg.arguments().at(1)); if (!properties.contains("Size")) { // react only on Size changes return; } const QString udi = msg.path(); updateBackend(udi); qulonglong size = properties.value("Size").toULongLong(); qCDebug(UDISKS2) << "MEDIA CHANGED in" << udi << "; size is:" << size; if (!m_deviceCache.contains(udi) && size > 0) { // we don't know the optdisc, got inserted m_deviceCache.append(udi); emit deviceAdded(udi); } if (m_deviceCache.contains(udi) && size == 0) { // we know the optdisc, got removed emit deviceRemoved(udi); m_deviceCache.removeAll(udi); DeviceBackend::destroyBackend(udi); } } const QStringList &Manager::deviceCache() { if (m_deviceCache.isEmpty()) { allDevices(); } return m_deviceCache; } void Manager::updateBackend(const QString &udi) { DeviceBackend *backend = DeviceBackend::backendForUDI(udi); if (!backend) { return; } //This doesn't emit "changed" signals. Signals are emitted later by DeviceBackend's slots backend->allProperties(); QVariant driveProp = backend->prop("Drive"); if (!driveProp.isValid()) { return; } QDBusObjectPath drivePath = qdbus_cast(driveProp); DeviceBackend *driveBackend = DeviceBackend::backendForUDI(drivePath.path(), false); if (!driveBackend) { return; } driveBackend->invalidateProperties(); } diff --git a/src/solid/devices/backends/udisks2/udisksopticaldrive.cpp b/src/solid/devices/backends/udisks2/udisksopticaldrive.cpp index 0e3e742..592547c 100644 --- a/src/solid/devices/backends/udisks2/udisksopticaldrive.cpp +++ b/src/solid/devices/backends/udisks2/udisksopticaldrive.cpp @@ -1,220 +1,219 @@ /* SPDX-FileCopyrightText: 2010 Michael Zanetti SPDX-FileCopyrightText: 2010-2012 Lukáš Tinkl SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "udisksopticaldrive.h" #include #include #include #include #include #include #include #include #include #include "udisks_debug.h" #include "udisks2.h" #include "udisksdevice.h" #include "dbus/manager.h" using namespace Solid::Backends::UDisks2; OpticalDrive::OpticalDrive(Device *device) : StorageDrive(device) , m_ejectInProgress(false) , m_readSpeed(0) , m_writeSpeed(0) , m_speedsInit(false) { m_device->registerAction("eject", this, SLOT(slotEjectRequested()), SLOT(slotEjectDone(int,QString))); connect(m_device, SIGNAL(changed()), this, SLOT(slotChanged())); } OpticalDrive::~OpticalDrive() { } bool OpticalDrive::eject() { if (m_ejectInProgress) { return false; } m_ejectInProgress = true; m_device->broadcastActionRequested("eject"); const QString path = m_device->udi(); QDBusConnection c = QDBusConnection::connectToBus(QDBusConnection::SystemBus, "Solid::Udisks2::OpticalDrive::" + path); // if the device is mounted, unmount first QString blockPath; org::freedesktop::DBus::ObjectManager manager(UD2_DBUS_SERVICE, UD2_DBUS_PATH, c); QDBusPendingReply reply = manager.GetManagedObjects(); reply.waitForFinished(); if (!reply.isError()) { // enum devices - Q_FOREACH (const QDBusObjectPath &objPath, reply.value().keys()) { - const QString udi = objPath.path(); + const auto objPathMap = reply.value(); + for (auto it = objPathMap.cbegin(); it != objPathMap.cend(); ++it) { + const QString udi = it.key().path(); //qDebug() << "Inspecting" << udi; if (udi == UD2_DBUS_PATH_MANAGER || udi == UD2_UDI_DISKS_PREFIX || udi.startsWith(UD2_DBUS_PATH_JOBS)) { continue; } Device device(udi); if (device.drivePath() == path && device.isMounted()) { //qDebug() << "Got mounted block device:" << udi; blockPath = udi; break; } } } else { // show error qCWarning(UDISKS2) << "Failed enumerating UDisks2 objects:" << reply.error().name() << "\n" << reply.error().message(); } if (!blockPath.isEmpty()) { //qDebug() << "Calling unmount on" << blockPath; QDBusMessage msg = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, blockPath, UD2_DBUS_INTERFACE_FILESYSTEM, "Unmount"); msg << QVariantMap(); // options, unused now c.call(msg, QDBus::BlockWithGui); } QDBusMessage msg = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, path, UD2_DBUS_INTERFACE_DRIVE, "Eject"); msg << QVariantMap(); return c.callWithCallback(msg, this, SLOT(slotDBusReply(QDBusMessage)), SLOT(slotDBusError(QDBusError))); } void OpticalDrive::slotDBusReply(const QDBusMessage &/*reply*/) { m_ejectInProgress = false; m_device->broadcastActionDone("eject"); } void OpticalDrive::slotDBusError(const QDBusError &error) { m_ejectInProgress = false; m_device->broadcastActionDone("eject", m_device->errorToSolidError(error.name()), m_device->errorToString(error.name()) + ": " + error.message()); } void OpticalDrive::slotEjectRequested() { m_ejectInProgress = true; emit ejectRequested(m_device->udi()); } void OpticalDrive::slotEjectDone(int error, const QString &errorString) { m_ejectInProgress = false; emit ejectDone(static_cast(error), errorString, m_device->udi()); } void OpticalDrive::initReadWriteSpeeds() const { #if 0 int read_speed, write_speed; char *write_speeds = 0; QByteArray device_file = QFile::encodeName(m_device->property("Device").toString()); //qDebug("Doing open (\"%s\", O_RDONLY | O_NONBLOCK)", device_file.constData()); int fd = open(device_file, O_RDONLY | O_NONBLOCK); if (fd < 0) { qWarning("Cannot open %s: %s", device_file.constData(), strerror(errno)); return; } if (get_read_write_speed(fd, &read_speed, &write_speed, &write_speeds) >= 0) { m_readSpeed = read_speed; m_writeSpeed = write_speed; #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) QStringList list = QString::fromLatin1(write_speeds).split(',', QString::SkipEmptyParts); #else QStringList list = QString::fromLatin1(write_speeds).split(',', Qt::SkipEmptyParts); #endif Q_FOREACH (const QString &speed, list) { m_writeSpeeds.append(speed.toInt()); } free(write_speeds); m_speedsInit = true; } close(fd); #endif } QList OpticalDrive::writeSpeeds() const { if (!m_speedsInit) { initReadWriteSpeeds(); } //qDebug() << "solid write speeds:" << m_writeSpeeds; return m_writeSpeeds; } int OpticalDrive::writeSpeed() const { if (!m_speedsInit) { initReadWriteSpeeds(); } return m_writeSpeed; } int OpticalDrive::readSpeed() const { if (!m_speedsInit) { initReadWriteSpeeds(); } return m_readSpeed; } Solid::OpticalDrive::MediumTypes OpticalDrive::supportedMedia() const { const QStringList mediaTypes = m_device->prop("MediaCompatibility").toStringList(); Solid::OpticalDrive::MediumTypes supported; - QMap map; - map[Solid::OpticalDrive::Cdr] = "optical_cd_r"; - map[Solid::OpticalDrive::Cdrw] = "optical_cd_rw"; - map[Solid::OpticalDrive::Dvd] = "optical_dvd"; - map[Solid::OpticalDrive::Dvdr] = "optical_dvd_r"; - map[Solid::OpticalDrive::Dvdrw] = "optical_dvd_rw"; - map[Solid::OpticalDrive::Dvdram] = "optical_dvd_ram"; - map[Solid::OpticalDrive::Dvdplusr] = "optical_dvd_plus_r"; - map[Solid::OpticalDrive::Dvdplusrw] = "optical_dvd_plus_rw"; - map[Solid::OpticalDrive::Dvdplusdl] = "optical_dvd_plus_r_dl"; - map[Solid::OpticalDrive::Dvdplusdlrw] = "optical_dvd_plus_rw_dl"; - map[Solid::OpticalDrive::Bd] = "optical_bd"; - map[Solid::OpticalDrive::Bdr] = "optical_bd_r"; - map[Solid::OpticalDrive::Bdre] = "optical_bd_re"; - map[Solid::OpticalDrive::HdDvd] = "optical_hddvd"; - map[Solid::OpticalDrive::HdDvdr] = "optical_hddvd_r"; - map[Solid::OpticalDrive::HdDvdrw] = "optical_hddvd_rw"; + QMap map = { + {QStringLiteral("optical_cd_r"), Solid::OpticalDrive::Cdr}, + {QStringLiteral("optical_cd_rw"), Solid::OpticalDrive::Cdrw}, + {QStringLiteral("optical_dvd"), Solid::OpticalDrive::Dvd}, + {QStringLiteral("optical_dvd_r"), Solid::OpticalDrive::Dvdr}, + {QStringLiteral("optical_dvd_rw"), Solid::OpticalDrive::Dvdrw}, + {QStringLiteral("optical_dvd_ram"), Solid::OpticalDrive::Dvdram}, + {QStringLiteral("optical_dvd_plus_r"), Solid::OpticalDrive::Dvdplusr}, + {QStringLiteral("optical_dvd_plus_rw"), Solid::OpticalDrive::Dvdplusrw}, + {QStringLiteral("optical_dvd_plus_r_dl"), Solid::OpticalDrive::Dvdplusdl}, + {QStringLiteral("optical_dvd_plus_rw_dl"), Solid::OpticalDrive::Dvdplusdlrw}, + {QStringLiteral("optical_bd"), Solid::OpticalDrive::Bd}, + {QStringLiteral("optical_bd_r"), Solid::OpticalDrive::Bdr}, + {QStringLiteral("optical_bd_re"), Solid::OpticalDrive::Bdre}, + {QStringLiteral("optical_hddvd"), Solid::OpticalDrive::HdDvd}, + {QStringLiteral("optical_hddvd_r"), Solid::OpticalDrive::HdDvdr}, + {QStringLiteral("optical_hddvd_rw"), Solid::OpticalDrive::HdDvdrw}}; // TODO add these to Solid //map[Solid::OpticalDrive::Mo] ="optical_mo"; //map[Solid::OpticalDrive::Mr] ="optical_mrw"; //map[Solid::OpticalDrive::Mrw] ="optical_mrw_w"; - Q_FOREACH (const Solid::OpticalDrive::MediumType &type, map.keys()) { - if (mediaTypes.contains(map[type])) { - supported |= type; - } + for (const QString &media : mediaTypes) { + supported |= map.value(media, Solid::OpticalDrive::UnknownMediumType); } return supported; } void OpticalDrive::slotChanged() { m_speedsInit = false; // reset the read/write speeds, changes eg. with an inserted media }