Advance Wayland and KDE package bring-up
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
add_subdirectory(solid)
|
||||
add_subdirectory(tools)
|
||||
|
||||
ecm_qt_install_logging_categories(
|
||||
EXPORT SOLID
|
||||
FILE solid.categories
|
||||
DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}
|
||||
)
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Extract strings from all source files.
|
||||
# EXTRACT_TR_STRINGS extracts strings with lupdate and convert them to .pot with
|
||||
# lconvert.
|
||||
$EXTRACT_TR_STRINGS `find . -name \*.cpp -o -name \*.h -o -name \*.ui -o -name \*.qml` -o $podir/solid6_qt.pot
|
||||
@@ -0,0 +1,120 @@
|
||||
ecm_create_qm_loader(solid_QM_LOADER solid6_qt)
|
||||
|
||||
include(devices/CMakeLists.txt)
|
||||
|
||||
set(solid_LIB_SRCS ${solid_LIB_SRCS} ${solid_QM_LOADER})
|
||||
|
||||
add_library(KF6Solid ${solid_LIB_SRCS})
|
||||
set(solid_BUILD_INCLUDE_DIRS
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/..
|
||||
${CMAKE_CURRENT_BINARY_DIR}/..
|
||||
)
|
||||
target_include_directories(KF6Solid PUBLIC "$<BUILD_INTERFACE:${solid_BUILD_INCLUDE_DIRS}>")
|
||||
|
||||
ecm_generate_export_header(KF6Solid
|
||||
BASE_NAME Solid
|
||||
GROUP_BASE_NAME KF
|
||||
VERSION ${KF_VERSION}
|
||||
USE_VERSION_HEADER
|
||||
DEPRECATED_BASE_VERSION 0
|
||||
DEPRECATION_VERSIONS
|
||||
EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT}
|
||||
)
|
||||
|
||||
add_library(KF6::Solid ALIAS KF6Solid)
|
||||
|
||||
# Apps must include <Solid/File> or <solid/file.h>
|
||||
target_include_directories(KF6Solid INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR_KF}/Solid>")
|
||||
|
||||
target_link_libraries(KF6Solid PUBLIC Qt6::Core
|
||||
PRIVATE Qt6::Xml
|
||||
Qt6::Gui
|
||||
${solid_OPTIONAL_LIBS}
|
||||
)
|
||||
if (HAVE_DBUS)
|
||||
target_link_libraries(KF6Solid PRIVATE Qt6::DBus)
|
||||
endif()
|
||||
|
||||
set_target_properties(KF6Solid PROPERTIES VERSION ${SOLID_VERSION}
|
||||
SOVERSION ${SOLID_SOVERSION}
|
||||
EXPORT_NAME Solid
|
||||
)
|
||||
|
||||
ecm_generate_headers(Solid_CamelCase_HEADERS
|
||||
HEADER_NAMES
|
||||
Device
|
||||
DeviceNotifier
|
||||
DeviceInterface
|
||||
GenericInterface
|
||||
Processor
|
||||
Block
|
||||
StorageAccess
|
||||
StorageDrive
|
||||
OpticalDrive
|
||||
StorageVolume
|
||||
OpticalDisc
|
||||
Camera
|
||||
PortableMediaPlayer
|
||||
Battery
|
||||
Predicate
|
||||
NetworkShare
|
||||
SolidNamespace
|
||||
|
||||
RELATIVE devices/frontend
|
||||
REQUIRED_HEADERS Solid_HEADERS
|
||||
PREFIX Solid
|
||||
)
|
||||
|
||||
install(FILES ${Solid_CamelCase_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF}/Solid/Solid COMPONENT Devel)
|
||||
|
||||
install(TARGETS KF6Solid EXPORT KF6SolidTargets ${KF_INSTALL_TARGETS_DEFAULT_ARGS})
|
||||
|
||||
########### static lib for tests ###############
|
||||
|
||||
if (BUILD_TESTING)
|
||||
add_library(KF6Solid_static STATIC ${solid_LIB_SRCS})
|
||||
set_target_properties(KF6Solid_static PROPERTIES COMPILE_FLAGS -DSOLID_STATIC_DEFINE=1)
|
||||
|
||||
target_link_libraries(KF6Solid_static PUBLIC Qt6::Core)
|
||||
target_link_libraries(KF6Solid_static PRIVATE Qt6::Xml Qt6::Gui ${solid_OPTIONAL_LIBS})
|
||||
if (HAVE_DBUS)
|
||||
target_link_libraries(KF6Solid_static PRIVATE Qt6::DBus)
|
||||
endif()
|
||||
target_include_directories(KF6Solid_static PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/..;${CMAKE_CURRENT_BINARY_DIR}/..>")
|
||||
endif()
|
||||
|
||||
########### install files ###############
|
||||
|
||||
install(FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/solid_export.h
|
||||
${Solid_HEADERS}
|
||||
DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF}/Solid/solid COMPONENT Devel
|
||||
)
|
||||
|
||||
if(BUILD_QCH)
|
||||
ecm_add_qch(
|
||||
KF6Solid_QCH
|
||||
NAME Solid
|
||||
BASE_NAME KF6Solid
|
||||
VERSION ${KF_VERSION}
|
||||
ORG_DOMAIN org.kde
|
||||
SOURCES # using only public headers, to cover only public API
|
||||
${Solid_HEADERS}
|
||||
"${CMAKE_SOURCE_DIR}/docs/song.md"
|
||||
MD_MAINPAGE "${CMAKE_SOURCE_DIR}/README.md"
|
||||
LINK_QCHS
|
||||
Qt6Core_QCH
|
||||
INCLUDE_DIRS
|
||||
${solid_BUILD_INCLUDE_DIRS}
|
||||
BLANK_MACROS
|
||||
SOLID_EXPORT
|
||||
SOLID_DEPRECATED
|
||||
SOLID_DEPRECATED_EXPORT
|
||||
"SOLID_DEPRECATED_VERSION(x, y, t)"
|
||||
TAGFILE_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR}
|
||||
QCH_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR}
|
||||
COMPONENT Devel
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
include (CheckCXXSourceCompiles)
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-DYY_NO_UNISTD_H)
|
||||
endif()
|
||||
|
||||
if(MSVC OR (WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "Intel"))
|
||||
check_cxx_source_compiles("int main() { __asm { pxor mm0, mm0 }; }" HAVE_X86_MMX)
|
||||
check_cxx_source_compiles("int main() { __asm { xorps xmm0, xmm0 }; }" HAVE_X86_SSE)
|
||||
check_cxx_source_compiles("int main() { __asm { xorpd xmm0, xmm0 }; }" HAVE_X86_SSE2)
|
||||
check_cxx_source_compiles("int main() { __asm { femms }; }" HAVE_X86_3DNOW)
|
||||
else()
|
||||
check_cxx_source_compiles(" #ifdef __SUNPRO_CC
|
||||
#define __asm__ asm
|
||||
#endif
|
||||
int main() { __asm__(\"pxor %mm0, %mm0\") ; }" HAVE_X86_MMX)
|
||||
check_cxx_source_compiles(" #ifdef __SUNPRO_CC
|
||||
#define __asm__ asm
|
||||
#endif
|
||||
int main() { __asm__(\"xorps %xmm0, %xmm0\"); }" HAVE_X86_SSE)
|
||||
check_cxx_source_compiles(" #ifdef __SUNPRO_CC
|
||||
#define __asm__ asm
|
||||
#endif
|
||||
int main() { __asm__(\"xorpd %xmm0, %xmm0\"); }" HAVE_X86_SSE2)
|
||||
check_cxx_source_compiles(" #ifdef __SUNPRO_CC
|
||||
#define __asm__ asm
|
||||
#endif
|
||||
int main() { __asm__(\"femms\"); }" HAVE_X86_3DNOW)
|
||||
endif()
|
||||
check_cxx_source_compiles(" #ifdef __SUNPRO_CC
|
||||
#define __asm__ asm
|
||||
#endif
|
||||
int main() { __asm__(\"mtspr 256, %0; vand %%v0, %%v0, %%v0\" : : \"r\"(-1) ); }" HAVE_PPC_ALTIVEC)
|
||||
|
||||
configure_file(devices/config-processor.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-processor.h )
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/devices/ ${CMAKE_CURRENT_SOURCE_DIR}/devices/frontend/ ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(solid_LIB_SRCS
|
||||
${solid_LIB_SRCS}
|
||||
devices/managerbase.cpp
|
||||
devices/solidnamespace.cpp
|
||||
devices/predicateparse.cpp
|
||||
|
||||
devices/frontend/device.cpp
|
||||
devices/frontend/devicemanager.cpp
|
||||
devices/frontend/deviceinterface.cpp
|
||||
devices/frontend/genericinterface.cpp
|
||||
devices/frontend/processor.cpp
|
||||
devices/frontend/block.cpp
|
||||
devices/frontend/storagedrive.cpp
|
||||
devices/frontend/opticaldrive.cpp
|
||||
devices/frontend/storagevolume.cpp
|
||||
devices/frontend/opticaldisc.cpp
|
||||
devices/frontend/storageaccess.cpp
|
||||
devices/frontend/camera.cpp
|
||||
devices/frontend/portablemediaplayer.cpp
|
||||
devices/frontend/networkshare.cpp
|
||||
devices/frontend/battery.cpp
|
||||
devices/frontend/predicate.cpp
|
||||
|
||||
devices/ifaces/battery.cpp
|
||||
devices/ifaces/block.cpp
|
||||
devices/ifaces/camera.cpp
|
||||
devices/ifaces/opticaldrive.cpp
|
||||
devices/ifaces/device.cpp
|
||||
devices/ifaces/deviceinterface.cpp
|
||||
devices/ifaces/devicemanager.cpp
|
||||
devices/ifaces/genericinterface.cpp
|
||||
devices/ifaces/networkshare.cpp
|
||||
devices/ifaces/opticaldisc.cpp
|
||||
devices/ifaces/portablemediaplayer.cpp
|
||||
devices/ifaces/processor.cpp
|
||||
devices/ifaces/storagedrive.cpp
|
||||
devices/ifaces/storagevolume.cpp
|
||||
devices/ifaces/storageaccess.cpp
|
||||
|
||||
devices/backends/shared/rootdevice.cpp
|
||||
devices/backends/shared/cpufeatures.cpp
|
||||
)
|
||||
|
||||
ecm_qt_declare_logging_category(solid_LIB_SRCS
|
||||
HEADER devices_debug.h
|
||||
IDENTIFIER Solid::Frontend::DeviceManager::DEVICEMANAGER
|
||||
DEFAULT_SEVERITY Warning
|
||||
CATEGORY_NAME kf.solid.frontend.devicemanager
|
||||
DESCRIPTION "Solid (Device Manager)"
|
||||
EXPORT SOLID
|
||||
)
|
||||
|
||||
bison_target(SolidParser
|
||||
devices/predicate_parser.y
|
||||
${CMAKE_CURRENT_BINARY_DIR}/predicate_parser.c
|
||||
COMPILE_FLAGS "-p Solid -d -b predicate_parser --no-lines"
|
||||
)
|
||||
set_property(SOURCE ${CMAKE_CURRENT_BINARY_DIR}/predicate_parser.h PROPERTY SKIP_AUTOMOC TRUE) # don't run automoc on this file
|
||||
|
||||
flex_target(SolidLexer
|
||||
devices/predicate_lexer.l
|
||||
${CMAKE_CURRENT_BINARY_DIR}/predicate_lexer.c
|
||||
COMPILE_FLAGS "-P Solid --noline"
|
||||
)
|
||||
add_flex_bison_dependency(SolidLexer SolidParser)
|
||||
list(APPEND solid_LIB_SRCS ${BISON_SolidParser_OUTPUTS} ${FLEX_SolidLexer_OUTPUTS})
|
||||
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckCXXSourceCompiles)
|
||||
|
||||
#Needed for the fstab backend
|
||||
check_include_files(sys/types.h HAVE_SYS_TYPES_H)
|
||||
check_include_files(sys/param.h HAVE_SYS_PARAM_H)
|
||||
check_include_files("stdio.h;sys/mnttab.h" HAVE_SYS_MNTTAB_H)
|
||||
check_include_files("sys/param.h;sys/mount.h" HAVE_SYS_MOUNT_H)
|
||||
|
||||
check_function_exists(getmntinfo HAVE_GETMNTINFO)
|
||||
|
||||
check_cxx_source_compiles("
|
||||
#include <sys/types.h>
|
||||
#include <sys/statvfs.h>
|
||||
int main(){
|
||||
struct statvfs *mntbufp;
|
||||
int flags;
|
||||
return getmntinfo(&mntbufp, flags);
|
||||
}
|
||||
" GETMNTINFO_USES_STATVFS )
|
||||
|
||||
configure_file(devices/config-solid.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-solid.h )
|
||||
|
||||
set(solid_OPTIONAL_LIBS)
|
||||
|
||||
add_device_backends_build("${CMAKE_CURRENT_SOURCE_DIR}/devices/backends" solid_LIB_SRCS solid_OPTIONAL_LIBS)
|
||||
@@ -0,0 +1,17 @@
|
||||
set(backend_sources
|
||||
fakebattery.cpp
|
||||
fakeblock.cpp
|
||||
fakecamera.cpp
|
||||
fakecdrom.cpp
|
||||
fakedevice.cpp
|
||||
fakedeviceinterface.cpp
|
||||
fakegenericinterface.cpp
|
||||
fakemanager.cpp
|
||||
fakenetworkshare.cpp
|
||||
fakeopticaldisc.cpp
|
||||
fakeportablemediaplayer.cpp
|
||||
fakeprocessor.cpp
|
||||
fakestorage.cpp
|
||||
fakestorageaccess.cpp
|
||||
fakevolume.cpp
|
||||
)
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Kevin Ottens <ervin@kde.org>
|
||||
SPDX-FileCopyrightText: 2012 Lukas Tinkl <ltinkl@redhat.com>
|
||||
SPDX-FileCopyrightText: 2014 Kai Uwe Broulik <kde@privat.broulik.de>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "fakebattery.h"
|
||||
#include <QVariant>
|
||||
|
||||
using namespace Solid::Backends::Fake;
|
||||
|
||||
FakeBattery::FakeBattery(FakeDevice *device)
|
||||
: FakeDeviceInterface(device)
|
||||
{
|
||||
}
|
||||
|
||||
FakeBattery::~FakeBattery()
|
||||
{
|
||||
}
|
||||
|
||||
bool FakeBattery::isPresent() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("isPresent")).toBool();
|
||||
}
|
||||
|
||||
Solid::Battery::BatteryType FakeBattery::type() const
|
||||
{
|
||||
QString name = fakeDevice()->property(QStringLiteral("batteryType")).toString();
|
||||
|
||||
if (name == QLatin1String("pda")) {
|
||||
return Solid::Battery::PdaBattery;
|
||||
} else if (name == QLatin1String("ups")) {
|
||||
return Solid::Battery::UpsBattery;
|
||||
} else if (name == QLatin1String("primary")) {
|
||||
return Solid::Battery::PrimaryBattery;
|
||||
} else if (name == QLatin1String("mouse")) {
|
||||
return Solid::Battery::MouseBattery;
|
||||
} else if (name == QLatin1String("keyboard")) {
|
||||
return Solid::Battery::KeyboardBattery;
|
||||
} else if (name == QLatin1String("keyboard_mouse")) {
|
||||
return Solid::Battery::KeyboardMouseBattery;
|
||||
} else if (name == QLatin1String("camera")) {
|
||||
return Solid::Battery::CameraBattery;
|
||||
} else if (name == QLatin1String("gaminginput")) {
|
||||
return Solid::Battery::GamingInputBattery;
|
||||
} else if (name == QLatin1String("bluetooth")) {
|
||||
return Solid::Battery::BluetoothBattery;
|
||||
} else if (name == QLatin1String("tablet")) {
|
||||
return Solid::Battery::TabletBattery;
|
||||
} else {
|
||||
return Solid::Battery::UnknownBattery;
|
||||
}
|
||||
}
|
||||
|
||||
int FakeBattery::chargePercent() const
|
||||
{
|
||||
int last_full = fakeDevice()->property(QStringLiteral("lastFullLevel")).toInt();
|
||||
int current = fakeDevice()->property(QStringLiteral("currentLevel")).toInt();
|
||||
|
||||
int percent = 0;
|
||||
if (last_full > 0) {
|
||||
percent = (100 * current) / last_full;
|
||||
}
|
||||
|
||||
return percent;
|
||||
}
|
||||
|
||||
int FakeBattery::capacity() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("capacity")).toInt();
|
||||
}
|
||||
|
||||
int FakeBattery::cycleCount() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("cycleCount")).toInt();
|
||||
}
|
||||
|
||||
bool FakeBattery::isRechargeable() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("isRechargeable")).toBool();
|
||||
}
|
||||
|
||||
bool FakeBattery::isPowerSupply() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("isPowerSupply")).toBool();
|
||||
}
|
||||
|
||||
Solid::Battery::ChargeState FakeBattery::chargeState() const
|
||||
{
|
||||
QString state = fakeDevice()->property(QStringLiteral("chargeState")).toString();
|
||||
|
||||
if (state == QLatin1String("charging")) {
|
||||
return Solid::Battery::Charging;
|
||||
} else if (state == QLatin1String("discharging")) {
|
||||
return Solid::Battery::Discharging;
|
||||
} else if (state == QLatin1String("fullyCharged")) {
|
||||
return Solid::Battery::FullyCharged;
|
||||
} else {
|
||||
return Solid::Battery::NoCharge;
|
||||
}
|
||||
}
|
||||
|
||||
qlonglong FakeBattery::timeToEmpty() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("timeToEmpty")).toLongLong();
|
||||
}
|
||||
|
||||
qlonglong FakeBattery::timeToFull() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("timeToFull")).toLongLong();
|
||||
}
|
||||
|
||||
void FakeBattery::setChargeState(Solid::Battery::ChargeState newState)
|
||||
{
|
||||
QString name;
|
||||
|
||||
switch (newState) {
|
||||
case Solid::Battery::Charging:
|
||||
name = QStringLiteral("charging");
|
||||
break;
|
||||
case Solid::Battery::Discharging:
|
||||
name = QStringLiteral("discharging");
|
||||
break;
|
||||
case Solid::Battery::NoCharge:
|
||||
name = QStringLiteral("noCharge");
|
||||
break;
|
||||
case Solid::Battery::FullyCharged:
|
||||
name = QStringLiteral("fullyCharged");
|
||||
break;
|
||||
}
|
||||
|
||||
fakeDevice()->setProperty(QStringLiteral("chargeState"), name);
|
||||
Q_EMIT chargeStateChanged(newState, fakeDevice()->udi());
|
||||
}
|
||||
|
||||
void FakeBattery::setChargeLevel(int newLevel)
|
||||
{
|
||||
fakeDevice()->setProperty(QStringLiteral("currentLevel"), newLevel);
|
||||
Q_EMIT chargePercentChanged(chargePercent(), fakeDevice()->udi());
|
||||
}
|
||||
|
||||
Solid::Battery::Technology FakeBattery::technology() const
|
||||
{
|
||||
return (Solid::Battery::Technology)fakeDevice()->property(QStringLiteral("technology")).toInt();
|
||||
}
|
||||
|
||||
double FakeBattery::energy() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("energy")).toDouble();
|
||||
}
|
||||
|
||||
double FakeBattery::energyFull() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("energyFull")).toDouble();
|
||||
}
|
||||
|
||||
double FakeBattery::energyFullDesign() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("energyFullDesign")).toDouble();
|
||||
}
|
||||
|
||||
double FakeBattery::energyRate() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("energyRate")).toDouble();
|
||||
}
|
||||
|
||||
double FakeBattery::voltage() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("voltage")).toDouble();
|
||||
}
|
||||
|
||||
double FakeBattery::temperature() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("temperature")).toDouble();
|
||||
}
|
||||
|
||||
QString FakeBattery::serial() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("serial")).toString();
|
||||
}
|
||||
|
||||
qlonglong FakeBattery::remainingTime() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("remainingTime")).toLongLong();
|
||||
}
|
||||
|
||||
#include "moc_fakebattery.cpp"
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Kevin Ottens <ervin@kde.org>
|
||||
SPDX-FileCopyrightText: 2012 Lukas Tinkl <ltinkl@redhat.com>
|
||||
SPDX-FileCopyrightText: 2014 Kai Uwe Broulik <kde@privat.broulik.de>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_FAKEHW_FAKEBATTERY_H
|
||||
#define SOLID_BACKENDS_FAKEHW_FAKEBATTERY_H
|
||||
|
||||
#include "fakedeviceinterface.h"
|
||||
#include <solid/devices/ifaces/battery.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fake
|
||||
{
|
||||
class FakeBattery : public FakeDeviceInterface, virtual public Solid::Ifaces::Battery
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::Battery)
|
||||
|
||||
public:
|
||||
explicit FakeBattery(FakeDevice *device);
|
||||
~FakeBattery() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
bool isPresent() const override;
|
||||
Solid::Battery::BatteryType type() const override;
|
||||
|
||||
int chargePercent() const override;
|
||||
int capacity() const override;
|
||||
int cycleCount() const override;
|
||||
|
||||
bool isRechargeable() const override;
|
||||
bool isPowerSupply() const override;
|
||||
|
||||
Solid::Battery::ChargeState chargeState() const override;
|
||||
qlonglong timeToEmpty() const override;
|
||||
qlonglong timeToFull() const override;
|
||||
|
||||
void setChargeState(Solid::Battery::ChargeState newState);
|
||||
void setChargeLevel(int newLevel);
|
||||
|
||||
Solid::Battery::Technology technology() const override;
|
||||
|
||||
double energy() const override;
|
||||
double energyFull() const override;
|
||||
double energyFullDesign() const override;
|
||||
double energyRate() const override;
|
||||
|
||||
double voltage() const override;
|
||||
double temperature() const override;
|
||||
|
||||
QString serial() const override;
|
||||
|
||||
qlonglong remainingTime() const override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void presentStateChanged(bool newState, const QString &udi) override;
|
||||
void chargePercentChanged(int value, const QString &udi) override;
|
||||
void capacityChanged(int value, const QString &udi) override;
|
||||
void cycleCountChanged(int value, const QString &udi) override;
|
||||
void powerSupplyStateChanged(bool newState, const QString &udi) override;
|
||||
void chargeStateChanged(int newState, const QString &udi) override;
|
||||
void timeToEmptyChanged(qlonglong time, const QString &udi) override;
|
||||
void timeToFullChanged(qlonglong time, const QString &udi) override;
|
||||
void energyChanged(double energy, const QString &udi) override;
|
||||
void energyFullChanged(double energyFull, const QString &udi) override;
|
||||
void energyFullDesignChanged(double energyFullDesign, const QString &udi) override;
|
||||
void energyRateChanged(double energyRate, const QString &udi) override;
|
||||
void voltageChanged(double voltage, const QString &udi) override;
|
||||
void temperatureChanged(double temperature, const QString &udi) override;
|
||||
void remainingTimeChanged(qlonglong time, const QString &udi) override;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_FAKEHW_FAKEBATTERY_H
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Davide Bettio <davide.bettio@kdemail.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "fakeblock.h"
|
||||
#include <QVariant>
|
||||
|
||||
using namespace Solid::Backends::Fake;
|
||||
|
||||
FakeBlock::FakeBlock(FakeDevice *device)
|
||||
: FakeDeviceInterface(device)
|
||||
{
|
||||
}
|
||||
|
||||
FakeBlock::~FakeBlock()
|
||||
{
|
||||
}
|
||||
|
||||
int FakeBlock::deviceMajor() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("major")).toInt();
|
||||
}
|
||||
|
||||
int FakeBlock::deviceMinor() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("minor")).toInt();
|
||||
}
|
||||
|
||||
QString FakeBlock::device() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("device")).toString();
|
||||
}
|
||||
|
||||
#include "moc_fakeblock.cpp"
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Davide Bettio <davide.bettio@kdemail.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_FAKEHW_FAKEBLOCK_H
|
||||
#define SOLID_BACKENDS_FAKEHW_FAKEBLOCK_H
|
||||
|
||||
#include "fakedeviceinterface.h"
|
||||
#include <solid/devices/ifaces/block.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fake
|
||||
{
|
||||
class FakeBlock : public FakeDeviceInterface, virtual public Solid::Ifaces::Block
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::Block)
|
||||
|
||||
public:
|
||||
explicit FakeBlock(FakeDevice *device);
|
||||
~FakeBlock() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
int deviceMajor() const override;
|
||||
int deviceMinor() const override;
|
||||
QString device() const override;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_FAKEHW_FAKEBLOCK_H
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Kevin Ottens <ervin@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "fakecamera.h"
|
||||
#include <QVariant>
|
||||
|
||||
using namespace Solid::Backends::Fake;
|
||||
|
||||
FakeCamera::FakeCamera(FakeDevice *device)
|
||||
: FakeDeviceInterface(device)
|
||||
{
|
||||
}
|
||||
|
||||
FakeCamera::~FakeCamera()
|
||||
{
|
||||
}
|
||||
|
||||
QStringList FakeCamera::supportedProtocols() const
|
||||
{
|
||||
QString method = fakeDevice()->property(QStringLiteral("accessMethod")).toString();
|
||||
|
||||
return {method};
|
||||
}
|
||||
|
||||
QStringList FakeCamera::supportedDrivers(QString /*protocol*/) const
|
||||
{
|
||||
if (fakeDevice()->property(QStringLiteral("gphotoSupport")).toBool()) {
|
||||
return {QStringLiteral("gphoto")};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
QVariant Solid::Backends::Fake::FakeCamera::driverHandle(const QString &driver) const
|
||||
{
|
||||
Q_UNUSED(driver);
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
#include "moc_fakecamera.cpp"
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Kevin Ottens <ervin@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_FAKEHW_FAKECAMERA_H
|
||||
#define SOLID_BACKENDS_FAKEHW_FAKECAMERA_H
|
||||
|
||||
#include "fakedeviceinterface.h"
|
||||
#include <solid/devices/ifaces/camera.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fake
|
||||
{
|
||||
class FakeCamera : public FakeDeviceInterface, virtual public Solid::Ifaces::Camera
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::Camera)
|
||||
|
||||
public:
|
||||
explicit FakeCamera(FakeDevice *device);
|
||||
~FakeCamera() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
QStringList supportedProtocols() const override;
|
||||
QStringList supportedDrivers(QString protocol) const override;
|
||||
QVariant driverHandle(const QString &driver) const override;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_FAKEHW_FAKECAMERA_H
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Davide Bettio <davide.bettio@kdemail.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "fakecdrom.h"
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
using namespace Solid::Backends::Fake;
|
||||
|
||||
FakeCdrom::FakeCdrom(FakeDevice *device)
|
||||
: FakeStorage(device)
|
||||
{
|
||||
}
|
||||
|
||||
FakeCdrom::~FakeCdrom()
|
||||
{
|
||||
}
|
||||
|
||||
Solid::OpticalDrive::MediumTypes FakeCdrom::supportedMedia() const
|
||||
{
|
||||
Solid::OpticalDrive::MediumTypes supported;
|
||||
|
||||
const QMap<QString, Solid::OpticalDrive::MediumType> map = {
|
||||
{QStringLiteral("cdr"), Solid::OpticalDrive::Cdr},
|
||||
{QStringLiteral("cdrw"), Solid::OpticalDrive::Cdrw},
|
||||
{QStringLiteral("dvd"), Solid::OpticalDrive::Dvd},
|
||||
{QStringLiteral("dvdr"), Solid::OpticalDrive::Dvdr},
|
||||
{QStringLiteral("dvdrw"), Solid::OpticalDrive::Dvdrw},
|
||||
{QStringLiteral("dvdram"), Solid::OpticalDrive::Dvdram},
|
||||
{QStringLiteral("dvdplusr"), Solid::OpticalDrive::Dvdplusr},
|
||||
{QStringLiteral("dvdplusrw"), Solid::OpticalDrive::Dvdplusrw},
|
||||
{QStringLiteral("dvdplusrdl"), Solid::OpticalDrive::Dvdplusdl},
|
||||
{QStringLiteral("dvdplusrwdl"), Solid::OpticalDrive::Dvdplusdlrw},
|
||||
{QStringLiteral("bd"), Solid::OpticalDrive::Bd},
|
||||
{QStringLiteral("bdr"), Solid::OpticalDrive::Bdr},
|
||||
{QStringLiteral("bdre"), Solid::OpticalDrive::Bdre},
|
||||
{QStringLiteral("hddvd"), Solid::OpticalDrive::HdDvd},
|
||||
{QStringLiteral("hddvdr"), Solid::OpticalDrive::HdDvdr},
|
||||
{QStringLiteral("hddvdrw"), Solid::OpticalDrive::HdDvdrw},
|
||||
};
|
||||
|
||||
const QStringList supported_medialist = fakeDevice()->property(QStringLiteral("supportedMedia")).toString().simplified().split(QLatin1Char(','));
|
||||
|
||||
for (const QString &media : supported_medialist) {
|
||||
supported |= map.value(media, Solid::OpticalDrive::UnknownMediumType);
|
||||
}
|
||||
|
||||
return supported;
|
||||
}
|
||||
|
||||
int FakeCdrom::readSpeed() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("readSpeed")).toInt();
|
||||
}
|
||||
|
||||
int FakeCdrom::writeSpeed() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("writeSpeed")).toInt();
|
||||
}
|
||||
|
||||
QList<int> FakeCdrom::writeSpeeds() const
|
||||
{
|
||||
QList<int> speeds;
|
||||
const QStringList speed_strlist = fakeDevice()->property(QStringLiteral("writeSpeeds")).toString().simplified().split(QLatin1Char(','));
|
||||
|
||||
for (const QString &speed_str : speed_strlist) {
|
||||
speeds << speed_str.toInt();
|
||||
}
|
||||
|
||||
return speeds;
|
||||
}
|
||||
|
||||
bool FakeCdrom::eject()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#include "moc_fakecdrom.cpp"
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Davide Bettio <davide.bettio@kdemail.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_FAKEHW_FAKECDROM_H
|
||||
#define SOLID_BACKENDS_FAKEHW_FAKECDROM_H
|
||||
|
||||
#include "fakestorage.h"
|
||||
#include <solid/devices/ifaces/opticaldrive.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fake
|
||||
{
|
||||
class FakeCdrom : public FakeStorage, virtual public Solid::Ifaces::OpticalDrive
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::OpticalDrive)
|
||||
|
||||
public:
|
||||
explicit FakeCdrom(FakeDevice *device);
|
||||
~FakeCdrom() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
Solid::OpticalDrive::MediumTypes supportedMedia() const override;
|
||||
int readSpeed() const override;
|
||||
int writeSpeed() const override;
|
||||
QList<int> writeSpeeds() const override;
|
||||
bool eject() override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void ejectPressed(const QString &udi) override;
|
||||
void ejectDone(Solid::ErrorType error, QVariant errorData, const QString &udi) override;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_FAKEHW_FAKECDROM_H
|
||||
+620
@@ -0,0 +1,620 @@
|
||||
<!-- Please note that in this file we indent more than necessary so that the
|
||||
device tree is visible -->
|
||||
|
||||
<machine>
|
||||
<!-- This is a computer -->
|
||||
<device udi="/org/kde/solid/fakehw/computer">
|
||||
<property key="name">Computer</property>
|
||||
<property key="vendor">Solid</property>
|
||||
</device>
|
||||
|
||||
|
||||
<!-- A system with its own AC adapter and a battery (like a laptop) -->
|
||||
<device udi="/org/kde/solid/fakehw/acpi_AC">
|
||||
<property key="name">AC Adapter</property>
|
||||
<property key="interfaces">AcAdapter</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/computer</property>
|
||||
<property key="isPlugged">false</property>
|
||||
</device>
|
||||
<device udi="/org/kde/solid/fakehw/acpi_BAT0">
|
||||
<property key="name">Battery Bay</property>
|
||||
<property key="vendor">Acme Corporation</property>
|
||||
<property key="interfaces">Battery</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/computer</property>
|
||||
<property key="isPresent">true</property>
|
||||
<property key="batteryType">primary</property>
|
||||
<property key="chargeLevelUnit">mWh</property>
|
||||
<property key="maxLevel">43200000</property>
|
||||
<property key="lastFullLevel">42165000</property>
|
||||
<property key="currentLevel">42100000</property>
|
||||
<property key="warningLevel">140550000</property>
|
||||
<property key="lowLevel">7027500</property>
|
||||
<property key="voltageUnit">mV</property>
|
||||
<property key="voltage">11999</property>
|
||||
<property key="isRechargeable">true</property>
|
||||
<property key="isPowerSupply">true</property>
|
||||
<property key="chargeState">discharging</property>
|
||||
<property key="remainingTime">1000.5</property>
|
||||
</device>
|
||||
<device udi="/org/kde/solid/fakehw/acpi_BAT1">
|
||||
<property key="name">Miraculous Mouse</property>
|
||||
<property key="vendor">Orange Inc.</property>
|
||||
<property key="interfaces">Battery</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/computer</property>
|
||||
<property key="isPresent">false</property>
|
||||
<property key="batteryType">mouse</property>
|
||||
<!-- Battery properties beyond charge percentage are only reported by UPower
|
||||
for primary batteries, not for other batteries like this mouse -->
|
||||
<property key="isRechargeable">true</property>
|
||||
<property key="isPowerSupply">false</property>
|
||||
<property key="chargeState">discharging</property>
|
||||
<property key="capacity">85</property>
|
||||
<property key="cycleCount">175</property>
|
||||
<property key="technology">1</property>
|
||||
<property key="energy">72.25</property>
|
||||
<property key="energyRate">21.5</property>
|
||||
<property key="voltage">12.5</property>
|
||||
</device>
|
||||
|
||||
|
||||
<!-- Two CPUs -->
|
||||
<device udi="/org/kde/solid/fakehw/acpi_CPU0">
|
||||
<property key="name">Solid Processor #0</property>
|
||||
<property key="interfaces">Processor</property>
|
||||
<property key="vendor">Acme Corporation</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/computer</property>
|
||||
<property key="number">0</property>
|
||||
<property key="maxSpeed">3200</property>
|
||||
<property key="canChangeFrequency">true</property>
|
||||
<property key="instructionSets">mmx,sse</property>
|
||||
</device>
|
||||
<device udi="/org/kde/solid/fakehw/acpi_CPU1">
|
||||
<property key="name">Solid Processor #1</property>
|
||||
<property key="interfaces">Processor</property>
|
||||
<property key="vendor">Acme Corporation</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/computer</property>
|
||||
<property key="number">1</property>
|
||||
<property key="maxSpeed">3200</property>
|
||||
<property key="canChangeFrequency">true</property>
|
||||
</device>
|
||||
|
||||
|
||||
|
||||
<!-- Platform Device for a floppy drive -->
|
||||
<device udi="/org/kde/solid/fakehw/platform_floppy_0">
|
||||
<property key="name">Platform Device (floppy)</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/computer</property>
|
||||
</device>
|
||||
<!-- The actual floppy device -->
|
||||
<device udi="/org/kde/solid/fakehw/platform_floppy_0_storage">
|
||||
<property key="name">PC Floppy Drive</property>
|
||||
<property key="interfaces">StorageDrive,Block</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/platform_floppy_0</property>
|
||||
|
||||
<property key="minor">0</property>
|
||||
<property key="major">2</property>
|
||||
<property key="device">/dev/fd0</property>
|
||||
|
||||
<property key="bus">platform</property>
|
||||
<property key="driveType">floppy</property>
|
||||
<property key="isRemovable">true</property>
|
||||
<property key="isEjectRequired">false</property>
|
||||
<property key="isHotpluggable">false</property>
|
||||
<property key="isMediaCheckEnabled">false</property>
|
||||
</device>
|
||||
<!-- A (generally) virtual volume tracking the floppy drive state -->
|
||||
<device udi="/org/kde/solid/fakehw/platform_floppy_0_storage_virt_volume">
|
||||
<property key="name">Floppy Disk</property>
|
||||
<property key="interfaces">Block,StorageVolume,StorageAccess</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/platform_floppy_0_storage</property>
|
||||
|
||||
<property key="minor">0</property>
|
||||
<property key="major">2</property>
|
||||
<property key="device">/dev/fd0</property>
|
||||
|
||||
<property key="isIgnored">false</property>
|
||||
<property key="isMounted">true</property>
|
||||
<property key="mountPoint">/media/floppy0</property>
|
||||
<property key="usage">filesystem</property>
|
||||
</device>
|
||||
|
||||
|
||||
|
||||
<!-- Primary IDE controller -->
|
||||
<device udi="/org/kde/solid/fakehw/pci_001">
|
||||
<property key="name">99021 IDE Controller #1</property>
|
||||
<property key="vendor">Acme Corporation</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/computer</property>
|
||||
</device>
|
||||
|
||||
<!-- Master device... -->
|
||||
<device udi="/org/kde/solid/fakehw/pci_001_ide_0_0">
|
||||
<property key="name">IDE device (master)</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/pci_001</property>
|
||||
</device>
|
||||
<!-- ... is a 250GB disk... -->
|
||||
<device udi="/org/kde/solid/fakehw/storage_serial_HD56890I">
|
||||
<property key="name">HD250GB</property>
|
||||
<property key="vendor">Acme Corporation</property>
|
||||
<property key="interfaces">StorageDrive,Block</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/pci_001_ide_0_0</property>
|
||||
|
||||
<property key="minor">0</property>
|
||||
<property key="major">3</property>
|
||||
<property key="device">/dev/hda</property>
|
||||
|
||||
<property key="bus">scsi</property>
|
||||
<property key="driveType">disk</property>
|
||||
<property key="isRemovable">false</property>
|
||||
<property key="isEjectRequired">false</property>
|
||||
<property key="isHotpluggable">false</property>
|
||||
<property key="isMediaCheckEnabled">false</property>
|
||||
<property key="product">HD250GBSATA</property>
|
||||
</device>
|
||||
<!-- ... with five partitions:
|
||||
- one physical partition (the root /, ext3, 20GB)
|
||||
- one extended containing three logical volumes:
|
||||
- a swap volume (2GB)
|
||||
- /home volume (xfs, 188GB)
|
||||
- /foreign volume (ntfs, 20GB)
|
||||
- /data volume (encrypted Luks container, btrfs, 20GB)
|
||||
-->
|
||||
<device udi="/org/kde/solid/fakehw/volume_uuid_feedface">
|
||||
<property key="name">/</property>
|
||||
<property key="interfaces">Block,StorageVolume,StorageAccess</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/storage_serial_HD56890I</property>
|
||||
|
||||
<property key="minor">1</property>
|
||||
<property key="major">3</property>
|
||||
<property key="device">/dev/hda1</property>
|
||||
|
||||
<property key="isIgnored">true</property>
|
||||
<property key="isMounted">true</property>
|
||||
<property key="mountPoint">/</property>
|
||||
<property key="usage">filesystem</property>
|
||||
<property key="fsType">ext3</property>
|
||||
<property key="label">Root</property>
|
||||
<property key="uuid">feedface</property>
|
||||
<property key="size">21474836480</property>
|
||||
</device>
|
||||
<device udi="/org/kde/solid/fakehw/volume_uuid_c0ffee">
|
||||
<property key="name">/home</property>
|
||||
<property key="interfaces">Block,StorageVolume,StorageAccess</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/storage_serial_HD56890I</property>
|
||||
|
||||
<property key="minor">6</property>
|
||||
<property key="major">3</property>
|
||||
<property key="device">/dev/hda6</property>
|
||||
|
||||
<property key="isIgnored">true</property>
|
||||
<property key="isMounted">true</property>
|
||||
<property key="mountPoint">/home</property>
|
||||
<property key="usage">filesystem</property>
|
||||
<property key="fsType">xfs</property>
|
||||
<property key="label">Home</property>
|
||||
<property key="uuid">c0ffee</property>
|
||||
<property key="size">201863462912</property>
|
||||
</device>
|
||||
<device udi="/org/kde/solid/fakehw/volume_uuid_f00ba7">
|
||||
<property key="name">/foreign</property>
|
||||
<property key="interfaces">Block,StorageVolume,StorageAccess</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/storage_serial_HD56890I</property>
|
||||
|
||||
<property key="minor">7</property>
|
||||
<property key="major">3</property>
|
||||
<property key="device">/dev/hda7</property>
|
||||
|
||||
<property key="isIgnored">false</property>
|
||||
<property key="isMounted">true</property>
|
||||
<property key="mountPoint">/foreign</property>
|
||||
<property key="usage">filesystem</property>
|
||||
<property key="fsType">ntfs</property>
|
||||
<property key="label">Foreign</property>
|
||||
<property key="uuid">f00ba7</property>
|
||||
<property key="size">21474836480</property>
|
||||
</device>
|
||||
<device udi="/org/kde/solid/fakehw/volume_part2_size_1024">
|
||||
<property key="name">StorageVolume</property>
|
||||
<property key="interfaces">Block,StorageVolume,StorageAccess</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/storage_serial_HD56890I</property>
|
||||
|
||||
<property key="minor">2</property>
|
||||
<property key="major">3</property>
|
||||
<property key="device">/dev/hda2</property>
|
||||
|
||||
<property key="isIgnored">true</property>
|
||||
<property key="isMounted">false</property>
|
||||
<property key="usage">other</property>
|
||||
<property key="size">1024</property>
|
||||
</device>
|
||||
<device udi="/org/kde/solid/fakehw/volume_part5_size_1048576">
|
||||
<property key="name">StorageVolume (swap)</property>
|
||||
<property key="interfaces">Block,StorageVolume,StorageAccess</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/storage_serial_HD56890I</property>
|
||||
|
||||
<property key="minor">5</property>
|
||||
<property key="major">3</property>
|
||||
<property key="device">/dev/hda5</property>
|
||||
|
||||
<property key="isIgnored">true</property>
|
||||
<property key="isMounted">false</property>
|
||||
<property key="usage">other</property>
|
||||
<property key="fsType">swap</property>
|
||||
<property key="size">2147483648</property>
|
||||
</device>
|
||||
<device udi="/org/kde/solid/fakehw/volume_uuid_encrypted_0123">
|
||||
<property key="name">Luks Container</property>
|
||||
<property key="interfaces">Block,StorageVolume,StorageAccess</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/storage_serial_HD56890I</property>
|
||||
|
||||
<property key="minor">8</property>
|
||||
<property key="major">3</property>
|
||||
<property key="device">/dev/hda8</property>
|
||||
|
||||
<property key="isIgnored">true</property>
|
||||
<property key="isMounted">true</property>
|
||||
<property key="mountPoint">/data</property>
|
||||
<property key="usage">encrypted</property>
|
||||
<property key="fsType">crypto_LUKS</property>
|
||||
<property key="label"></property>
|
||||
<property key="uuid">encrypted-0123</property>
|
||||
<property key="size">21474836480</property>
|
||||
</device>
|
||||
<device udi="/org/kde/solid/fakehw/volume_uuid_cleartext_data_0123">
|
||||
<property key="name">Encrypted data</property>
|
||||
<property key="interfaces">Block,StorageVolume,StorageAccess</property>
|
||||
<property key="parent">/</property>
|
||||
|
||||
<property key="minor">0</property>
|
||||
<property key="major">254</property>
|
||||
<property key="device">/dev/dm-0</property>
|
||||
|
||||
<property key="isIgnored">true</property>
|
||||
<property key="isMounted">true</property>
|
||||
<property key="mountPoint">/data</property>
|
||||
<property key="usage">filesystem</property>
|
||||
<property key="fsType">btrfs</property>
|
||||
<property key="label"></property>
|
||||
<property key="uuid">cleartext-data-0123</property>
|
||||
<property key="size">21474835466</property>
|
||||
</device>
|
||||
|
||||
|
||||
<!-- Secondary IDE controller -->
|
||||
<device udi="/org/kde/solid/fakehw/pci_002">
|
||||
<property key="name">99021 IDE Controller #2</property>
|
||||
<property key="vendor">Acme Corporation</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/computer</property>
|
||||
</device>
|
||||
|
||||
<!-- Master device... -->
|
||||
<device udi="/org/kde/solid/fakehw/pci_002_ide_1_0">
|
||||
<property key="name">IDE device (master)</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/pci_002</property>
|
||||
</device>
|
||||
<!-- ... is a DVD writer... -->
|
||||
<device udi="/org/kde/solid/fakehw/storage_model_solid_writer">
|
||||
<property key="name">Solid IDE DVD Writer</property>
|
||||
<property key="vendor">Acme Corporation</property>
|
||||
<property key="interfaces">Block,StorageDrive,OpticalDrive</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/pci_002_ide_1_0</property>
|
||||
|
||||
<property key="minor">0</property>
|
||||
<property key="major">22</property>
|
||||
<property key="device">/dev/hdc</property>
|
||||
|
||||
<property key="bus">ide</property>
|
||||
<property key="driveType">cdrom</property>
|
||||
<property key="isRemovable">true</property>
|
||||
<property key="isEjectRequired">true</property>
|
||||
<property key="isHotpluggable">false</property>
|
||||
<property key="isMediaCheckEnabled">true</property>
|
||||
<property key="product">Solid DVD Writer</property>
|
||||
|
||||
<property key="supportedMedia">cdr,cdrw,dvd,dvdr,dvdrw</property>
|
||||
<property key="readSpeed">4234</property>
|
||||
<property key="writeSpeed">4234</property>
|
||||
<property key="writeSpeeds">4234,2822,2117,1411,706</property>
|
||||
</device>
|
||||
<!-- ... with a cd-r in it -->
|
||||
<device udi="/org/kde/solid/fakehw/volume_uuid_5011">
|
||||
<property key="name">FooDistro i386</property>
|
||||
<property key="interfaces">Block,StorageVolume,OpticalDisc,StorageAccess</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/storage_model_solid_writer</property>
|
||||
|
||||
<property key="discType">cd_rw</property>
|
||||
<property key="isAppendable">false</property>
|
||||
<property key="isRewritable">true</property>
|
||||
<property key="isBlank">false</property>
|
||||
<property key="availableContent">data</property>
|
||||
<property key="mountPoint">/media/cdrom</property>
|
||||
|
||||
<property key="uuid">5011</property>
|
||||
<property key="size">731047936</property>
|
||||
<property key="label">FooDistro i386</property>
|
||||
</device>
|
||||
|
||||
<!-- Slave device... -->
|
||||
<device udi="/org/kde/solid/fakehw/pci_002_ide_1_1">
|
||||
<property key="name">IDE device (slave)</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/pci_002</property>
|
||||
</device>
|
||||
<!-- ... is a DVD reader... -->
|
||||
<device udi="/org/kde/solid/fakehw/storage_model_solid_reader">
|
||||
<property key="name">Solid IDE DVD Reader</property>
|
||||
<property key="vendor">Acme Corporation</property>
|
||||
<property key="interfaces">Block,StorageDrive,OpticalDrive</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/pci_002_ide_1_1</property>
|
||||
|
||||
<property key="minor">0</property>
|
||||
<property key="major">22</property>
|
||||
<property key="device">/dev/hdc</property>
|
||||
|
||||
<property key="bus">ide</property>
|
||||
<property key="driveType">cdrom</property>
|
||||
<property key="isRemovable">true</property>
|
||||
<property key="isEjectRequired">true</property>
|
||||
<property key="isHotpluggable">false</property>
|
||||
<property key="isMediaCheckEnabled">true</property>
|
||||
<property key="product">Solid DVD Reader</property>
|
||||
|
||||
<property key="supportedMedia">cdr,cdrw,dvd,dvdr,dvdrw,dvdram,dvdplusr,dvdplusrw</property>
|
||||
<property key="readSpeed">4234</property>
|
||||
</device>
|
||||
<!-- ... with a DVD Video in it -->
|
||||
<device udi="/org/kde/solid/fakehw/volume_label_SOLIDMAN_BEGINS">
|
||||
<property key="name">SolidMan Begins</property>
|
||||
<property key="interfaces">Block,StorageVolume,OpticalDisc</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/storage_model_solid_reader</property>
|
||||
|
||||
<property key="discType">dvd_rom</property>
|
||||
<property key="isAppendable">false</property>
|
||||
<property key="isRewritable">false</property>
|
||||
<property key="isBlank">false</property>
|
||||
<property key="availableContent">dvdvideo</property>
|
||||
|
||||
<property key="uuid">5012</property>
|
||||
<property key="size">8033075200</property>
|
||||
<property key="label">SolidMan Begins</property>
|
||||
</device>
|
||||
|
||||
|
||||
<!-- Some unmounted storage
|
||||
Most attributes are irrelevant, but it has to be sorted first,
|
||||
and it has to have an empty mountPoint.
|
||||
-->
|
||||
<device udi="/org/kde/solid/fakehw/volume_0000_unmounted_storage">
|
||||
<property key="name">/</property>
|
||||
<property key="interfaces">Block,StorageVolume,StorageAccess</property>
|
||||
<property key="parent">/org/kde/solid/fakehw</property>
|
||||
|
||||
<property key="minor">0</property>
|
||||
<property key="major">253</property>
|
||||
<property key="device">/dev/sdg1</property>
|
||||
|
||||
<property key="isIgnored">true</property>
|
||||
<property key="isMounted">false</property>
|
||||
<property key="mountPoint"></property>
|
||||
<property key="usage">filesystem</property>
|
||||
<property key="fsType">vfat</property>
|
||||
<property key="label">Unmounted_drive</property>
|
||||
<property key="uuid">abcd-0123</property>
|
||||
<property key="size">7742685184</property>
|
||||
</device>
|
||||
|
||||
|
||||
<!-- First USB Controller -->
|
||||
<device udi="/org/kde/solid/fakehw/pci_8086_265c">
|
||||
<property key="name">99021 USB2 EHCI Controller #1</property>
|
||||
<property key="vendor">Acme Corporation</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/computer</property>
|
||||
</device>
|
||||
<!-- Host Controller -->
|
||||
<device udi="/org/kde/solid/fakehw/usb_device_0_0_1d_7">
|
||||
<property key="name">EHCI Host Controller</property>
|
||||
<property key="vendor">Kernel ehci_hcd</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/pci_8086_265c</property>
|
||||
</device>
|
||||
<!-- USB Device -->
|
||||
<device udi="/org/kde/solid/fakehw/usb_device_4e8_5041">
|
||||
<property key="name">Acme XO-Y4</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/usb_device_0_0_1d_7</property>
|
||||
</device>
|
||||
<!-- Mass Storage Interface -->
|
||||
<device udi="/org/kde/solid/fakehw/usb_device_4e8_5041_if0">
|
||||
<property key="name">USB Mass Storage Interface</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/usb_device_4e8_5041</property>
|
||||
</device>
|
||||
<!-- SCSI Adapter -->
|
||||
<device udi="/org/kde/solid/fakehw/usb_device_4e8_5041_if0_scsi_host">
|
||||
<property key="name">SCSI Host Adapter</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/usb_device_4e8_5041_if0</property>
|
||||
</device>
|
||||
<!-- SCSI Device -->
|
||||
<device udi="/org/kde/solid/fakehw/usb_device_4e8_5041_if0_scsi_host_scsi_device_lun0">
|
||||
<property key="name">SCSI Device</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/usb_device_4e8_5041_if0_scsi_host</property>
|
||||
</device>
|
||||
<!-- We finally find the storage device, which is a portable media player... -->
|
||||
<device udi="/org/kde/solid/fakehw/storage_serial_XOY4_5206">
|
||||
<property key="name">XO-Y4</property>
|
||||
<property key="vendor">Acme Electronics</property>
|
||||
<property key="interfaces">StorageDrive,Block,PortableMediaPlayer</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/usb_device_4e8_5041_if0_scsi_host_scsi_device_lun0</property>
|
||||
|
||||
<property key="minor">0</property>
|
||||
<property key="major">8</property>
|
||||
<property key="device">/dev/sda</property>
|
||||
|
||||
<property key="bus">usb</property>
|
||||
<property key="driveType">disk</property>
|
||||
<property key="isRemovable">true</property>
|
||||
<property key="isEjectRequired">true</property>
|
||||
<property key="isHotpluggable">true</property>
|
||||
<property key="isMediaCheckEnabled">true</property>
|
||||
<property key="product">XO-Y4</property>
|
||||
|
||||
<property key="accessMethod">MassStorage</property>
|
||||
<property key="outputFormats">audio/x-mp3</property>
|
||||
<property key="inputFormats">audio/x-wav,audio/x-mp3,audio/vorbis</property>
|
||||
<property key="playlistFormats">audio/x-mpegurl</property>
|
||||
</device>
|
||||
<!-- ... with a partition since it's a USB Mass Storage device -->
|
||||
<device udi="/org/kde/solid/fakehw/volume_part1_size_993284096">
|
||||
<property key="name">StorageVolume (vfat)</property>
|
||||
<property key="interfaces">Block,StorageVolume,StorageAccess</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/storage_serial_XOY4_5206</property>
|
||||
|
||||
<property key="minor">1</property>
|
||||
<property key="major">8</property>
|
||||
<property key="device">/dev/sda1</property>
|
||||
|
||||
<property key="isIgnored">false</property>
|
||||
<property key="isMounted">true</property>
|
||||
<property key="mountPoint">/media/XO-Y4</property>
|
||||
<property key="usage">filesystem</property>
|
||||
<property key="fsType">vfat</property>
|
||||
<property key="size">993284096</property>
|
||||
</device>
|
||||
|
||||
|
||||
|
||||
<!-- Second USB Controller -->
|
||||
<device udi="/org/kde/solid/fakehw/pci_8086_265d">
|
||||
<property key="name">99021 USB UHCI #1</property>
|
||||
<property key="vendor">Acme Corporation</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/computer</property>
|
||||
</device>
|
||||
<!-- Host Controller -->
|
||||
<device udi="/org/kde/solid/fakehw/usb_device_0_0_1d_2">
|
||||
<property key="name">UHCI Host Controller</property>
|
||||
<property key="vendor">Kernel uhci_hcd</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/pci_8086_265d</property>
|
||||
</device>
|
||||
|
||||
<!-- USB Device #1 -->
|
||||
<device udi="/org/kde/solid/fakehw/usb_device_4a9_30b9_noserial">
|
||||
<property key="name">PowerBullet A35</property>
|
||||
<property key="vendor">Firearm Inc.</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/usb_device_0_0_1d_2</property>
|
||||
</device>
|
||||
<!-- We finally find the camera interface -->
|
||||
<device udi="/org/kde/solid/fakehw/usb_device_4a9_30b9_noserial_if0">
|
||||
<property key="name">USB Imaging Interface</property>
|
||||
<property key="interfaces">Camera</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/usb_device_4a9_30b9_noserial</property>
|
||||
<property key="accessMethod">ptp</property>
|
||||
<property key="gphotoSupport">true</property>
|
||||
</device>
|
||||
|
||||
<!-- USB Device #2 containing a battery -->
|
||||
<device udi="/org/kde/solid/fakehw/usb_device_1267_210_noserial">
|
||||
<property key="name">ZX Cordless Mouse</property>
|
||||
<property key="vendor">Logi4 Inc.</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/usb_device_0_0_1d_2</property>
|
||||
<property key="interfaces">Battery</property>
|
||||
|
||||
<property key="isPresent">true</property>
|
||||
<property key="isPowerSupply">false</property>
|
||||
<property key="batteryType">mouse</property>
|
||||
<property key="chargeLevelUnit">mWh</property>
|
||||
<property key="maxLevel">432000</property>
|
||||
<property key="lastFullLevel">421650</property>
|
||||
<property key="currentLevel">421000</property>
|
||||
<property key="warningLevel">1405500</property>
|
||||
<property key="lowLevel">70275</property>
|
||||
<property key="voltageUnit">mV</property>
|
||||
<property key="voltage">5100</property>
|
||||
<property key="isRechargeable">true</property>
|
||||
<property key="chargeState">charging</property>
|
||||
</device>
|
||||
<!-- HID Interface -->
|
||||
<device udi="/org/kde/solid/fakehw/usb_device_1267_210_noserial_if0">
|
||||
<property key="name">USB HID Interface</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/usb_device_1267_210_noserial</property>
|
||||
</device>
|
||||
<!-- We finally find the mouse device -->
|
||||
<device udi="/org/kde/solid/fakehw/usb_device_1267_210_noserial_if0_logical_dev_input">
|
||||
<property key="name">Logi4 Receiver</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/usb_device_1267_210_noserial_if0</property>
|
||||
<!-- TODO: Complete this if we get input (mouse and keyb) related interfaces -->
|
||||
</device>
|
||||
|
||||
<!-- USB Device #3 -->
|
||||
<device udi="/org/kde/solid/fakehw/usb_device_4f1_5d33_HF8459">
|
||||
<property key="name">ORB 2400 series</property>
|
||||
<property key="vendor">Acme Corporation</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/usb_device_0_0_1d_2</property>
|
||||
</device>
|
||||
<!-- USB Printer Interface -->
|
||||
<device udi="/org/kde/solid/fakehw/usb_device_4f1_5d33_HF8459_if0">
|
||||
<property key="name">USB Printer Interface</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/usb_device_4f1_5d33_HF8459</property>
|
||||
</device>
|
||||
<!-- We finally find the printer device -->
|
||||
<device udi="/org/kde/solid/fakehw/usb_device_4f1_5d33_HF8459_if0_printer">
|
||||
<property key="name">ORB 2400 series</property>
|
||||
<property key="vendor">Acme</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/usb_device_4f1_5d33_HF8459_if0</property>
|
||||
<!-- TODO: Complete this if we get printer related interfaces -->
|
||||
</device>
|
||||
|
||||
|
||||
|
||||
<!-- PCI Bridge -->
|
||||
<device udi="/org/kde/solid/fakehw/pci_8086_2448">
|
||||
<property key="name">99021 PCI Bridge</property>
|
||||
<property key="vendor">Acme Corporation</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/computer</property>
|
||||
</device>
|
||||
|
||||
<!-- PCI device #1 -->
|
||||
<device udi="/org/kde/solid/fakehw/pci_3452_7890">
|
||||
<property key="name">Wireless 1144AH</property>
|
||||
<property key="vendor">Acme Corporation</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/pci_8086_2448</property>
|
||||
</device>
|
||||
|
||||
<!-- PCI device #2 -->
|
||||
<device udi="/org/kde/solid/fakehw/pci_8904_5e21">
|
||||
<property key="name">RC-1893</property>
|
||||
<property key="vendor">ReallyChip Corporation</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/pci_8086_2448</property>
|
||||
</device>
|
||||
|
||||
<!-- PCI device #3 -->
|
||||
<device udi="/org/kde/solid/fakehw/pci_8843_6a11">
|
||||
<property key="name">VisioTNT</property>
|
||||
<property key="vendor">DigitalVid Ltd</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/pci_8086_2448</property>
|
||||
</device>
|
||||
<!-- Digital video broadcasting interface -->
|
||||
<device udi="/org/kde/solid/fakehw/pci_8843_6a11_dvb1">
|
||||
<property key="name">DVB Interface</property>
|
||||
<property key="interfaces">DvbInterface</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/pci_8843_6a11</property>
|
||||
<property key="device">/dev/broadcast0/demux</property>
|
||||
<property key="deviceAdapter">2</property>
|
||||
<property key="deviceType">demux</property>
|
||||
<property key="deviceIndex">1</property>
|
||||
</device>
|
||||
|
||||
<device udi="/org/kde/solid/fakehw/fstab">
|
||||
<property key="name">Network Shares</property>
|
||||
<property key="product">Network Shares</property>
|
||||
<property key="vendor">KDE</property>
|
||||
<property key="parent">/org/kde/solid/fakehw/computer</property>
|
||||
</device>
|
||||
<device udi="/org/kde/solid/fakehw/fstab/thehost/solidpath">
|
||||
<property key="parent">/org/kde/solid/fstab</property>
|
||||
<property key="interfaces">NetworkShare,StorageAccess</property>
|
||||
<property key="vendor">/solidpath</property>
|
||||
<property key="product">thehost</property>
|
||||
<property key="type">nfs</property>
|
||||
<property key="url">nfs://thehost/solid-path</property>
|
||||
<property key="filePath">/media/nfs</property>
|
||||
<property key="isIgnored">false</property>
|
||||
<property key="isMounted">true</property>
|
||||
<property key="mountPoint">/media/nfs</property>
|
||||
</device>
|
||||
</machine>
|
||||
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Michaël Larouche <michael.larouche@kdemail.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#include "fakedevice.h"
|
||||
#include "fakedevice_p.h"
|
||||
|
||||
#include "fakebattery.h"
|
||||
#include "fakeblock.h"
|
||||
#include "fakecamera.h"
|
||||
#include "fakecdrom.h"
|
||||
#include "fakedeviceinterface.h"
|
||||
#include "fakegenericinterface.h"
|
||||
#include "fakenetworkshare.h"
|
||||
#include "fakeopticaldisc.h"
|
||||
#include "fakeportablemediaplayer.h"
|
||||
#include "fakeprocessor.h"
|
||||
#include "fakestorage.h"
|
||||
#include "fakestorageaccess.h"
|
||||
#include "fakevolume.h"
|
||||
|
||||
#include <QStringList>
|
||||
#ifdef HAVE_DBUS
|
||||
#include <QDBusConnection>
|
||||
#endif
|
||||
|
||||
#include <solid/genericinterface.h>
|
||||
|
||||
using namespace Solid::Backends::Fake;
|
||||
|
||||
FakeDevice::FakeDevice(const QString &udi, const QMap<QString, QVariant> &propertyMap)
|
||||
: Solid::Ifaces::Device()
|
||||
, d(new Private)
|
||||
{
|
||||
d->udi = udi;
|
||||
d->propertyMap = propertyMap;
|
||||
d->interfaceList = d->propertyMap[QStringLiteral("interfaces")].toString().simplified().split(QLatin1Char(','));
|
||||
d->interfaceList << QStringLiteral("GenericInterface");
|
||||
d->locked = false;
|
||||
d->broken = false;
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
QDBusConnection::sessionBus().registerObject(udi, this, QDBusConnection::ExportNonScriptableSlots);
|
||||
#endif
|
||||
|
||||
// Force instantiation of all the device interfaces
|
||||
// this way they'll get exported on the bus
|
||||
// that means they'll be created twice, but that won't be
|
||||
// a problem for unit testing.
|
||||
for (const QString &interface : std::as_const(d->interfaceList)) {
|
||||
Solid::DeviceInterface::Type type = Solid::DeviceInterface::stringToType(interface);
|
||||
createDeviceInterface(type);
|
||||
}
|
||||
|
||||
connect(d.data(), SIGNAL(propertyChanged(QMap<QString, int>)), this, SIGNAL(propertyChanged(QMap<QString, int>)));
|
||||
connect(d.data(), SIGNAL(conditionRaised(QString, QString)), this, SIGNAL(conditionRaised(QString, QString)));
|
||||
}
|
||||
|
||||
FakeDevice::FakeDevice(const FakeDevice &dev)
|
||||
: Solid::Ifaces::Device()
|
||||
, d(dev.d)
|
||||
{
|
||||
connect(d.data(), SIGNAL(propertyChanged(QMap<QString, int>)), this, SIGNAL(propertyChanged(QMap<QString, int>)));
|
||||
connect(d.data(), SIGNAL(conditionRaised(QString, QString)), this, SIGNAL(conditionRaised(QString, QString)));
|
||||
}
|
||||
|
||||
FakeDevice::~FakeDevice()
|
||||
{
|
||||
#ifdef HAVE_DBUS
|
||||
QDBusConnection::sessionBus().unregisterObject(d->udi, QDBusConnection::UnregisterTree);
|
||||
#endif
|
||||
}
|
||||
|
||||
QString FakeDevice::udi() const
|
||||
{
|
||||
return d->udi;
|
||||
}
|
||||
|
||||
QString FakeDevice::parentUdi() const
|
||||
{
|
||||
return d->propertyMap[QStringLiteral("parent")].toString();
|
||||
}
|
||||
|
||||
QString FakeDevice::vendor() const
|
||||
{
|
||||
return d->propertyMap[QStringLiteral("vendor")].toString();
|
||||
}
|
||||
|
||||
QString FakeDevice::product() const
|
||||
{
|
||||
return d->propertyMap[QStringLiteral("name")].toString();
|
||||
}
|
||||
|
||||
QString FakeDevice::icon() const
|
||||
{
|
||||
if (parentUdi().isEmpty()) {
|
||||
return QStringLiteral("system");
|
||||
} else if (queryDeviceInterface(Solid::DeviceInterface::OpticalDrive)) {
|
||||
return QStringLiteral("cdrom-unmount");
|
||||
} else if (queryDeviceInterface(Solid::DeviceInterface::PortableMediaPlayer)) {
|
||||
return QStringLiteral("ipod-unmount");
|
||||
} else if (queryDeviceInterface(Solid::DeviceInterface::Camera)) {
|
||||
return QStringLiteral("camera-unmount");
|
||||
} else if (queryDeviceInterface(Solid::DeviceInterface::Processor)) {
|
||||
return QStringLiteral("cpu");
|
||||
} else if (queryDeviceInterface(Solid::DeviceInterface::StorageDrive)) {
|
||||
return QStringLiteral("hdd-unmount");
|
||||
} else if (queryDeviceInterface(Solid::DeviceInterface::Block)) {
|
||||
return QStringLiteral("blockdevice");
|
||||
} else {
|
||||
return QStringLiteral("hwinfo");
|
||||
}
|
||||
}
|
||||
|
||||
QStringList FakeDevice::emblems() const
|
||||
{
|
||||
if (queryDeviceInterface(Solid::DeviceInterface::StorageAccess)) {
|
||||
if (property(QStringLiteral("isMounted")).toBool()) {
|
||||
return {QStringLiteral("emblem-mounted")};
|
||||
} else {
|
||||
return {QStringLiteral("emblem-unmounted")};
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
QString FakeDevice::description() const
|
||||
{
|
||||
return product();
|
||||
}
|
||||
|
||||
QVariant FakeDevice::property(const QString &key) const
|
||||
{
|
||||
return d->propertyMap[key];
|
||||
}
|
||||
|
||||
QMap<QString, QVariant> FakeDevice::allProperties() const
|
||||
{
|
||||
return d->propertyMap;
|
||||
}
|
||||
|
||||
bool FakeDevice::propertyExists(const QString &key) const
|
||||
{
|
||||
return d->propertyMap.contains(key);
|
||||
}
|
||||
|
||||
bool FakeDevice::setProperty(const QString &key, const QVariant &value)
|
||||
{
|
||||
if (d->broken) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Solid::GenericInterface::PropertyChange change_type = Solid::GenericInterface::PropertyModified;
|
||||
|
||||
if (!d->propertyMap.contains(key)) {
|
||||
change_type = Solid::GenericInterface::PropertyAdded;
|
||||
}
|
||||
|
||||
d->propertyMap[key] = value;
|
||||
|
||||
QMap<QString, int> change;
|
||||
change[key] = change_type;
|
||||
|
||||
Q_EMIT d->propertyChanged(change);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FakeDevice::removeProperty(const QString &key)
|
||||
{
|
||||
if (d->broken || !d->propertyMap.contains(key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
d->propertyMap.remove(key);
|
||||
|
||||
QMap<QString, int> change;
|
||||
change[key] = Solid::GenericInterface::PropertyRemoved;
|
||||
|
||||
Q_EMIT d->propertyChanged(change);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FakeDevice::setBroken(bool broken)
|
||||
{
|
||||
d->broken = broken;
|
||||
}
|
||||
|
||||
bool FakeDevice::isBroken()
|
||||
{
|
||||
return d->broken;
|
||||
}
|
||||
|
||||
bool FakeDevice::lock(const QString &reason)
|
||||
{
|
||||
if (d->broken || d->locked) {
|
||||
return false;
|
||||
}
|
||||
|
||||
d->locked = true;
|
||||
d->lockReason = reason;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FakeDevice::unlock()
|
||||
{
|
||||
if (d->broken || !d->locked) {
|
||||
return false;
|
||||
}
|
||||
|
||||
d->locked = false;
|
||||
d->lockReason.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FakeDevice::isLocked() const
|
||||
{
|
||||
return d->locked;
|
||||
}
|
||||
|
||||
QString FakeDevice::lockReason() const
|
||||
{
|
||||
return d->lockReason;
|
||||
}
|
||||
|
||||
void FakeDevice::raiseCondition(const QString &condition, const QString &reason)
|
||||
{
|
||||
Q_EMIT d->conditionRaised(condition, reason);
|
||||
}
|
||||
|
||||
bool FakeDevice::queryDeviceInterface(const Solid::DeviceInterface::Type &type) const
|
||||
{
|
||||
return d->interfaceList.contains(Solid::DeviceInterface::typeToString(type));
|
||||
}
|
||||
|
||||
QObject *FakeDevice::createDeviceInterface(const Solid::DeviceInterface::Type &type)
|
||||
{
|
||||
// Do not try to cast with a unsupported device interface.
|
||||
if (!queryDeviceInterface(type)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FakeDeviceInterface *iface = nullptr;
|
||||
|
||||
switch (type) {
|
||||
case Solid::DeviceInterface::GenericInterface:
|
||||
iface = new FakeGenericInterface(this);
|
||||
break;
|
||||
case Solid::DeviceInterface::Processor:
|
||||
iface = new FakeProcessor(this);
|
||||
break;
|
||||
case Solid::DeviceInterface::Block:
|
||||
iface = new FakeBlock(this);
|
||||
break;
|
||||
case Solid::DeviceInterface::StorageDrive:
|
||||
iface = new FakeStorage(this);
|
||||
break;
|
||||
case Solid::DeviceInterface::OpticalDrive:
|
||||
iface = new FakeCdrom(this);
|
||||
break;
|
||||
case Solid::DeviceInterface::StorageVolume:
|
||||
iface = new FakeVolume(this);
|
||||
break;
|
||||
case Solid::DeviceInterface::OpticalDisc:
|
||||
iface = new FakeOpticalDisc(this);
|
||||
break;
|
||||
case Solid::DeviceInterface::StorageAccess:
|
||||
iface = new FakeStorageAccess(this);
|
||||
break;
|
||||
case Solid::DeviceInterface::Camera:
|
||||
iface = new FakeCamera(this);
|
||||
break;
|
||||
case Solid::DeviceInterface::PortableMediaPlayer:
|
||||
iface = new FakePortableMediaPlayer(this);
|
||||
break;
|
||||
case Solid::DeviceInterface::Battery:
|
||||
iface = new FakeBattery(this);
|
||||
break;
|
||||
case Solid::DeviceInterface::NetworkShare:
|
||||
iface = new FakeNetworkShare(this);
|
||||
break;
|
||||
case Solid::DeviceInterface::Unknown:
|
||||
break;
|
||||
case Solid::DeviceInterface::Last:
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
if (iface) {
|
||||
QDBusConnection::sessionBus().registerObject(d->udi + QLatin1Char('/') + Solid::DeviceInterface::typeToString(type),
|
||||
iface,
|
||||
QDBusConnection::ExportNonScriptableSlots);
|
||||
}
|
||||
#endif
|
||||
|
||||
return iface;
|
||||
}
|
||||
|
||||
#include "moc_fakedevice.cpp"
|
||||
#include "moc_fakedevice_p.cpp"
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Michaël Larouche <michael.larouche@kdemail.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#ifndef SOLID_BACKENDS_FAKEHW_FAKEDEVICE_H
|
||||
#define SOLID_BACKENDS_FAKEHW_FAKEDEVICE_H
|
||||
|
||||
#include <solid/devices/ifaces/device.h>
|
||||
|
||||
#include <QMap>
|
||||
#include <QSharedPointer>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fake
|
||||
{
|
||||
class FakeDevice : public Solid::Ifaces::Device
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FakeDevice(const QString &udi, const QMap<QString, QVariant> &propertyMap);
|
||||
FakeDevice(const FakeDevice &dev);
|
||||
~FakeDevice() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
QString udi() const override;
|
||||
QString parentUdi() const override;
|
||||
QString vendor() const override;
|
||||
QString product() const override;
|
||||
QString icon() const override;
|
||||
QStringList emblems() const override;
|
||||
QString description() const override;
|
||||
|
||||
virtual QVariant property(const QString &key) const;
|
||||
virtual QMap<QString, QVariant> allProperties() const;
|
||||
virtual bool propertyExists(const QString &key) const;
|
||||
virtual bool setProperty(const QString &key, const QVariant &value);
|
||||
virtual bool removeProperty(const QString &key);
|
||||
|
||||
virtual bool lock(const QString &reason);
|
||||
virtual bool unlock();
|
||||
virtual bool isLocked() const;
|
||||
virtual QString lockReason() const;
|
||||
|
||||
void setBroken(bool broken);
|
||||
bool isBroken();
|
||||
void raiseCondition(const QString &condition, const QString &reason);
|
||||
|
||||
public:
|
||||
bool queryDeviceInterface(const Solid::DeviceInterface::Type &type) const override;
|
||||
QObject *createDeviceInterface(const Solid::DeviceInterface::Type &type) override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void propertyChanged(const QMap<QString, int> &changes);
|
||||
void conditionRaised(const QString &condition, const QString &reason);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
QSharedPointer<Private> d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_FAKEHW_FAKEDEVICE_H
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Michaël Larouche <michael.larouche@kdemail.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#ifndef SOLID_BACKENDS_FAKEHW_FAKEDEVICE_P_H
|
||||
#define SOLID_BACKENDS_FAKEHW_FAKEDEVICE_P_H
|
||||
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
|
||||
#include "fakedevice.h"
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fake
|
||||
{
|
||||
class FakeDevice;
|
||||
class FakeDevice::Private : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QString udi;
|
||||
QMap<QString, QVariant> propertyMap;
|
||||
QStringList interfaceList;
|
||||
bool locked;
|
||||
QString lockReason;
|
||||
bool broken;
|
||||
|
||||
Q_SIGNALS:
|
||||
void propertyChanged(const QMap<QString, int> &changes);
|
||||
void conditionRaised(const QString &condition, const QString &reason);
|
||||
|
||||
friend class FakeDevice;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Michaël Larouche <michael.larouche@kdemail.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#include "fakedeviceinterface.h"
|
||||
|
||||
using namespace Solid::Backends::Fake;
|
||||
|
||||
FakeDeviceInterface::FakeDeviceInterface(FakeDevice *device)
|
||||
: QObject(device)
|
||||
, m_device(device)
|
||||
{
|
||||
}
|
||||
|
||||
FakeDeviceInterface::~FakeDeviceInterface()
|
||||
{
|
||||
}
|
||||
|
||||
#include "moc_fakedeviceinterface.cpp"
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Michaël Larouche <michael.larouche@kdemail.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#ifndef SOLID_BACKENDS_FAKEHW_FAKEDEVICEINTERFACE_H
|
||||
#define SOLID_BACKENDS_FAKEHW_FAKEDEVICEINTERFACE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <solid/devices/ifaces/deviceinterface.h>
|
||||
|
||||
#include "fakedevice.h"
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fake
|
||||
{
|
||||
class FakeDeviceInterface : public QObject, virtual public Solid::Ifaces::DeviceInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::DeviceInterface)
|
||||
public:
|
||||
explicit FakeDeviceInterface(FakeDevice *device);
|
||||
~FakeDeviceInterface() override;
|
||||
|
||||
protected:
|
||||
FakeDevice *fakeDevice() const
|
||||
{
|
||||
return m_device;
|
||||
}
|
||||
FakeDevice *fakeDevice()
|
||||
{
|
||||
return m_device;
|
||||
}
|
||||
|
||||
private:
|
||||
FakeDevice *m_device;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_FAKEHW_FAKEDEVICEINTERFACE_H
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2007 Kevin Ottens <ervin@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "fakegenericinterface.h"
|
||||
|
||||
using namespace Solid::Backends::Fake;
|
||||
|
||||
FakeGenericInterface::FakeGenericInterface(FakeDevice *device)
|
||||
: FakeDeviceInterface(device)
|
||||
{
|
||||
connect(device, SIGNAL(propertyChanged(QMap<QString, int>)), this, SIGNAL(propertyChanged(QMap<QString, int>)));
|
||||
connect(device, SIGNAL(conditionRaised(QString, QString)), this, SIGNAL(conditionRaised(QString, QString)));
|
||||
}
|
||||
|
||||
FakeGenericInterface::~FakeGenericInterface()
|
||||
{
|
||||
}
|
||||
|
||||
QVariant FakeGenericInterface::property(const QString &key) const
|
||||
{
|
||||
return fakeDevice()->property(key);
|
||||
}
|
||||
|
||||
QMap<QString, QVariant> FakeGenericInterface::allProperties() const
|
||||
{
|
||||
return fakeDevice()->allProperties();
|
||||
}
|
||||
|
||||
bool FakeGenericInterface::propertyExists(const QString &key) const
|
||||
{
|
||||
return fakeDevice()->propertyExists(key);
|
||||
}
|
||||
|
||||
#include "moc_fakegenericinterface.cpp"
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2007 Kevin Ottens <ervin@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_FAKEHW_FAKEGENERICINTERFACE_H
|
||||
#define SOLID_BACKENDS_FAKEHW_FAKEGENERICINTERFACE_H
|
||||
|
||||
#include "fakedeviceinterface.h"
|
||||
#include <solid/devices/ifaces/genericinterface.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fake
|
||||
{
|
||||
class FakeGenericInterface : public FakeDeviceInterface, public Solid::Ifaces::GenericInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::GenericInterface)
|
||||
|
||||
public:
|
||||
explicit FakeGenericInterface(FakeDevice *device);
|
||||
~FakeGenericInterface() override;
|
||||
|
||||
QVariant property(const QString &key) const override;
|
||||
QMap<QString, QVariant> allProperties() const override;
|
||||
bool propertyExists(const QString &key) const override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void propertyChanged(const QMap<QString, int> &changes) override;
|
||||
void conditionRaised(const QString &condition, const QString &reason) override;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_FAKEHW_FAKEGENERICINTERFACE_H
|
||||
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Michaël Larouche <michael.larouche@kdemail.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#include "fakemanager.h"
|
||||
|
||||
#include "fakedevice.h"
|
||||
|
||||
// Qt includes
|
||||
#include <QDebug>
|
||||
#include <QDomDocument>
|
||||
#include <QDomElement>
|
||||
#include <QDomNode>
|
||||
#include <QFile>
|
||||
#include <QString>
|
||||
#ifdef HAVE_DBUS
|
||||
#include <QDBusConnection>
|
||||
#endif
|
||||
|
||||
using namespace Solid::Backends::Fake;
|
||||
|
||||
class FakeManager::Private
|
||||
{
|
||||
public:
|
||||
QMap<QString, FakeDevice *> loadedDevices;
|
||||
QMap<QString, QMap<QString, QVariant>> hiddenDevices;
|
||||
QString xmlFile;
|
||||
QSet<Solid::DeviceInterface::Type> supportedInterfaces;
|
||||
};
|
||||
|
||||
FakeManager::FakeManager(QObject *parent, const QString &xmlFile)
|
||||
: Solid::Ifaces::DeviceManager(parent)
|
||||
, d(new Private)
|
||||
{
|
||||
QString machineXmlFile = xmlFile;
|
||||
d->xmlFile = machineXmlFile;
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
QDBusConnection::sessionBus().registerObject(QStringLiteral("/org/kde/solid/fakehw"), this, QDBusConnection::ExportNonScriptableSlots);
|
||||
#endif
|
||||
|
||||
parseMachineFile();
|
||||
|
||||
// clang-format off
|
||||
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
|
||||
<< Solid::DeviceInterface::NetworkShare;
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
FakeManager::~FakeManager()
|
||||
{
|
||||
#ifdef HAVE_DBUS
|
||||
QDBusConnection::sessionBus().unregisterObject(QStringLiteral("/org/kde/solid/fakehw"), QDBusConnection::UnregisterTree);
|
||||
#endif
|
||||
qDeleteAll(d->loadedDevices);
|
||||
delete d;
|
||||
}
|
||||
|
||||
QString FakeManager::udiPrefix() const
|
||||
{
|
||||
return QStringLiteral("/org/kde/solid/fakehw");
|
||||
}
|
||||
|
||||
QSet<Solid::DeviceInterface::Type> FakeManager::supportedInterfaces() const
|
||||
{
|
||||
return d->supportedInterfaces;
|
||||
}
|
||||
|
||||
QStringList FakeManager::allDevices()
|
||||
{
|
||||
QStringList deviceUdiList;
|
||||
|
||||
for (const FakeDevice *device : std::as_const(d->loadedDevices)) {
|
||||
deviceUdiList.append(device->udi());
|
||||
}
|
||||
|
||||
return deviceUdiList;
|
||||
}
|
||||
|
||||
QStringList FakeManager::devicesFromQuery(const QString &parentUdi, Solid::DeviceInterface::Type type)
|
||||
{
|
||||
if (!parentUdi.isEmpty()) {
|
||||
QStringList found = findDeviceStringMatch(QStringLiteral("parent"), parentUdi);
|
||||
|
||||
if (type == Solid::DeviceInterface::Unknown) {
|
||||
return found;
|
||||
}
|
||||
|
||||
QStringList result;
|
||||
|
||||
QStringList::ConstIterator it = found.constBegin();
|
||||
QStringList::ConstIterator end = found.constEnd();
|
||||
|
||||
for (; it != end; ++it) {
|
||||
FakeDevice *device = d->loadedDevices[*it];
|
||||
|
||||
if (device->queryDeviceInterface(type)) {
|
||||
result << *it;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
} else if (type != Solid::DeviceInterface::Unknown) {
|
||||
return findDeviceByDeviceInterface(type);
|
||||
} else {
|
||||
return allDevices();
|
||||
}
|
||||
}
|
||||
|
||||
QObject *FakeManager::createDevice(const QString &udi)
|
||||
{
|
||||
if (d->loadedDevices.contains(udi)) {
|
||||
return new FakeDevice(*d->loadedDevices[udi]);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FakeDevice *FakeManager::findDevice(const QString &udi)
|
||||
{
|
||||
return d->loadedDevices.value(udi);
|
||||
}
|
||||
|
||||
QStringList FakeManager::findDeviceStringMatch(const QString &key, const QString &value)
|
||||
{
|
||||
QStringList result;
|
||||
for (const FakeDevice *device : std::as_const(d->loadedDevices)) {
|
||||
if (device->property(key).toString() == value) {
|
||||
result.append(device->udi());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QStringList FakeManager::findDeviceByDeviceInterface(Solid::DeviceInterface::Type type)
|
||||
{
|
||||
QStringList result;
|
||||
for (const FakeDevice *device : std::as_const(d->loadedDevices)) {
|
||||
if (device->queryDeviceInterface(type)) {
|
||||
result.append(device->udi());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void FakeManager::plug(const QString &udi)
|
||||
{
|
||||
if (d->hiddenDevices.contains(udi)) {
|
||||
QMap<QString, QVariant> properties = d->hiddenDevices.take(udi);
|
||||
d->loadedDevices[udi] = new FakeDevice(udi, properties);
|
||||
Q_EMIT deviceAdded(udi);
|
||||
}
|
||||
}
|
||||
|
||||
void FakeManager::unplug(const QString &udi)
|
||||
{
|
||||
if (d->loadedDevices.contains(udi)) {
|
||||
FakeDevice *dev = d->loadedDevices.take(udi);
|
||||
d->hiddenDevices[udi] = dev->allProperties();
|
||||
Q_EMIT deviceRemoved(udi);
|
||||
delete dev;
|
||||
}
|
||||
}
|
||||
|
||||
void FakeManager::parseMachineFile()
|
||||
{
|
||||
QFile machineFile(d->xmlFile);
|
||||
if (!machineFile.open(QIODevice::ReadOnly)) {
|
||||
qWarning() << Q_FUNC_INFO << "Error while opening " << d->xmlFile;
|
||||
return;
|
||||
}
|
||||
|
||||
QDomDocument fakeDocument;
|
||||
if (!fakeDocument.setContent(&machineFile)) {
|
||||
qWarning() << Q_FUNC_INFO << "Error while creating the QDomDocument.";
|
||||
machineFile.close();
|
||||
return;
|
||||
}
|
||||
machineFile.close();
|
||||
|
||||
qDebug() << Q_FUNC_INFO << "Parsing fake computer XML: " << d->xmlFile;
|
||||
QDomElement mainElement = fakeDocument.documentElement();
|
||||
QDomNode node = mainElement.firstChild();
|
||||
while (!node.isNull()) {
|
||||
QDomElement tempElement = node.toElement();
|
||||
if (!tempElement.isNull() && tempElement.tagName() == QLatin1String("device")) {
|
||||
FakeDevice *tempDevice = parseDeviceElement(tempElement);
|
||||
if (tempDevice) {
|
||||
Q_ASSERT(!d->loadedDevices.contains(tempDevice->udi()));
|
||||
d->loadedDevices.insert(tempDevice->udi(), tempDevice);
|
||||
Q_EMIT deviceAdded(tempDevice->udi());
|
||||
}
|
||||
}
|
||||
|
||||
node = node.nextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
FakeDevice *FakeManager::parseDeviceElement(const QDomElement &deviceElement)
|
||||
{
|
||||
FakeDevice *device = nullptr;
|
||||
QMap<QString, QVariant> propertyMap;
|
||||
QString udi = deviceElement.attribute(QStringLiteral("udi"));
|
||||
|
||||
QDomNode propertyNode = deviceElement.firstChild();
|
||||
while (!propertyNode.isNull()) {
|
||||
QDomElement propertyElement = propertyNode.toElement();
|
||||
if (!propertyElement.isNull() && propertyElement.tagName() == QLatin1String("property")) {
|
||||
QString propertyKey;
|
||||
QVariant propertyValue;
|
||||
|
||||
propertyKey = propertyElement.attribute(QStringLiteral("key"));
|
||||
propertyValue = QVariant(propertyElement.text());
|
||||
|
||||
propertyMap.insert(propertyKey, propertyValue);
|
||||
}
|
||||
|
||||
propertyNode = propertyNode.nextSibling();
|
||||
}
|
||||
|
||||
if (!propertyMap.isEmpty()) {
|
||||
device = new FakeDevice(udi, propertyMap);
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
#include "moc_fakemanager.cpp"
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Michaël Larouche <michael.larouche@kdemail.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_FAKEHW_FAKEMANAGER_H
|
||||
#define SOLID_BACKENDS_FAKEHW_FAKEMANAGER_H
|
||||
|
||||
#include <solid/devices/ifaces/devicemanager.h>
|
||||
|
||||
class QDomElement;
|
||||
|
||||
using namespace Solid::Ifaces;
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fake
|
||||
{
|
||||
class FakeDevice;
|
||||
|
||||
/**
|
||||
* @brief a Fake manager that read a device list from a XML file.
|
||||
* This fake manager is used for unit tests and developers.
|
||||
*
|
||||
* @author Michaël Larouche <michael.larouche@kdemail.net>
|
||||
*/
|
||||
class FakeManager : public Solid::Ifaces::DeviceManager
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FakeManager(QObject *parent, const QString &xmlFile);
|
||||
~FakeManager() override;
|
||||
|
||||
QString udiPrefix() const override;
|
||||
QSet<Solid::DeviceInterface::Type> supportedInterfaces() const override;
|
||||
|
||||
/**
|
||||
* Return the list of UDI of all available devices.
|
||||
*/
|
||||
QStringList allDevices() override;
|
||||
|
||||
QStringList devicesFromQuery(const QString &parentUdi, Solid::DeviceInterface::Type type) override;
|
||||
|
||||
QObject *createDevice(const QString &udi) override;
|
||||
virtual FakeDevice *findDevice(const QString &udi);
|
||||
|
||||
public Q_SLOTS:
|
||||
void plug(const QString &udi);
|
||||
void unplug(const QString &udi);
|
||||
|
||||
private Q_SLOTS:
|
||||
/**
|
||||
* @internal
|
||||
* Parse the XML file that represent the fake machine.
|
||||
*/
|
||||
void parseMachineFile();
|
||||
/**
|
||||
* @internal
|
||||
* Parse a device node and the return the device.
|
||||
*/
|
||||
FakeDevice *parseDeviceElement(const QDomElement &element);
|
||||
|
||||
private:
|
||||
QStringList findDeviceStringMatch(const QString &key, const QString &value);
|
||||
QStringList findDeviceByDeviceInterface(Solid::DeviceInterface::Type type);
|
||||
|
||||
class Private;
|
||||
Private *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_FAKEHW_FAKEMANAGER_H
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2011 Mario Bensi <mbensi@ipsquad.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "fakenetworkshare.h"
|
||||
#include <QVariant>
|
||||
|
||||
using namespace Solid::Backends::Fake;
|
||||
|
||||
FakeNetworkShare::FakeNetworkShare(FakeDevice *device)
|
||||
: FakeDeviceInterface(device)
|
||||
{
|
||||
}
|
||||
|
||||
FakeNetworkShare::~FakeNetworkShare()
|
||||
{
|
||||
}
|
||||
|
||||
Solid::NetworkShare::ShareType FakeNetworkShare::type() const
|
||||
{
|
||||
QString type = fakeDevice()->property(QStringLiteral("type")).toString();
|
||||
if (type == QLatin1String("nfs")) {
|
||||
return Solid::NetworkShare::Nfs;
|
||||
} else if (type == QLatin1String("cifs")) {
|
||||
return Solid::NetworkShare::Cifs;
|
||||
} else if (type == QLatin1String("smb3")) {
|
||||
return Solid::NetworkShare::Smb3;
|
||||
} else {
|
||||
return Solid::NetworkShare::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
QUrl FakeNetworkShare::url() const
|
||||
{
|
||||
QString url = fakeDevice()->property(QStringLiteral("url")).toString();
|
||||
return QUrl(url);
|
||||
}
|
||||
|
||||
#include "moc_fakenetworkshare.cpp"
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2011 Mario Bensi <mbensi@ipsquad.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_FAKE_NETWORKSHARE_H
|
||||
#define SOLID_BACKENDS_FAKE_NETWORKSHARE_H
|
||||
|
||||
#include "fakedeviceinterface.h"
|
||||
#include <solid/devices/ifaces/networkshare.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fake
|
||||
{
|
||||
class FakeNetworkShare : public FakeDeviceInterface, public Solid::Ifaces::NetworkShare
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::NetworkShare)
|
||||
|
||||
public:
|
||||
explicit FakeNetworkShare(FakeDevice *device);
|
||||
|
||||
~FakeNetworkShare() override;
|
||||
|
||||
Solid::NetworkShare::ShareType type() const override;
|
||||
|
||||
QUrl url() const override;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_FAKE_NETWORKSHARE_H
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Davide Bettio <davide.bettio@kdemail.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "fakeopticaldisc.h"
|
||||
|
||||
#include <QStringList>
|
||||
#include <QVariant>
|
||||
|
||||
using namespace Solid::Backends::Fake;
|
||||
|
||||
FakeOpticalDisc::FakeOpticalDisc(FakeDevice *device)
|
||||
: FakeVolume(device)
|
||||
{
|
||||
}
|
||||
|
||||
FakeOpticalDisc::~FakeOpticalDisc()
|
||||
{
|
||||
}
|
||||
|
||||
Solid::OpticalDisc::ContentTypes FakeOpticalDisc::availableContent() const
|
||||
{
|
||||
Solid::OpticalDisc::ContentTypes content;
|
||||
|
||||
const QMap<QString, Solid::OpticalDisc::ContentType> map = {
|
||||
{QStringLiteral("audio"), Solid::OpticalDisc::Audio},
|
||||
{QStringLiteral("data"), Solid::OpticalDisc::Data},
|
||||
{QStringLiteral("vcd"), Solid::OpticalDisc::VideoCd},
|
||||
{QStringLiteral("svcd"), Solid::OpticalDisc::SuperVideoCd},
|
||||
{QStringLiteral("videodvd"), Solid::OpticalDisc::VideoDvd},
|
||||
};
|
||||
|
||||
const QStringList content_typelist = fakeDevice()->property(QStringLiteral("availableContent")).toString().split(QLatin1Char(','));
|
||||
|
||||
for (const QString &type : content_typelist) {
|
||||
content |= map.value(type, Solid::OpticalDisc::NoContent);
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
Solid::OpticalDisc::DiscType FakeOpticalDisc::discType() const
|
||||
{
|
||||
QString type = fakeDevice()->property(QStringLiteral("discType")).toString();
|
||||
|
||||
if (type == QLatin1String("cd_rom")) {
|
||||
return Solid::OpticalDisc::CdRom;
|
||||
} else if (type == QLatin1String("cd_r")) {
|
||||
return Solid::OpticalDisc::CdRecordable;
|
||||
} else if (type == QLatin1String("cd_rw")) {
|
||||
return Solid::OpticalDisc::CdRewritable;
|
||||
} else if (type == QLatin1String("dvd_rom")) {
|
||||
return Solid::OpticalDisc::DvdRom;
|
||||
} else if (type == QLatin1String("dvd_ram")) {
|
||||
return Solid::OpticalDisc::DvdRam;
|
||||
} else if (type == QLatin1String("dvd_r")) {
|
||||
return Solid::OpticalDisc::DvdRecordable;
|
||||
} else if (type == QLatin1String("dvd_rw")) {
|
||||
return Solid::OpticalDisc::DvdRewritable;
|
||||
} else if (type == QLatin1String("dvd_plus_r")) {
|
||||
return Solid::OpticalDisc::DvdPlusRecordable;
|
||||
} else if (type == QLatin1String("dvd_plus_rw")) {
|
||||
return Solid::OpticalDisc::DvdPlusRewritable;
|
||||
} else if (type == QLatin1String("dvd_plus_r_dl")) {
|
||||
return Solid::OpticalDisc::DvdPlusRecordableDuallayer;
|
||||
} else if (type == QLatin1String("dvd_plus_rw_dl")) {
|
||||
return Solid::OpticalDisc::DvdPlusRewritableDuallayer;
|
||||
} else if (type == QLatin1String("bd_rom")) {
|
||||
return Solid::OpticalDisc::BluRayRom;
|
||||
} else if (type == QLatin1String("bd_r")) {
|
||||
return Solid::OpticalDisc::BluRayRecordable;
|
||||
} else if (type == QLatin1String("bd_re")) {
|
||||
return Solid::OpticalDisc::BluRayRewritable;
|
||||
} else if (type == QLatin1String("hddvd_rom")) {
|
||||
return Solid::OpticalDisc::HdDvdRom;
|
||||
} else if (type == QLatin1String("hddvd_r")) {
|
||||
return Solid::OpticalDisc::HdDvdRecordable;
|
||||
} else if (type == QLatin1String("hddvd_rw")) {
|
||||
return Solid::OpticalDisc::HdDvdRewritable;
|
||||
} else {
|
||||
return Solid::OpticalDisc::UnknownDiscType;
|
||||
}
|
||||
}
|
||||
|
||||
bool FakeOpticalDisc::isAppendable() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("isAppendable")).toBool();
|
||||
}
|
||||
|
||||
bool FakeOpticalDisc::isBlank() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("isBlank")).toBool();
|
||||
}
|
||||
|
||||
bool FakeOpticalDisc::isRewritable() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("isRewritable")).toBool();
|
||||
}
|
||||
|
||||
qulonglong FakeOpticalDisc::capacity() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("capacity")).toULongLong();
|
||||
}
|
||||
|
||||
#include "moc_fakeopticaldisc.cpp"
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Davide Bettio <davide.bettio@kdemail.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_FAKEHW_FAKEOPTICALDISC_H
|
||||
#define SOLID_BACKENDS_FAKEHW_FAKEOPTICALDISC_H
|
||||
|
||||
#include "fakevolume.h"
|
||||
#include <solid/devices/ifaces/opticaldisc.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fake
|
||||
{
|
||||
class FakeOpticalDisc : public FakeVolume, virtual public Solid::Ifaces::OpticalDisc
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::OpticalDisc)
|
||||
|
||||
public:
|
||||
explicit FakeOpticalDisc(FakeDevice *device);
|
||||
~FakeOpticalDisc() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
Solid::OpticalDisc::ContentTypes availableContent() const override;
|
||||
Solid::OpticalDisc::DiscType discType() const override;
|
||||
bool isAppendable() const override;
|
||||
bool isBlank() const override;
|
||||
bool isRewritable() const override;
|
||||
qulonglong capacity() const override;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_FAKEHW_FAKEOPTICALDISC_H
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Davide Bettio <davide.bettio@kdemail.net>
|
||||
SPDX-FileCopyrightText: 2007 Jeff Mitchell <kde-dev@emailgoeshere.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "fakeportablemediaplayer.h"
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
using namespace Solid::Backends::Fake;
|
||||
|
||||
FakePortableMediaPlayer::FakePortableMediaPlayer(FakeDevice *device)
|
||||
: FakeDeviceInterface(device)
|
||||
{
|
||||
}
|
||||
|
||||
FakePortableMediaPlayer::~FakePortableMediaPlayer()
|
||||
{
|
||||
}
|
||||
|
||||
QStringList FakePortableMediaPlayer::supportedProtocols() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("supportedProtocols")).toString().simplified().split(QLatin1Char(','));
|
||||
}
|
||||
|
||||
QStringList FakePortableMediaPlayer::supportedDrivers(QString protocol) const
|
||||
{
|
||||
Q_UNUSED(protocol);
|
||||
return fakeDevice()->property(QStringLiteral("supportedDrivers")).toString().simplified().split(QLatin1Char(','));
|
||||
}
|
||||
|
||||
QVariant Solid::Backends::Fake::FakePortableMediaPlayer::driverHandle(const QString &driver) const
|
||||
{
|
||||
Q_UNUSED(driver);
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
#include "moc_fakeportablemediaplayer.cpp"
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Davide Bettio <davide.bettio@kdemail.net>
|
||||
SPDX-FileCopyrightText: 2007 Jeff Mitchell <kde-dev@emailgoeshere.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_FAKEHW_FAKEPORTABLEMEDIAPLAYER_H
|
||||
#define SOLID_BACKENDS_FAKEHW_FAKEPORTABLEMEDIAPLAYER_H
|
||||
|
||||
#include "fakedeviceinterface.h"
|
||||
#include <solid/devices/ifaces/portablemediaplayer.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fake
|
||||
{
|
||||
class FakePortableMediaPlayer : public FakeDeviceInterface, virtual public Solid::Ifaces::PortableMediaPlayer
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::PortableMediaPlayer)
|
||||
|
||||
public:
|
||||
explicit FakePortableMediaPlayer(FakeDevice *device);
|
||||
~FakePortableMediaPlayer() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
QStringList supportedProtocols() const override;
|
||||
QStringList supportedDrivers(QString protocol) const override;
|
||||
QVariant driverHandle(const QString &driver) const override;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_FAKEHW_FAKEPORTABLEMEDIAPLAYER_H
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Michaël Larouche <michael.larouche@kdemail.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "fakeprocessor.h"
|
||||
|
||||
#include <QStringList>
|
||||
#include <QVariant>
|
||||
|
||||
using namespace Solid::Backends::Fake;
|
||||
|
||||
FakeProcessor::FakeProcessor(FakeDevice *device)
|
||||
: FakeDeviceInterface(device)
|
||||
{
|
||||
}
|
||||
|
||||
FakeProcessor::~FakeProcessor()
|
||||
{
|
||||
}
|
||||
|
||||
int FakeProcessor::number() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("number")).toInt();
|
||||
}
|
||||
|
||||
int FakeProcessor::maxSpeed() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("maxSpeed")).toInt();
|
||||
}
|
||||
|
||||
bool FakeProcessor::canChangeFrequency() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("canChangeFrequency")).toBool();
|
||||
}
|
||||
|
||||
Solid::Processor::InstructionSets FakeProcessor::instructionSets() const
|
||||
{
|
||||
Solid::Processor::InstructionSets result;
|
||||
|
||||
const QStringList extension_list = fakeDevice()->property(QStringLiteral("instructionSets")).toString().split(QLatin1Char(','));
|
||||
for (const QString &extension_str : extension_list) {
|
||||
if (extension_str == QLatin1String("mmx")) {
|
||||
result |= Solid::Processor::IntelMmx;
|
||||
} else if (extension_str == QLatin1String("sse")) {
|
||||
result |= Solid::Processor::IntelSse;
|
||||
} else if (extension_str == QLatin1String("sse2")) {
|
||||
result |= Solid::Processor::IntelSse2;
|
||||
} else if (extension_str == QLatin1String("sse3")) {
|
||||
result |= Solid::Processor::IntelSse3;
|
||||
} else if (extension_str == QLatin1String("sse4")) {
|
||||
result |= Solid::Processor::IntelSse4;
|
||||
} else if (extension_str == QLatin1String("3dnow")) {
|
||||
result |= Solid::Processor::Amd3DNow;
|
||||
} else if (extension_str == QLatin1String("altivec")) {
|
||||
result |= Solid::Processor::AltiVec;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#include "moc_fakeprocessor.cpp"
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Michaël Larouche <michael.larouche@kdemail.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_FAKEHW_FAKEPROCESSOR_H
|
||||
#define SOLID_BACKENDS_FAKEHW_FAKEPROCESSOR_H
|
||||
|
||||
#include "fakedeviceinterface.h"
|
||||
#include <solid/devices/ifaces/processor.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fake
|
||||
{
|
||||
class FakeProcessor : public FakeDeviceInterface, public Solid::Ifaces::Processor
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::Processor)
|
||||
|
||||
public:
|
||||
explicit FakeProcessor(FakeDevice *device);
|
||||
~FakeProcessor() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
int number() const override;
|
||||
int maxSpeed() const override;
|
||||
bool canChangeFrequency() const override;
|
||||
Solid::Processor::InstructionSets instructionSets() const override;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_FAKEHW_FAKEPROCESSOR_H
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Davide Bettio <davide.bettio@kdemail.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "fakestorage.h"
|
||||
#include <QVariant>
|
||||
|
||||
using namespace Solid::Backends::Fake;
|
||||
|
||||
FakeStorage::FakeStorage(FakeDevice *device)
|
||||
: FakeBlock(device)
|
||||
{
|
||||
}
|
||||
|
||||
FakeStorage::~FakeStorage()
|
||||
{
|
||||
}
|
||||
|
||||
Solid::StorageDrive::Bus FakeStorage::bus() const
|
||||
{
|
||||
QString bus = fakeDevice()->property(QStringLiteral("bus")).toString();
|
||||
|
||||
if (bus == QLatin1String("ide")) {
|
||||
return Solid::StorageDrive::Ide;
|
||||
} else if (bus == QLatin1String("usb")) {
|
||||
return Solid::StorageDrive::Usb;
|
||||
} else if (bus == QLatin1String("ieee1394")) {
|
||||
return Solid::StorageDrive::Ieee1394;
|
||||
} else if (bus == QLatin1String("scsi")) {
|
||||
return Solid::StorageDrive::Scsi;
|
||||
} else if (bus == QLatin1String("sata")) {
|
||||
return Solid::StorageDrive::Sata;
|
||||
} else {
|
||||
return Solid::StorageDrive::Platform;
|
||||
}
|
||||
}
|
||||
|
||||
Solid::StorageDrive::DriveType FakeStorage::driveType() const
|
||||
{
|
||||
QString type = fakeDevice()->property(QStringLiteral("major")).toString();
|
||||
|
||||
if (type == QLatin1String("disk")) {
|
||||
return Solid::StorageDrive::HardDisk;
|
||||
} else if (type == QLatin1String("cdrom")) {
|
||||
return Solid::StorageDrive::CdromDrive;
|
||||
} else if (type == QLatin1String("floppy")) {
|
||||
return Solid::StorageDrive::Floppy;
|
||||
} else if (type == QLatin1String("tape")) {
|
||||
return Solid::StorageDrive::Tape;
|
||||
} else if (type == QLatin1String("compact_flash")) {
|
||||
return Solid::StorageDrive::CompactFlash;
|
||||
} else if (type == QLatin1String("memory_stick")) {
|
||||
return Solid::StorageDrive::MemoryStick;
|
||||
} else if (type == QLatin1String("smart_media")) {
|
||||
return Solid::StorageDrive::SmartMedia;
|
||||
} else if (type == QLatin1String("sd_mmc")) {
|
||||
return Solid::StorageDrive::SdMmc;
|
||||
} else {
|
||||
return Solid::StorageDrive::HardDisk;
|
||||
}
|
||||
}
|
||||
|
||||
bool FakeStorage::isRemovable() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("isRemovable")).toBool();
|
||||
}
|
||||
|
||||
bool FakeStorage::isHotpluggable() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("isHotpluggable")).toBool();
|
||||
}
|
||||
|
||||
qulonglong FakeStorage::size() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("size")).toULongLong();
|
||||
}
|
||||
|
||||
QDateTime FakeStorage::timeDetected() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("timeDetected")).toDateTime();
|
||||
}
|
||||
|
||||
QDateTime FakeStorage::timeMediaDetected() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("timeMediaDetected")).toDateTime();
|
||||
}
|
||||
|
||||
#include "moc_fakestorage.cpp"
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Davide Bettio <davide.bettio@kdemail.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_FAKEHW_FAKESTORAGE_H
|
||||
#define SOLID_BACKENDS_FAKEHW_FAKESTORAGE_H
|
||||
|
||||
#include "fakeblock.h"
|
||||
#include <solid/devices/ifaces/storagedrive.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fake
|
||||
{
|
||||
class FakeStorage : public FakeBlock, virtual public Solid::Ifaces::StorageDrive
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::StorageDrive)
|
||||
|
||||
public:
|
||||
explicit FakeStorage(FakeDevice *device);
|
||||
~FakeStorage() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
Solid::StorageDrive::Bus bus() const override;
|
||||
Solid::StorageDrive::DriveType driveType() const override;
|
||||
|
||||
bool isRemovable() const override;
|
||||
bool isHotpluggable() const override;
|
||||
qulonglong size() const override;
|
||||
|
||||
QDateTime timeDetected() const override;
|
||||
QDateTime timeMediaDetected() const override;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_FAKEHW_FAKESTORAGE_H
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2007 Kevin Ottens <ervin@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "fakestorageaccess.h"
|
||||
|
||||
using namespace Solid::Backends::Fake;
|
||||
|
||||
FakeStorageAccess::FakeStorageAccess(FakeDevice *device)
|
||||
: FakeDeviceInterface(device)
|
||||
{
|
||||
connect(device, SIGNAL(propertyChanged(QMap<QString, int>)), this, SLOT(onPropertyChanged(QMap<QString, int>)));
|
||||
}
|
||||
|
||||
FakeStorageAccess::~FakeStorageAccess()
|
||||
{
|
||||
}
|
||||
|
||||
bool FakeStorageAccess::isAccessible() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("isMounted")).toBool();
|
||||
}
|
||||
|
||||
QString FakeStorageAccess::filePath() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("mountPoint")).toString();
|
||||
}
|
||||
|
||||
bool FakeStorageAccess::isIgnored() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("isIgnored")).toBool();
|
||||
}
|
||||
|
||||
bool FakeStorageAccess::isEncrypted() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("isEncrypted")).toBool();
|
||||
}
|
||||
|
||||
bool FakeStorageAccess::setup()
|
||||
{
|
||||
if (fakeDevice()->isBroken() || isAccessible()) {
|
||||
return false;
|
||||
} else {
|
||||
fakeDevice()->setProperty(QStringLiteral("isMounted"), true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool FakeStorageAccess::teardown()
|
||||
{
|
||||
if (fakeDevice()->isBroken() || !isAccessible()) {
|
||||
return false;
|
||||
} else {
|
||||
fakeDevice()->setProperty(QStringLiteral("isMounted"), false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void Solid::Backends::Fake::FakeStorageAccess::onPropertyChanged(const QMap<QString, int> &changes)
|
||||
{
|
||||
for (auto it = changes.cbegin(); it != changes.cend(); ++it) {
|
||||
if (it.key() == QLatin1String(QLatin1String("isMounted"))) {
|
||||
Q_EMIT accessibilityChanged(fakeDevice()->property(QStringLiteral("isMounted")).toBool(), fakeDevice()->udi());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_fakestorageaccess.cpp"
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2007 Kevin Ottens <ervin@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_FAKEHW_FAKESTORAGEACCESS_H
|
||||
#define SOLID_BACKENDS_FAKEHW_FAKESTORAGEACCESS_H
|
||||
|
||||
#include "fakedeviceinterface.h"
|
||||
#include <solid/devices/ifaces/storageaccess.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fake
|
||||
{
|
||||
class FakeStorageAccess : public FakeDeviceInterface, virtual public Solid::Ifaces::StorageAccess
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::StorageAccess)
|
||||
|
||||
public:
|
||||
FakeStorageAccess(FakeDevice *device);
|
||||
~FakeStorageAccess() override;
|
||||
|
||||
bool isAccessible() const override;
|
||||
QString filePath() const override;
|
||||
bool isIgnored() const override;
|
||||
bool isEncrypted() const override;
|
||||
public Q_SLOTS:
|
||||
bool setup() override;
|
||||
bool teardown() override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void accessibilityChanged(bool accessible, const QString &udi) override;
|
||||
void setupDone(Solid::ErrorType error, QVariant errorData, const QString &udi) override;
|
||||
void teardownDone(Solid::ErrorType error, QVariant errorData, const QString &udi) override;
|
||||
void setupRequested(const QString &udi) override;
|
||||
void teardownRequested(const QString &udi) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void onPropertyChanged(const QMap<QString, int> &changes);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_FAKEHW_FAKESTORAGEACCESS_H
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Davide Bettio <davide.bettio@kdemail.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "fakevolume.h"
|
||||
#include <QVariant>
|
||||
|
||||
using namespace Solid::Backends::Fake;
|
||||
|
||||
FakeVolume::FakeVolume(FakeDevice *device)
|
||||
: FakeBlock(device)
|
||||
{
|
||||
}
|
||||
|
||||
FakeVolume::~FakeVolume()
|
||||
{
|
||||
}
|
||||
|
||||
bool FakeVolume::isIgnored() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("isIgnored")).toBool();
|
||||
}
|
||||
|
||||
Solid::StorageVolume::UsageType FakeVolume::usage() const
|
||||
{
|
||||
QString usage = fakeDevice()->property(QStringLiteral("usage")).toString();
|
||||
|
||||
if (usage == QLatin1String("filesystem")) {
|
||||
return Solid::StorageVolume::FileSystem;
|
||||
} else if (usage == QLatin1String("partitiontable")) {
|
||||
return Solid::StorageVolume::PartitionTable;
|
||||
} else if (usage == QLatin1String("raid")) {
|
||||
return Solid::StorageVolume::Raid;
|
||||
} else if (usage == QLatin1String("unused")) {
|
||||
return Solid::StorageVolume::Unused;
|
||||
} else if (usage == QLatin1String("encrypted")) {
|
||||
return Solid::StorageVolume::Encrypted;
|
||||
} else {
|
||||
return Solid::StorageVolume::Other;
|
||||
}
|
||||
}
|
||||
|
||||
QString FakeVolume::fsType() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("fsType")).toString();
|
||||
}
|
||||
|
||||
QString FakeVolume::label() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("label")).toString();
|
||||
}
|
||||
|
||||
QString FakeVolume::uuid() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("uuid")).toString();
|
||||
}
|
||||
|
||||
qulonglong FakeVolume::size() const
|
||||
{
|
||||
return fakeDevice()->property(QStringLiteral("size")).toULongLong();
|
||||
}
|
||||
|
||||
QString Solid::Backends::Fake::FakeVolume::encryptedContainerUdi() const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
#include "moc_fakevolume.cpp"
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Davide Bettio <davide.bettio@kdemail.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_FAKEHW_FAKEVOLUME_H
|
||||
#define SOLID_BACKENDS_FAKEHW_FAKEVOLUME_H
|
||||
|
||||
#include "fakeblock.h"
|
||||
#include <solid/devices/ifaces/storagevolume.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fake
|
||||
{
|
||||
class FakeVolume : public FakeBlock, virtual public Solid::Ifaces::StorageVolume
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::StorageVolume)
|
||||
|
||||
public:
|
||||
explicit FakeVolume(FakeDevice *device);
|
||||
~FakeVolume() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
bool isIgnored() const override;
|
||||
Solid::StorageVolume::UsageType usage() const override;
|
||||
QString fsType() const override;
|
||||
QString label() const override;
|
||||
QString uuid() const override;
|
||||
qulonglong size() const override;
|
||||
QString encryptedContainerUdi() const override;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_FAKEHW_FAKEVOLUME_H
|
||||
@@ -0,0 +1,18 @@
|
||||
set(backend_sources
|
||||
fstabmanager.cpp
|
||||
fstabdevice.cpp
|
||||
fstabnetworkshare.cpp
|
||||
fstabstorageaccess.cpp
|
||||
fstabhandling.cpp
|
||||
fstabwatcher.cpp
|
||||
)
|
||||
|
||||
ecm_qt_declare_logging_category(backend_sources
|
||||
HEADER fstab_debug.h
|
||||
IDENTIFIER Solid::Backends::Fstab::FSTAB_LOG
|
||||
DEFAULT_SEVERITY Warning
|
||||
CATEGORY_NAME kf.solid.backends.fstab
|
||||
OLD_CATEGORY_NAMES org.kde.solid.fstab
|
||||
DESCRIPTION "Fstab (Solid)"
|
||||
EXPORT SOLID
|
||||
)
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Mario Bensi <mbensi@ipsquad.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "fstabdevice.h"
|
||||
#include "fstab_debug.h"
|
||||
#include "fstabhandling.h"
|
||||
#include "fstabnetworkshare.h"
|
||||
#include "fstabservice.h"
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QUrl>
|
||||
|
||||
using namespace Solid::Backends::Fstab;
|
||||
|
||||
FstabDevice::FstabDevice(QString uid)
|
||||
: Solid::Ifaces::Device()
|
||||
, m_uid(uid)
|
||||
{
|
||||
m_device = m_uid.mid(parentUdi().length() + 1);
|
||||
|
||||
const QString &fstype = FstabHandling::fstype(m_device);
|
||||
qCDebug(FSTAB_LOG) << "Adding " << m_device << "type:" << fstype;
|
||||
|
||||
if (m_device.startsWith(QLatin1String("//"))) {
|
||||
m_vendor = m_device.mid(2, m_device.indexOf(QLatin1String("/"), 2) - 2);
|
||||
m_product = m_device.mid(m_device.indexOf(QLatin1String("/"), 2) + 1);
|
||||
m_storageType = StorageType::NetworkShare;
|
||||
} else if (fstype.startsWith(QLatin1String("nfs"))) {
|
||||
m_vendor = m_device.left(m_device.indexOf(QLatin1String(":/")));
|
||||
m_product = m_device.mid(m_device.indexOf(QLatin1String(":/")) + 1);
|
||||
m_storageType = StorageType::NetworkShare;
|
||||
} else if (fstype.startsWith(QLatin1String("fuse.")) || fstype == QLatin1String("overlay")) {
|
||||
m_vendor = fstype;
|
||||
m_product = m_device.mid(m_device.indexOf(fstype) + fstype.length());
|
||||
QString home = QDir::homePath();
|
||||
if (m_product.startsWith(home)) {
|
||||
m_product = QStringLiteral("~") + m_product.mid(home.length());
|
||||
}
|
||||
if ((fstype == QLatin1String("fuse.encfs")) || (fstype == QLatin1String("fuse.cryfs")) || (fstype == QLatin1String("fuse.gocryptfs"))) {
|
||||
m_storageType = StorageType::Encrypted;
|
||||
} else if (fstype == QLatin1String("fuse.sshfs") || fstype == QLatin1String("fuse.rclone")) {
|
||||
m_storageType = StorageType::NetworkShare;
|
||||
}
|
||||
}
|
||||
|
||||
const auto &options = FstabHandling::options(m_device);
|
||||
|
||||
const auto gvfsName = options.value(QLatin1String("x-gvfs-name"));
|
||||
if (!gvfsName.isEmpty()) {
|
||||
m_displayName = QUrl::fromPercentEncoding(gvfsName.toUtf8());
|
||||
}
|
||||
const auto gvfsIcon = options.value(QLatin1String("x-gvfs-icon"));
|
||||
if (!gvfsIcon.isEmpty()) {
|
||||
m_iconName = QUrl::fromPercentEncoding(gvfsIcon.toUtf8());
|
||||
}
|
||||
|
||||
if (m_storageType == StorageType::NetworkShare) {
|
||||
m_description = QCoreApplication::translate("", "%1 on %2", "%1 is sharename, %2 is servername").arg(m_product, m_vendor);
|
||||
} else {
|
||||
m_description = QCoreApplication::translate("", "%1 (%2)", "%1 is mountpoint, %2 is fs type").arg(m_product, m_vendor);
|
||||
}
|
||||
|
||||
if (m_displayName.isEmpty()) {
|
||||
const QStringList currentMountPoints = FstabHandling::currentMountPoints(m_device);
|
||||
if (currentMountPoints.isEmpty()) {
|
||||
const QStringList mountPoints = FstabHandling::mountPoints(m_device);
|
||||
m_displayName = mountPoints.isEmpty() ? m_description : mountPoints.first();
|
||||
} else {
|
||||
m_displayName = currentMountPoints.first();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_iconName.isEmpty()) {
|
||||
if (m_storageType == StorageType::NetworkShare) {
|
||||
m_iconName = QStringLiteral("network-server");
|
||||
} else if (m_storageType == StorageType::Encrypted) {
|
||||
m_iconName = QStringLiteral("folder-decrypted");
|
||||
} else {
|
||||
const QStringList &mountPoints = FstabHandling::mountPoints(m_device);
|
||||
const QString home = QDir::homePath();
|
||||
if (mountPoints.contains(QLatin1String("/"))) {
|
||||
m_iconName = QStringLiteral("drive-harddisk-root");
|
||||
} else if (mountPoints.contains(home)) {
|
||||
m_iconName = QStringLiteral("user-home");
|
||||
} else {
|
||||
m_iconName = QStringLiteral("folder");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FstabDevice::~FstabDevice()
|
||||
{
|
||||
}
|
||||
|
||||
QString FstabDevice::udi() const
|
||||
{
|
||||
return m_uid;
|
||||
}
|
||||
|
||||
QString FstabDevice::parentUdi() const
|
||||
{
|
||||
return QString::fromLatin1(FSTAB_UDI_PREFIX);
|
||||
}
|
||||
|
||||
QString FstabDevice::vendor() const
|
||||
{
|
||||
return m_vendor;
|
||||
}
|
||||
|
||||
QString FstabDevice::product() const
|
||||
{
|
||||
return m_product;
|
||||
}
|
||||
|
||||
QString FstabDevice::icon() const
|
||||
{
|
||||
return m_iconName;
|
||||
}
|
||||
|
||||
QStringList FstabDevice::emblems() const
|
||||
{
|
||||
if (!m_storageAccess) {
|
||||
FstabDevice *d = const_cast<FstabDevice *>(this);
|
||||
d->m_storageAccess = new FstabStorageAccess(d);
|
||||
}
|
||||
if (m_storageAccess->isAccessible()) {
|
||||
return {QStringLiteral("emblem-mounted")};
|
||||
} else {
|
||||
return {QStringLiteral("emblem-unmounted")};
|
||||
}
|
||||
}
|
||||
|
||||
QString FstabDevice::displayName() const
|
||||
{
|
||||
return m_displayName;
|
||||
}
|
||||
|
||||
QString FstabDevice::description() const
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
bool FstabDevice::isEncrypted() const
|
||||
{
|
||||
return m_storageType == FstabDevice::StorageType::Encrypted;
|
||||
}
|
||||
|
||||
bool FstabDevice::queryDeviceInterface(const Solid::DeviceInterface::Type &interfaceType) const
|
||||
{
|
||||
if (interfaceType == Solid::DeviceInterface::StorageAccess) {
|
||||
return true;
|
||||
}
|
||||
if ((m_storageType == StorageType::NetworkShare) && (interfaceType == Solid::DeviceInterface::NetworkShare)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QObject *FstabDevice::createDeviceInterface(const Solid::DeviceInterface::Type &interfaceType)
|
||||
{
|
||||
if (interfaceType == Solid::DeviceInterface::StorageAccess) {
|
||||
if (!m_storageAccess) {
|
||||
m_storageAccess = new FstabStorageAccess(this);
|
||||
}
|
||||
return m_storageAccess;
|
||||
} else if ((m_storageType == StorageType::NetworkShare) && (interfaceType == Solid::DeviceInterface::NetworkShare)) {
|
||||
return new FstabNetworkShare(this);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QString FstabDevice::device() const
|
||||
{
|
||||
return m_device;
|
||||
}
|
||||
|
||||
void FstabDevice::onMtabChanged(const QString &device)
|
||||
{
|
||||
if (m_device == device) {
|
||||
Q_EMIT mtabChanged(device);
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_fstabdevice.cpp"
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Mario Bensi <mbensi@ipsquad.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_FSTAB_FSTAB_DEVICE_H
|
||||
#define SOLID_BACKENDS_FSTAB_FSTAB_DEVICE_H
|
||||
|
||||
#include "fstabstorageaccess.h"
|
||||
#include <QPointer>
|
||||
#include <QString>
|
||||
#include <solid/devices/ifaces/device.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fstab
|
||||
{
|
||||
class FstabDevice : public Solid::Ifaces::Device
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FstabDevice(QString uid);
|
||||
|
||||
~FstabDevice() override;
|
||||
|
||||
QString udi() const override;
|
||||
|
||||
QString parentUdi() const override;
|
||||
|
||||
QString vendor() const override;
|
||||
|
||||
QString product() const override;
|
||||
|
||||
QString icon() const override;
|
||||
|
||||
QStringList emblems() const override;
|
||||
|
||||
QString displayName() const override;
|
||||
|
||||
QString description() const override;
|
||||
|
||||
bool isEncrypted() const;
|
||||
|
||||
bool queryDeviceInterface(const Solid::DeviceInterface::Type &type) const override;
|
||||
|
||||
QObject *createDeviceInterface(const Solid::DeviceInterface::Type &type) override;
|
||||
|
||||
QString device() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void mtabChanged(const QString &device);
|
||||
|
||||
public Q_SLOTS:
|
||||
void onMtabChanged(const QString &device);
|
||||
|
||||
private:
|
||||
QString m_uid;
|
||||
QString m_device;
|
||||
QString m_product;
|
||||
QString m_vendor;
|
||||
QString m_displayName;
|
||||
QString m_description;
|
||||
QString m_iconName;
|
||||
QPointer<FstabStorageAccess> m_storageAccess;
|
||||
enum class StorageType : uint8_t {
|
||||
Other = 0,
|
||||
NetworkShare,
|
||||
Encrypted,
|
||||
};
|
||||
StorageType m_storageType = StorageType::Other;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // SOLID_BACKENDS_FSTAB_FSTAB_DEVICE_H
|
||||
+397
@@ -0,0 +1,397 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006-2010 Kevin Ottens <ervin@kde.org>
|
||||
SPDX-FileCopyrightText: 2010 Mario Bensi <mbensi@ipsquad.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "fstabhandling.h"
|
||||
#include "fstab_debug.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QObject>
|
||||
#include <QProcess>
|
||||
#include <QRegularExpression>
|
||||
#include <QStandardPaths>
|
||||
#include <QTextStream>
|
||||
#include <QThreadStorage>
|
||||
|
||||
#include <solid/devices/soliddefs_p.h>
|
||||
|
||||
#include <solid/config-solid.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if HAVE_LIBMOUNT
|
||||
#include <libmount.h>
|
||||
#endif
|
||||
|
||||
// This is the *BSD branch
|
||||
#if HAVE_SYS_MOUNT_H
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#if HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#include <sys/mount.h>
|
||||
#endif
|
||||
|
||||
#define FSTAB "/etc/fstab"
|
||||
|
||||
// There are currently two APIs implemented:
|
||||
// libmount for linux
|
||||
// getmntinfo + struct statfs&flags (BSD 4.4 and friends)
|
||||
|
||||
Q_GLOBAL_STATIC(QThreadStorage<Solid::Backends::Fstab::FstabHandling>, globalFstabCache)
|
||||
|
||||
Solid::Backends::Fstab::FstabHandling::FstabHandling()
|
||||
: m_fstabCacheValid(false)
|
||||
, m_mtabCacheValid(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool _k_isFstabNetworkFileSystem(const QString &fstype, const QString &devName)
|
||||
{
|
||||
if (fstype == QLatin1String("nfs") //
|
||||
|| fstype == QLatin1String("nfs4") //
|
||||
|| fstype == QLatin1String("smbfs") //
|
||||
|| fstype == QLatin1String("cifs") //
|
||||
|| fstype == QLatin1String("smb3") //
|
||||
|| fstype == QLatin1String("fuse.sshfs") //
|
||||
|| fstype == QLatin1String("fuse.rclone") //
|
||||
|| devName.startsWith(QLatin1String("//"))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool _k_isFstabSupportedLocalFileSystem(const QString &fstype)
|
||||
{
|
||||
if (fstype == QLatin1String("fuse.encfs") //
|
||||
|| fstype == QLatin1String("fuse.cryfs") //
|
||||
|| fstype == QLatin1String("fuse.gocryptfs") //
|
||||
|| fstype == QLatin1String("overlay")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QString _k_mntFstype(const QString &orig)
|
||||
{
|
||||
if (orig == QLatin1String("sshfs") || orig == QLatin1String("rclone")) {
|
||||
return QStringLiteral("fuse.%1").arg(orig);
|
||||
}
|
||||
return orig;
|
||||
}
|
||||
|
||||
QString _k_deviceNameForMountpoint(const QString &source, const QString &fstype, const QString &mountpoint)
|
||||
{
|
||||
if (fstype.startsWith(QLatin1String("fuse.")) || fstype == QLatin1String("overlay")) {
|
||||
return fstype + mountpoint;
|
||||
}
|
||||
// A source may be mounted several times, e.g. with different
|
||||
// options, often a network share with different credentials
|
||||
// for different users. Make sure it is unique by appending the
|
||||
// mountpoint (which is unique).
|
||||
|
||||
auto _mountpoint = mountpoint;
|
||||
if (fstype == QLatin1String("nfs") || fstype == QLatin1String("nfs4")) {
|
||||
if (!mountpoint.startsWith(QLatin1Char('/'))) {
|
||||
// making sure mount point starts with /
|
||||
_mountpoint.prepend(QLatin1Char('/'));
|
||||
}
|
||||
}
|
||||
return source + QLatin1Char(':') + _mountpoint;
|
||||
}
|
||||
|
||||
void Solid::Backends::Fstab::FstabHandling::_k_updateFstabMountPointsCache()
|
||||
{
|
||||
if (globalFstabCache->localData().m_fstabCacheValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
globalFstabCache->localData().m_fstabCache.clear();
|
||||
globalFstabCache->localData().m_fstabOptionsCache.clear();
|
||||
|
||||
#if HAVE_LIBMOUNT
|
||||
|
||||
struct libmnt_table *table = mnt_new_table();
|
||||
if (!table) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mnt_table_parse_fstab(table, NULL) != 0) {
|
||||
mnt_free_table(table);
|
||||
return;
|
||||
}
|
||||
|
||||
struct libmnt_iter *itr = mnt_new_iter(MNT_ITER_FORWARD);
|
||||
struct libmnt_fs *fs;
|
||||
|
||||
while (mnt_table_next_fs(table, itr, &fs) == 0) {
|
||||
const QString fstype = _k_mntFstype(QFile::decodeName(mnt_fs_get_fstype(fs)));
|
||||
const QString fsname = QFile::decodeName(mnt_fs_get_srcpath(fs));
|
||||
if (_k_isFstabNetworkFileSystem(fstype, fsname) || _k_isFstabSupportedLocalFileSystem(fstype)) {
|
||||
const QString mountpoint = QFile::decodeName(mnt_fs_get_target(fs));
|
||||
const QString device = _k_deviceNameForMountpoint(fsname, fstype, mountpoint);
|
||||
char *name = mnt_fs_strdup_options(fs);
|
||||
const QStringList options = QFile::decodeName(name).split(QLatin1Char(','));
|
||||
free(name);
|
||||
|
||||
globalFstabCache->localData().m_fstabCache.insert(device, mountpoint);
|
||||
globalFstabCache->localData().m_fstabFstypeCache.insert(device, fstype);
|
||||
for (const auto &optionLine : options) {
|
||||
const auto split = optionLine.split(QLatin1Char('='));
|
||||
const auto optionName = split[0];
|
||||
const auto optionValue = split.size() > 1 ? split[1] : QString{};
|
||||
|
||||
globalFstabCache->localData().m_fstabOptionsCache[device].insert(optionName, optionValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mnt_free_iter(itr);
|
||||
|
||||
mnt_free_table(table);
|
||||
|
||||
#else
|
||||
|
||||
QFile fstab(QStringLiteral(FSTAB));
|
||||
if (!fstab.open(QIODevice::ReadOnly)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QTextStream stream(&fstab);
|
||||
QString line;
|
||||
|
||||
while (!stream.atEnd()) {
|
||||
line = stream.readLine().simplified();
|
||||
if (line.isEmpty() || line.startsWith(QLatin1Char('#'))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// not empty or commented out by '#'
|
||||
const QStringList items = line.split(QLatin1Char(' '));
|
||||
if (items.count() < 4) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const QString device = items.at(0);
|
||||
const QString fstype = _k_mntFstype(items.at(2));
|
||||
|
||||
// prevent accessing a blocking directory
|
||||
if (_k_isFstabNetworkFileSystem(fstype, device) || _k_isFstabSupportedLocalFileSystem(fstype)) {
|
||||
QString mountpoint = items.at(1);
|
||||
|
||||
if (fstype == QLatin1String("nfs") || fstype == QLatin1String("nfs4")) {
|
||||
if (!mountpoint.startsWith(QLatin1Char('/'))) {
|
||||
// making sure mount point starts with /
|
||||
mountpoint.prepend(QLatin1Char('/'));
|
||||
}
|
||||
}
|
||||
|
||||
globalFstabCache->localData().m_fstabCache.insert(device, mountpoint);
|
||||
}
|
||||
}
|
||||
|
||||
fstab.close();
|
||||
#endif
|
||||
globalFstabCache->localData().m_fstabCacheValid = true;
|
||||
}
|
||||
|
||||
QStringList Solid::Backends::Fstab::FstabHandling::deviceList()
|
||||
{
|
||||
_k_updateFstabMountPointsCache();
|
||||
_k_updateMtabMountPointsCache();
|
||||
|
||||
QStringList devices = globalFstabCache->localData().m_mtabCache.keys();
|
||||
|
||||
// Ensure that regardless an fstab device ends with a slash
|
||||
// it will match its eventual mounted device regardless whether or not its path
|
||||
// ends with a slash
|
||||
for (auto it = globalFstabCache->localData().m_fstabCache.constBegin(), end = globalFstabCache->localData().m_fstabCache.constEnd(); it != end; ++it) {
|
||||
auto device = it.key();
|
||||
// the device is already known
|
||||
if (devices.contains(device)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// deviceName will or won't end with / depending if device ended with one
|
||||
QString deviceName = device;
|
||||
if (deviceName.endsWith(QLatin1Char('/'))) {
|
||||
deviceName.chop(1);
|
||||
} else {
|
||||
deviceName.append(QLatin1Char('/'));
|
||||
}
|
||||
if (!devices.contains(deviceName)) {
|
||||
devices.append(device);
|
||||
}
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
|
||||
QStringList Solid::Backends::Fstab::FstabHandling::mountPoints(const QString &device)
|
||||
{
|
||||
_k_updateFstabMountPointsCache();
|
||||
_k_updateMtabMountPointsCache();
|
||||
|
||||
QStringList mountpoints = globalFstabCache->localData().m_fstabCache.values(device);
|
||||
mountpoints += globalFstabCache->localData().m_mtabCache.values(device);
|
||||
mountpoints.removeDuplicates();
|
||||
return mountpoints;
|
||||
}
|
||||
|
||||
QHash<QString, QString> Solid::Backends::Fstab::FstabHandling::options(const QString &device)
|
||||
{
|
||||
_k_updateFstabMountPointsCache();
|
||||
_k_updateMtabMountPointsCache();
|
||||
|
||||
auto options = globalFstabCache->localData().m_mtabOptionsCache.value(device);
|
||||
|
||||
const auto optionsFstab = globalFstabCache->localData().m_fstabOptionsCache.value(device);
|
||||
for (const auto &it : optionsFstab.asKeyValueRange()) {
|
||||
if (!options.contains(it.first)) {
|
||||
options.insert(it.first, it.second);
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
QString Solid::Backends::Fstab::FstabHandling::fstype(const QString &device)
|
||||
{
|
||||
_k_updateFstabMountPointsCache();
|
||||
|
||||
return globalFstabCache->localData().m_fstabFstypeCache.value(device);
|
||||
}
|
||||
|
||||
bool Solid::Backends::Fstab::FstabHandling::callSystemCommand(const QString &commandName,
|
||||
const QStringList &args,
|
||||
const QObject *receiver,
|
||||
std::function<void(QProcess *)> callback)
|
||||
{
|
||||
static const QStringList searchPaths{QStringLiteral("/sbin"), QStringLiteral("/bin"), QStringLiteral("/usr/sbin"), QStringLiteral("/usr/bin")};
|
||||
static const QString joinedPaths = searchPaths.join(QLatin1Char(':'));
|
||||
const QString exec = QStandardPaths::findExecutable(commandName, searchPaths);
|
||||
if (exec.isEmpty()) {
|
||||
qCWarning(FSTAB_LOG) << "Couldn't find executable" << commandName << "in" << joinedPaths;
|
||||
return false;
|
||||
}
|
||||
|
||||
QProcess *process = new QProcess();
|
||||
|
||||
QObject::connect(process,
|
||||
static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
|
||||
receiver,
|
||||
[process, callback](int exitCode, QProcess::ExitStatus exitStatus) {
|
||||
Q_UNUSED(exitCode);
|
||||
Q_UNUSED(exitStatus);
|
||||
callback(process);
|
||||
process->deleteLater();
|
||||
});
|
||||
|
||||
static const QRegularExpression re(QStringLiteral("^PATH=.*"), QRegularExpression::CaseInsensitiveOption);
|
||||
QStringList env = QProcess::systemEnvironment();
|
||||
env.replaceInStrings(re, QLatin1String("PATH=") + joinedPaths);
|
||||
process->setEnvironment(env);
|
||||
process->start(exec, args);
|
||||
|
||||
if (process->waitForStarted()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
delete process;
|
||||
return false;
|
||||
}
|
||||
|
||||
void Solid::Backends::Fstab::FstabHandling::_k_updateMtabMountPointsCache()
|
||||
{
|
||||
if (globalFstabCache->localData().m_mtabCacheValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
globalFstabCache->localData().m_mtabCache.clear();
|
||||
globalFstabCache->localData().m_mtabOptionsCache.clear();
|
||||
|
||||
#if HAVE_GETMNTINFO
|
||||
|
||||
#if GETMNTINFO_USES_STATVFS
|
||||
struct statvfs *mounted;
|
||||
#else
|
||||
struct statfs *mounted;
|
||||
#endif
|
||||
|
||||
int num_fs = getmntinfo(&mounted, MNT_NOWAIT);
|
||||
|
||||
for (int i = 0; i < num_fs; i++) {
|
||||
QString type = _k_mntFstype(QFile::decodeName(mounted[i].f_fstypename));
|
||||
if (_k_isFstabNetworkFileSystem(type, QString()) || _k_isFstabSupportedLocalFileSystem(type)) {
|
||||
const QString fsname = QFile::decodeName(mounted[i].f_mntfromname);
|
||||
const QString mountpoint = QFile::decodeName(mounted[i].f_mntonname);
|
||||
const QString device = _k_deviceNameForMountpoint(fsname, type, mountpoint);
|
||||
globalFstabCache->localData().m_mtabCache.insert(device, mountpoint);
|
||||
globalFstabCache->localData().m_fstabFstypeCache.insert(device, type);
|
||||
}
|
||||
}
|
||||
|
||||
#elif HAVE_LIBMOUNT
|
||||
|
||||
struct libmnt_table *table = mnt_new_table();
|
||||
if (!table) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mnt_table_parse_mtab(table, NULL) != 0) {
|
||||
mnt_free_table(table);
|
||||
return;
|
||||
}
|
||||
|
||||
struct libmnt_iter *itr = mnt_new_iter(MNT_ITER_FORWARD);
|
||||
struct libmnt_fs *fs;
|
||||
|
||||
while (mnt_table_next_fs(table, itr, &fs) == 0) {
|
||||
const QString fstype = _k_mntFstype(QFile::decodeName(mnt_fs_get_fstype(fs)));
|
||||
if (_k_isFstabNetworkFileSystem(fstype, QString{}) || _k_isFstabSupportedLocalFileSystem(fstype)) {
|
||||
const QString mountpoint = QFile::decodeName(mnt_fs_get_target(fs));
|
||||
const QString fsname = QFile::decodeName(mnt_fs_get_srcpath(fs));
|
||||
const QString device = _k_deviceNameForMountpoint(fsname, fstype, mountpoint);
|
||||
char *name = mnt_fs_strdup_options(fs);
|
||||
const QStringList options = QFile::decodeName(name).split(QLatin1Char(','));
|
||||
free(name);
|
||||
|
||||
globalFstabCache->localData().m_mtabCache.insert(device, mountpoint);
|
||||
globalFstabCache->localData().m_fstabFstypeCache.insert(device, fstype);
|
||||
for (const auto &optionLine : options) {
|
||||
const auto split = optionLine.split(QLatin1Char('='));
|
||||
const auto optionName = split[0];
|
||||
const auto optionValue = split.size() > 1 ? split[1] : QString{};
|
||||
|
||||
globalFstabCache->localData().m_mtabOptionsCache[device].insert(optionName, optionValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mnt_free_iter(itr);
|
||||
|
||||
mnt_free_table(table);
|
||||
|
||||
#endif
|
||||
|
||||
globalFstabCache->localData().m_mtabCacheValid = true;
|
||||
}
|
||||
|
||||
QStringList Solid::Backends::Fstab::FstabHandling::currentMountPoints(const QString &device)
|
||||
{
|
||||
_k_updateMtabMountPointsCache();
|
||||
return globalFstabCache->localData().m_mtabCache.values(device);
|
||||
}
|
||||
|
||||
void Solid::Backends::Fstab::FstabHandling::flushMtabCache()
|
||||
{
|
||||
globalFstabCache->localData().m_mtabCacheValid = false;
|
||||
}
|
||||
|
||||
void Solid::Backends::Fstab::FstabHandling::flushFstabCache()
|
||||
{
|
||||
globalFstabCache->localData().m_fstabCacheValid = false;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006-2010 Kevin Ottens <ervin@kde.org>
|
||||
SPDX-FileCopyrightText: 2010 Mario Bensi <mbensi@ipsquad.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_FSTAB_FSTABHANDLING_H
|
||||
#define SOLID_BACKENDS_FSTAB_FSTABHANDLING_H
|
||||
|
||||
#include <QMultiHash>
|
||||
#include <QString>
|
||||
|
||||
#include <functional>
|
||||
|
||||
class QProcess;
|
||||
class QObject;
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fstab
|
||||
{
|
||||
class FstabHandling
|
||||
{
|
||||
public:
|
||||
FstabHandling();
|
||||
|
||||
static QStringList deviceList();
|
||||
static QStringList currentMountPoints(const QString &device);
|
||||
static QStringList mountPoints(const QString &device);
|
||||
static QHash<QString, QString> options(const QString &device);
|
||||
static QString fstype(const QString &device);
|
||||
static bool callSystemCommand(const QString &commandName, const QStringList &args, const QObject *recvr, std::function<void(QProcess *)> callback);
|
||||
static void flushMtabCache();
|
||||
static void flushFstabCache();
|
||||
|
||||
private:
|
||||
static void _k_updateMtabMountPointsCache();
|
||||
static void _k_updateFstabMountPointsCache();
|
||||
|
||||
typedef QMultiHash<QString, QString> QStringMultiHash;
|
||||
|
||||
QStringMultiHash m_mtabCache;
|
||||
QStringMultiHash m_fstabCache;
|
||||
QHash<QString, QHash<QString, QString>> m_fstabOptionsCache;
|
||||
QHash<QString, QHash<QString, QString>> m_mtabOptionsCache;
|
||||
QHash<QString, QString> m_fstabFstypeCache;
|
||||
bool m_fstabCacheValid;
|
||||
bool m_mtabCacheValid;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Mario Bensi <mbensi@ipsquad.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "fstabmanager.h"
|
||||
#include "../shared/rootdevice.h"
|
||||
#include "fstab_debug.h"
|
||||
#include "fstabdevice.h"
|
||||
#include "fstabhandling.h"
|
||||
#include "fstabservice.h"
|
||||
#include "fstabwatcher.h"
|
||||
|
||||
using namespace Solid::Backends::Fstab;
|
||||
using namespace Solid::Backends::Shared;
|
||||
|
||||
FstabManager::FstabManager(QObject *parent)
|
||||
: Solid::Ifaces::DeviceManager(parent)
|
||||
, m_deviceList(FstabHandling::deviceList())
|
||||
{
|
||||
m_supportedInterfaces << Solid::DeviceInterface::StorageAccess;
|
||||
m_supportedInterfaces << Solid::DeviceInterface::NetworkShare;
|
||||
|
||||
connect(FstabWatcher::instance(), &FstabWatcher::fstabChanged, this, &FstabManager::onFstabChanged);
|
||||
connect(FstabWatcher::instance(), &FstabWatcher::mtabChanged, this, &FstabManager::onMtabChanged);
|
||||
}
|
||||
|
||||
QString FstabManager::udiPrefix() const
|
||||
{
|
||||
return QStringLiteral(FSTAB_UDI_PREFIX);
|
||||
}
|
||||
|
||||
QSet<Solid::DeviceInterface::Type> FstabManager::supportedInterfaces() const
|
||||
{
|
||||
return m_supportedInterfaces;
|
||||
}
|
||||
|
||||
QStringList FstabManager::allDevices()
|
||||
{
|
||||
QStringList result;
|
||||
|
||||
result << udiPrefix();
|
||||
for (const QString &device : std::as_const(m_deviceList)) {
|
||||
result << udiPrefix() + QStringLiteral("/") + device;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QStringList FstabManager::devicesFromQuery(const QString &parentUdi, Solid::DeviceInterface::Type type)
|
||||
{
|
||||
if ((parentUdi == udiPrefix()) || parentUdi.isEmpty()) {
|
||||
QStringList result;
|
||||
if (type == Solid::DeviceInterface::StorageAccess) {
|
||||
for (const QString &device : std::as_const(m_deviceList)) {
|
||||
result << udiPrefix() + QStringLiteral("/") + device;
|
||||
}
|
||||
return result;
|
||||
} else if (type == Solid::DeviceInterface::NetworkShare) {
|
||||
for (const QString &device : std::as_const(m_deviceList)) {
|
||||
result << udiPrefix() + QStringLiteral("/") + device;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
if (type == Solid::DeviceInterface::StorageAccess || type == Solid::DeviceInterface::NetworkShare) {
|
||||
return QStringList{parentUdi};
|
||||
}
|
||||
}
|
||||
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
QObject *FstabManager::createDevice(const QString &udi)
|
||||
{
|
||||
if (udi == udiPrefix()) {
|
||||
RootDevice *root = new RootDevice(udi);
|
||||
|
||||
root->setProduct(tr("Filesystem Volumes"));
|
||||
root->setDescription(tr("Mountable filesystems declared in your system"));
|
||||
root->setIcon(QStringLiteral("folder"));
|
||||
|
||||
return root;
|
||||
|
||||
} else {
|
||||
// global device manager makes sure udi starts with udi prefix + '/'
|
||||
QString internalName = udi.mid(udiPrefix().length() + 1, -1);
|
||||
if (!m_deviceList.contains(internalName)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FstabDevice *device = new FstabDevice(udi);
|
||||
connect(this, &FstabManager::mtabChanged, device, &FstabDevice::onMtabChanged);
|
||||
return device;
|
||||
}
|
||||
}
|
||||
|
||||
void FstabManager::onFstabChanged()
|
||||
{
|
||||
FstabHandling::flushFstabCache();
|
||||
_k_updateDeviceList();
|
||||
}
|
||||
|
||||
void FstabManager::_k_updateDeviceList()
|
||||
{
|
||||
const QStringList deviceList = FstabHandling::deviceList();
|
||||
const QSet<QString> newlist(deviceList.begin(), deviceList.end());
|
||||
const QSet<QString> oldlist(m_deviceList.begin(), m_deviceList.end());
|
||||
|
||||
m_deviceList = deviceList;
|
||||
|
||||
qCDebug(FSTAB_LOG) << oldlist << "->" << newlist;
|
||||
|
||||
for (const QString &device : newlist) {
|
||||
if (!oldlist.contains(device)) {
|
||||
Q_EMIT deviceAdded(udiPrefix() + QStringLiteral("/") + device);
|
||||
}
|
||||
}
|
||||
|
||||
for (const QString &device : oldlist) {
|
||||
if (!newlist.contains(device)) {
|
||||
Q_EMIT deviceRemoved(udiPrefix() + QStringLiteral("/") + device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FstabManager::onMtabChanged()
|
||||
{
|
||||
FstabHandling::flushMtabCache();
|
||||
|
||||
_k_updateDeviceList(); // devicelist is union of mtab and fstab
|
||||
|
||||
for (const QString &device : std::as_const(m_deviceList)) {
|
||||
// notify storageaccess objects via device ...
|
||||
Q_EMIT mtabChanged(device);
|
||||
}
|
||||
}
|
||||
|
||||
FstabManager::~FstabManager()
|
||||
{
|
||||
}
|
||||
|
||||
#include "moc_fstabmanager.cpp"
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Mario Bensi <mbensi@ipsquad.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_FSTAB_FSTABMANAGER_H
|
||||
#define SOLID_BACKENDS_FSTAB_FSTABMANAGER_H
|
||||
|
||||
#include <QSet>
|
||||
#include <QStringList>
|
||||
#include <solid/deviceinterface.h>
|
||||
#include <solid/devices/ifaces/devicemanager.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fstab
|
||||
{
|
||||
class AbstractDeviceFactory;
|
||||
|
||||
class FstabManager : public Solid::Ifaces::DeviceManager
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FstabManager(QObject *parent);
|
||||
~FstabManager() override;
|
||||
|
||||
QString udiPrefix() const override;
|
||||
QSet<Solid::DeviceInterface::Type> supportedInterfaces() const override;
|
||||
QStringList allDevices() override;
|
||||
QStringList devicesFromQuery(const QString &parentUdi, Solid::DeviceInterface::Type type) override;
|
||||
QObject *createDevice(const QString &udi) override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void mtabChanged(const QString &device);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onFstabChanged();
|
||||
void onMtabChanged();
|
||||
|
||||
private:
|
||||
QSet<Solid::DeviceInterface::Type> m_supportedInterfaces;
|
||||
QStringList m_deviceList;
|
||||
void _k_updateDeviceList();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2011 Mario Bensi <mbensi@ipsquad.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "fstabnetworkshare.h"
|
||||
#include "fstabhandling.h"
|
||||
#include <solid/devices/backends/fstab/fstabdevice.h>
|
||||
|
||||
using namespace Solid::Backends::Fstab;
|
||||
|
||||
FstabNetworkShare::FstabNetworkShare(Solid::Backends::Fstab::FstabDevice *device)
|
||||
: QObject(device)
|
||||
, m_fstabDevice(device)
|
||||
{
|
||||
QString url;
|
||||
if (m_fstabDevice->device().startsWith(QLatin1String("//"))) {
|
||||
QString fsType = FstabHandling::fstype(m_fstabDevice->device());
|
||||
if (fsType == QLatin1String("cifs")) {
|
||||
m_type = Solid::NetworkShare::Cifs;
|
||||
} else if (fsType == QLatin1String("smb3")) {
|
||||
m_type = Solid::NetworkShare::Smb3;
|
||||
}
|
||||
url = QStringLiteral("smb:%1").arg(m_fstabDevice->device());
|
||||
} else if (m_fstabDevice->device().contains(QLatin1String(":/"))) {
|
||||
m_type = Solid::NetworkShare::Nfs;
|
||||
url = QStringLiteral("nfs://%1/%2").arg(m_fstabDevice->vendor(), m_fstabDevice->product());
|
||||
} else {
|
||||
m_type = Solid::NetworkShare::Unknown;
|
||||
}
|
||||
m_url = QUrl(url);
|
||||
}
|
||||
|
||||
FstabNetworkShare::~FstabNetworkShare()
|
||||
{
|
||||
}
|
||||
|
||||
Solid::NetworkShare::ShareType FstabNetworkShare::type() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
QUrl FstabNetworkShare::url() const
|
||||
{
|
||||
return m_url;
|
||||
}
|
||||
|
||||
const Solid::Backends::Fstab::FstabDevice *FstabNetworkShare::fstabDevice() const
|
||||
{
|
||||
return m_fstabDevice;
|
||||
}
|
||||
|
||||
#include "moc_fstabnetworkshare.cpp"
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2011 Mario Bensi <mbensi@ipsquad.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_FSTAB_NETWORKSHARE_H
|
||||
#define SOLID_BACKENDS_FSTAB_NETWORKSHARE_H
|
||||
|
||||
#include <solid/devices/ifaces/networkshare.h>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fstab
|
||||
{
|
||||
class FstabDevice;
|
||||
class FstabNetworkShare : public QObject, public Solid::Ifaces::NetworkShare
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::NetworkShare)
|
||||
|
||||
public:
|
||||
explicit FstabNetworkShare(Solid::Backends::Fstab::FstabDevice *device);
|
||||
|
||||
~FstabNetworkShare() override;
|
||||
|
||||
Solid::NetworkShare::ShareType type() const override;
|
||||
|
||||
QUrl url() const override;
|
||||
|
||||
public:
|
||||
const Solid::Backends::Fstab::FstabDevice *fstabDevice() const;
|
||||
|
||||
private:
|
||||
Solid::Backends::Fstab::FstabDevice *m_fstabDevice;
|
||||
Solid::NetworkShare::ShareType m_type;
|
||||
QUrl m_url;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_FSTAB_NETWORKSHARE_H
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Mario Bensi <mbensi@ipsquad.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_FSTAB_SERVICE_H
|
||||
#define SOLID_BACKENDS_FSTAB_SERVICE_H
|
||||
|
||||
/* FStab */
|
||||
#define FSTAB_UDI_PREFIX "/org/kde/fstab"
|
||||
|
||||
#endif // SOLID_BACKENDS_FSTAB_H
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Mario Bensi <mbensi@ipsquad.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "fstabstorageaccess.h"
|
||||
#include "fstabwatcher.h"
|
||||
#include <QStringList>
|
||||
#include <solid/devices/backends/fstab/fstabdevice.h>
|
||||
#include <solid/devices/backends/fstab/fstabhandling.h>
|
||||
#include <solid/devices/backends/fstab/fstabservice.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QProcess>
|
||||
#include <QTimer>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
using namespace Solid::Backends::Fstab;
|
||||
|
||||
FstabStorageAccess::FstabStorageAccess(Solid::Backends::Fstab::FstabDevice *device)
|
||||
: QObject(device)
|
||||
, m_fstabDevice(device)
|
||||
{
|
||||
QStringList currentMountPoints = FstabHandling::currentMountPoints(device->device());
|
||||
if (currentMountPoints.isEmpty()) {
|
||||
QStringList mountPoints = FstabHandling::mountPoints(device->device());
|
||||
m_filePath = mountPoints.isEmpty() ? QString() : mountPoints.first();
|
||||
m_isAccessible = false;
|
||||
} else {
|
||||
m_filePath = currentMountPoints.first();
|
||||
m_isAccessible = true;
|
||||
}
|
||||
|
||||
const bool inUserPath =
|
||||
m_filePath.startsWith(QLatin1String("/media/")) || m_filePath.startsWith(QLatin1String("/run/media/")) || m_filePath.startsWith(QDir::homePath());
|
||||
|
||||
const bool gvfsHidden = FstabHandling::options(device->device()).contains(QLatin1String("x-gvfs-hide"));
|
||||
const bool fsIsOverlay = FstabHandling::fstype(device->device()) == QLatin1String("overlay");
|
||||
|
||||
m_isIgnored = gvfsHidden ||
|
||||
// ignore overlay fs not pointing to / or seemingly mounted by user
|
||||
(fsIsOverlay && m_filePath != QLatin1String("/") && !inUserPath);
|
||||
|
||||
connect(device, &FstabDevice::mtabChanged, this, &FstabStorageAccess::onMtabChanged);
|
||||
QTimer::singleShot(0, this, SLOT(connectDBusSignals()));
|
||||
}
|
||||
|
||||
FstabStorageAccess::~FstabStorageAccess()
|
||||
{
|
||||
}
|
||||
|
||||
void FstabStorageAccess::connectDBusSignals()
|
||||
{
|
||||
m_fstabDevice->registerAction(QStringLiteral("setup"), this, SLOT(slotSetupRequested()), SLOT(slotSetupDone(int, QString)));
|
||||
|
||||
m_fstabDevice->registerAction(QStringLiteral("teardown"), this, SLOT(slotTeardownRequested()), SLOT(slotTeardownDone(int, QString)));
|
||||
}
|
||||
|
||||
const Solid::Backends::Fstab::FstabDevice *FstabStorageAccess::fstabDevice() const
|
||||
{
|
||||
return m_fstabDevice;
|
||||
}
|
||||
|
||||
bool FstabStorageAccess::isAccessible() const
|
||||
{
|
||||
return m_isAccessible;
|
||||
}
|
||||
|
||||
QString FstabStorageAccess::filePath() const
|
||||
{
|
||||
return m_filePath;
|
||||
}
|
||||
|
||||
bool FstabStorageAccess::isIgnored() const
|
||||
{
|
||||
return m_isIgnored;
|
||||
}
|
||||
|
||||
bool FstabStorageAccess::isEncrypted() const
|
||||
{
|
||||
return m_fstabDevice->isEncrypted();
|
||||
}
|
||||
|
||||
bool FstabStorageAccess::setup()
|
||||
{
|
||||
if (filePath().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
m_fstabDevice->broadcastActionRequested(QStringLiteral("setup"));
|
||||
return FstabHandling::callSystemCommand(QStringLiteral("mount"), {filePath()}, this, [this](QProcess *process) {
|
||||
if (process->exitCode() == 0) {
|
||||
m_fstabDevice->broadcastActionDone(QStringLiteral("setup"), Solid::NoError, QString());
|
||||
} else {
|
||||
m_fstabDevice->broadcastActionDone(QStringLiteral("setup"),
|
||||
Solid::UnauthorizedOperation,
|
||||
QString::fromUtf8(process->readAllStandardError().trimmed()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void FstabStorageAccess::slotSetupRequested()
|
||||
{
|
||||
Q_EMIT setupRequested(m_fstabDevice->udi());
|
||||
}
|
||||
|
||||
bool FstabStorageAccess::teardown()
|
||||
{
|
||||
if (filePath().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
m_fstabDevice->broadcastActionRequested(QStringLiteral("teardown"));
|
||||
return FstabHandling::callSystemCommand(QStringLiteral("umount"), {filePath()}, this, [this](QProcess *process) {
|
||||
if (process->exitCode() == 0) {
|
||||
m_fstabDevice->broadcastActionDone(QStringLiteral("teardown"), Solid::NoError);
|
||||
} else if (process->exitCode() == EBUSY) {
|
||||
m_fstabDevice->broadcastActionDone(QStringLiteral("teardown"), Solid::DeviceBusy);
|
||||
} else if (process->exitCode() == EPERM) {
|
||||
m_fstabDevice->broadcastActionDone(QStringLiteral("teardown"),
|
||||
Solid::UnauthorizedOperation,
|
||||
QString::fromUtf8(process->readAllStandardError().trimmed()));
|
||||
} else {
|
||||
m_fstabDevice->broadcastActionDone(QStringLiteral("teardown"),
|
||||
Solid::OperationFailed,
|
||||
QString::fromUtf8(process->readAllStandardError().trimmed()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void FstabStorageAccess::slotTeardownRequested()
|
||||
{
|
||||
Q_EMIT teardownRequested(m_fstabDevice->udi());
|
||||
}
|
||||
|
||||
void FstabStorageAccess::slotSetupDone(int error, const QString &errorString)
|
||||
{
|
||||
Q_EMIT setupDone(static_cast<Solid::ErrorType>(error), errorString, m_fstabDevice->udi());
|
||||
}
|
||||
|
||||
void FstabStorageAccess::slotTeardownDone(int error, const QString &errorString)
|
||||
{
|
||||
Q_EMIT teardownDone(static_cast<Solid::ErrorType>(error), errorString, m_fstabDevice->udi());
|
||||
}
|
||||
|
||||
void FstabStorageAccess::onMtabChanged(const QString &device)
|
||||
{
|
||||
QStringList currentMountPoints = FstabHandling::currentMountPoints(device);
|
||||
if (currentMountPoints.isEmpty()) {
|
||||
// device umounted
|
||||
m_filePath = FstabHandling::mountPoints(device).first();
|
||||
if (m_isAccessible) {
|
||||
m_isAccessible = false;
|
||||
Q_EMIT accessibilityChanged(false, QStringLiteral(FSTAB_UDI_PREFIX "/%1").arg(device));
|
||||
}
|
||||
} else {
|
||||
// device added
|
||||
m_filePath = currentMountPoints.first();
|
||||
if (!m_isAccessible) {
|
||||
m_isAccessible = true;
|
||||
Q_EMIT accessibilityChanged(true, QStringLiteral(FSTAB_UDI_PREFIX "/%1").arg(device));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_fstabstorageaccess.cpp"
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Mario Bensi <mbensi@ipsquad.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_FSTAB_STORAGEACCESS_H
|
||||
#define SOLID_BACKENDS_FSTAB_STORAGEACCESS_H
|
||||
|
||||
#include <solid/devices/ifaces/storageaccess.h>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fstab
|
||||
{
|
||||
class FstabDevice;
|
||||
class FstabStorageAccess : public QObject, public Solid::Ifaces::StorageAccess
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::StorageAccess)
|
||||
|
||||
public:
|
||||
explicit FstabStorageAccess(Solid::Backends::Fstab::FstabDevice *device);
|
||||
|
||||
~FstabStorageAccess() override;
|
||||
|
||||
bool isAccessible() const override;
|
||||
|
||||
QString filePath() const override;
|
||||
|
||||
bool isIgnored() const override;
|
||||
|
||||
bool isEncrypted() const override;
|
||||
|
||||
bool setup() override;
|
||||
|
||||
bool teardown() override;
|
||||
|
||||
public:
|
||||
const Solid::Backends::Fstab::FstabDevice *fstabDevice() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void accessibilityChanged(bool accessible, const QString &udi) override;
|
||||
|
||||
void setupDone(Solid::ErrorType error, QVariant data, const QString &udi) override;
|
||||
|
||||
void teardownDone(Solid::ErrorType error, QVariant data, const QString &udi) override;
|
||||
|
||||
void setupRequested(const QString &udi) override;
|
||||
|
||||
void teardownRequested(const QString &udi) override;
|
||||
|
||||
void repairRequested(const QString &udi) override;
|
||||
|
||||
void repairDone(Solid::ErrorType error, QVariant resultData, const QString &udi) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void onMtabChanged(const QString &device);
|
||||
void connectDBusSignals();
|
||||
|
||||
void slotSetupRequested();
|
||||
void slotSetupDone(int error, const QString &errorString);
|
||||
void slotTeardownRequested();
|
||||
void slotTeardownDone(int error, const QString &errorString);
|
||||
|
||||
private:
|
||||
Solid::Backends::Fstab::FstabDevice *m_fstabDevice;
|
||||
QString m_filePath;
|
||||
bool m_isAccessible;
|
||||
bool m_isIgnored;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_FSTAB_DEVICE_INTERFACE_H
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Mario Bensi <mbensi@ipsquad.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "fstabwatcher.h"
|
||||
#include "fstab_debug.h"
|
||||
#include "soliddefs_p.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QFile>
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QSocketNotifier>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fstab
|
||||
{
|
||||
Q_GLOBAL_STATIC(FstabWatcher, globalFstabWatcher)
|
||||
|
||||
static const QString s_mtabFile = QStringLiteral("/etc/mtab");
|
||||
static const QString s_fstabFile = QStringLiteral("/etc/fstab");
|
||||
static const QString s_fstabPath = QStringLiteral("/etc");
|
||||
|
||||
FstabWatcher::FstabWatcher()
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
auto mountMonitor = mnt_new_monitor();
|
||||
|
||||
if (!mountMonitor) {
|
||||
qCritical(FSTAB_LOG) << "could not start mount monitor";
|
||||
return;
|
||||
}
|
||||
m_mountMonitor = mountMonitor;
|
||||
|
||||
auto r = mnt_monitor_enable_kernel(m_mountMonitor, true);
|
||||
if (r < 0) {
|
||||
mnt_unref_monitor(m_mountMonitor);
|
||||
qCritical(FSTAB_LOG) << "Failed to enable watching of kernel mount events:" << strerror(errno);
|
||||
}
|
||||
|
||||
r = mnt_monitor_enable_userspace(m_mountMonitor, true, NULL);
|
||||
if (r < 0) {
|
||||
mnt_unref_monitor(m_mountMonitor);
|
||||
qCritical(FSTAB_LOG) << "Failed to enable watching of userspace mount events:" << strerror(errno);
|
||||
}
|
||||
|
||||
auto fd = mnt_monitor_get_fd(m_mountMonitor);
|
||||
if (fd < 0) {
|
||||
mnt_unref_monitor(m_mountMonitor);
|
||||
qCritical(FSTAB_LOG) << "Failed to acquire watch file descriptor" << strerror(errno);
|
||||
return;
|
||||
}
|
||||
|
||||
m_socketNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
|
||||
connect(m_socketNotifier, &QSocketNotifier::activated, this, &FstabWatcher::onMountChanged);
|
||||
|
||||
if (qApp) {
|
||||
connect(qApp, &QCoreApplication::aboutToQuit, this, &FstabWatcher::onQuit);
|
||||
}
|
||||
#else
|
||||
m_isRoutineInstalled = false;
|
||||
m_fileSystemWatcher = new QFileSystemWatcher(this);
|
||||
|
||||
m_mtabFile = new QFile(s_mtabFile, this);
|
||||
if (m_mtabFile && m_mtabFile->symLinkTarget().startsWith(QLatin1String("/proc/")) && m_mtabFile->open(QIODevice::ReadOnly)) {
|
||||
m_socketNotifier = new QSocketNotifier(m_mtabFile->handle(), QSocketNotifier::Exception, this);
|
||||
connect(m_socketNotifier, &QSocketNotifier::activated, this, &FstabWatcher::mtabChanged);
|
||||
} else {
|
||||
m_fileSystemWatcher->addPath(s_mtabFile);
|
||||
}
|
||||
|
||||
m_fileSystemWatcher->addPath(s_fstabPath);
|
||||
connect(m_fileSystemWatcher, &QFileSystemWatcher::directoryChanged, this, [this](const QString &) {
|
||||
if (!m_isFstabWatched) {
|
||||
m_isFstabWatched = m_fileSystemWatcher->addPath(s_fstabFile);
|
||||
if (m_isFstabWatched) {
|
||||
qCDebug(FSTAB_LOG) << "Re-added" << s_fstabFile;
|
||||
Q_EMIT onFileChanged(s_fstabFile);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
m_isFstabWatched = m_fileSystemWatcher->addPath(s_fstabFile);
|
||||
connect(m_fileSystemWatcher, &QFileSystemWatcher::fileChanged, this, &FstabWatcher::onFileChanged);
|
||||
#endif
|
||||
}
|
||||
|
||||
FstabWatcher::~FstabWatcher()
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
mnt_unref_monitor(m_mountMonitor);
|
||||
#else
|
||||
// The QFileSystemWatcher doesn't work correctly in a singleton
|
||||
// The solution so far was to destroy the QFileSystemWatcher when the application quits
|
||||
// But we have some crash with this solution.
|
||||
// For the moment to workaround the problem, we detach the QFileSystemWatcher from the parent
|
||||
// effectively leaking it on purpose.
|
||||
m_fileSystemWatcher->setParent(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FstabWatcher::onQuit()
|
||||
{
|
||||
#ifndef Q_OS_LINUX
|
||||
m_fileSystemWatcher->setParent(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
FstabWatcher *FstabWatcher::instance()
|
||||
{
|
||||
#if 0
|
||||
FstabWatcher *fstabWatcher = globalFstabWatcher;
|
||||
|
||||
if (fstabWatcher && !fstabWatcher->m_isRoutineInstalled) {
|
||||
qAddPostRoutine(globalFstabWatcher.destroy);
|
||||
fstabWatcher->m_isRoutineInstalled = true;
|
||||
}
|
||||
return fstabWatcher;
|
||||
#else
|
||||
return globalFstabWatcher;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
void FstabWatcher::onMountChanged()
|
||||
{
|
||||
auto mtab = false;
|
||||
auto fstab = false;
|
||||
const char *filename;
|
||||
while (mnt_monitor_next_change(m_mountMonitor, &filename, NULL) == 0) {
|
||||
if (!mtab && ((strcmp(filename, "/proc/self/mountinfo") == 0) || (strcmp(filename, "/run/mount/utab") == 0))) {
|
||||
mtab = true;
|
||||
}
|
||||
if (!fstab && (strcmp(filename, "/etc/fstab") == 0)) {
|
||||
fstab = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mtab) {
|
||||
Q_EMIT mtabChanged();
|
||||
}
|
||||
if (fstab) {
|
||||
Q_EMIT fstabChanged();
|
||||
}
|
||||
}
|
||||
#else
|
||||
void FstabWatcher::onFileChanged(const QString &path)
|
||||
{
|
||||
if (path == s_mtabFile) {
|
||||
Q_EMIT mtabChanged();
|
||||
if (!m_fileSystemWatcher->files().contains(s_mtabFile)) {
|
||||
m_fileSystemWatcher->addPath(s_mtabFile);
|
||||
}
|
||||
}
|
||||
if (path == s_fstabFile) {
|
||||
Q_EMIT fstabChanged();
|
||||
if (!m_fileSystemWatcher->files().contains(s_fstabFile)) {
|
||||
m_isFstabWatched = m_fileSystemWatcher->addPath(s_fstabFile);
|
||||
qCDebug(FSTAB_LOG) << "Fstab removed, re-added:" << m_isFstabWatched;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} // namespace Solid:Backends::Fstab
|
||||
|
||||
#include "moc_fstabwatcher.cpp"
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Mario Bensi <mbensi@ipsquad.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_FSTAB_WATCHER_H
|
||||
#define SOLID_BACKENDS_FSTAB_WATCHER_H
|
||||
|
||||
#include <QObject>
|
||||
#ifdef Q_OS_LINUX
|
||||
#include <libmount.h>
|
||||
#endif
|
||||
|
||||
class QFileSystemWatcher;
|
||||
class QFile;
|
||||
class QSocketNotifier;
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Fstab
|
||||
{
|
||||
class FstabWatcher : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FstabWatcher();
|
||||
~FstabWatcher() override;
|
||||
|
||||
static FstabWatcher *instance();
|
||||
|
||||
Q_SIGNALS:
|
||||
void mtabChanged();
|
||||
void fstabChanged();
|
||||
|
||||
private Q_SLOTS:
|
||||
#ifdef Q_OS_LINUX
|
||||
void onMountChanged();
|
||||
#else
|
||||
void onFileChanged(const QString &path);
|
||||
#endif
|
||||
|
||||
void onQuit();
|
||||
|
||||
private:
|
||||
QSocketNotifier *m_socketNotifier;
|
||||
#ifdef Q_OS_LINUX
|
||||
libmnt_monitor *m_mountMonitor;
|
||||
#else
|
||||
bool m_isRoutineInstalled;
|
||||
QFileSystemWatcher *m_fileSystemWatcher;
|
||||
QFile *m_mtabFile;
|
||||
bool m_isFstabWatched;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // SOLID_BACKENDS_FSTAB_WATCHER_H
|
||||
@@ -0,0 +1,17 @@
|
||||
set(backend_sources
|
||||
imobile.cpp
|
||||
imobiledevice.cpp
|
||||
imobilemanager.cpp
|
||||
imobiledeviceinterface.cpp
|
||||
imobileportablemediaplayer.cpp
|
||||
)
|
||||
set(backend_libs IMobileDevice::IMobileDevice PList::PList)
|
||||
|
||||
ecm_qt_declare_logging_category(backend_sources
|
||||
HEADER imobile_debug.h
|
||||
IDENTIFIER Solid::Backends::IMobile::IMOBILE
|
||||
DEFAULT_SEVERITY Warning
|
||||
CATEGORY_NAME kf.solid.backends.imobile
|
||||
DESCRIPTION "IMobileDevice (Solid)"
|
||||
EXPORT SOLID
|
||||
)
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 MBition GmbH
|
||||
SPDX-FileContributor: Kai Uwe Broulik <kai_uwe.broulik@mbition.io>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "imobile.h"
|
||||
|
||||
QString Solid::Backends::IMobile::udiPrefix()
|
||||
{
|
||||
return QStringLiteral("/org/kde/solid/imobile");
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 MBition GmbH
|
||||
SPDX-FileContributor: Kai Uwe Broulik <kai_uwe.broulik@mbition.io>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_IMOBILE_H
|
||||
#define SOLID_BACKENDS_IMOBILE_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace IMobile
|
||||
{
|
||||
QString udiPrefix();
|
||||
|
||||
} // namespace IMobile
|
||||
} // namespace Backends
|
||||
} // namespace Solid
|
||||
|
||||
#endif // SOLID_BACKENDS_IMOBILE_H
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 MBition GmbH
|
||||
SPDX-FileContributor: Kai Uwe Broulik <kai_uwe.broulik@mbition.io>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "imobiledevice.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QScopeGuard>
|
||||
|
||||
#include "imobile_debug.h"
|
||||
|
||||
#include "imobile.h"
|
||||
#include "imobileportablemediaplayer.h"
|
||||
|
||||
#include <libimobiledevice/libimobiledevice.h>
|
||||
#include <libimobiledevice/lockdown.h>
|
||||
|
||||
using namespace Solid::Backends::IMobile;
|
||||
|
||||
IMobileDevice::IMobileDevice(const QString &udi)
|
||||
: Solid::Ifaces::Device()
|
||||
, m_udi(udi)
|
||||
{
|
||||
const QString deviceId = udi.mid(udiPrefix().length() + 1);
|
||||
|
||||
idevice_t device;
|
||||
auto ret = idevice_new(&device, deviceId.toUtf8().constData());
|
||||
if (ret != IDEVICE_E_SUCCESS) {
|
||||
qCWarning(IMOBILE) << "Failed to create device instance for" << deviceId << ret;
|
||||
return;
|
||||
}
|
||||
|
||||
auto deviceCleanup = qScopeGuard([device] {
|
||||
idevice_free(device);
|
||||
});
|
||||
|
||||
lockdownd_client_t lockdowndClient = nullptr;
|
||||
auto lockdownRet = lockdownd_client_new(device, &lockdowndClient, "kde_solid_imobile");
|
||||
if (lockdownRet != LOCKDOWN_E_SUCCESS || !lockdowndClient) {
|
||||
qCWarning(IMOBILE) << "Failed to create lockdownd client for" << deviceId;
|
||||
return;
|
||||
}
|
||||
|
||||
auto lockdowndClientCleanup = qScopeGuard([lockdowndClient] {
|
||||
lockdownd_client_free(lockdowndClient);
|
||||
});
|
||||
|
||||
char *name = nullptr;
|
||||
lockdownRet = lockdownd_get_device_name(lockdowndClient, &name);
|
||||
if (lockdownRet != LOCKDOWN_E_SUCCESS) {
|
||||
qCWarning(IMOBILE) << "Failed to get device name for" << deviceId << lockdownRet;
|
||||
} else if (name) {
|
||||
m_name = QString::fromUtf8(name);
|
||||
free(name);
|
||||
}
|
||||
|
||||
plist_t deviceClassEntry = nullptr;
|
||||
lockdownRet = lockdownd_get_value(lockdowndClient, nullptr /*global domain*/, "DeviceClass", &deviceClassEntry);
|
||||
if (lockdownRet != LOCKDOWN_E_SUCCESS) {
|
||||
qCWarning(IMOBILE) << "Failed to get device class for" << deviceId << lockdownRet;
|
||||
} else {
|
||||
char *deviceClass = nullptr;
|
||||
plist_get_string_val(deviceClassEntry, &deviceClass);
|
||||
if (deviceClass) {
|
||||
m_deviceClass = QString::fromUtf8(deviceClass);
|
||||
free(deviceClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IMobileDevice::~IMobileDevice()
|
||||
{
|
||||
}
|
||||
|
||||
QString IMobileDevice::udi() const
|
||||
{
|
||||
return m_udi;
|
||||
}
|
||||
|
||||
QString IMobileDevice::parentUdi() const
|
||||
{
|
||||
return udiPrefix();
|
||||
}
|
||||
|
||||
QString IMobileDevice::vendor() const
|
||||
{
|
||||
return QCoreApplication::translate("imobiledevice", "Apple", "Company name");
|
||||
}
|
||||
|
||||
QString IMobileDevice::product() const
|
||||
{
|
||||
// TODO would be nice to use actual product names, e.g. "iPhone 5S"
|
||||
// but accessing device type requires doing a handshake with the device,
|
||||
// which will fail if locked or not paired, and also would require us
|
||||
// to maintain a giant mapping table
|
||||
return m_deviceClass;
|
||||
}
|
||||
|
||||
QString IMobileDevice::icon() const
|
||||
{
|
||||
if (m_deviceClass.contains(QLatin1String("iPod"))) {
|
||||
return QStringLiteral("multimedia-player-apple-ipod-touch");
|
||||
} else if (m_deviceClass.contains(QLatin1String("iPad"))) {
|
||||
return QStringLiteral("computer-apple-ipad");
|
||||
} else {
|
||||
return QStringLiteral("phone-apple-iphone");
|
||||
}
|
||||
}
|
||||
|
||||
QStringList IMobileDevice::emblems() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
QString IMobileDevice::description() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
bool IMobileDevice::queryDeviceInterface(const Solid::DeviceInterface::Type &type) const
|
||||
{
|
||||
switch (type) {
|
||||
// TODO would be cool to support GenericInterface for reading
|
||||
// arbitrary plist configuration, cf. what ideviceinfo tool does
|
||||
|
||||
case Solid::DeviceInterface::PortableMediaPlayer:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
QObject *IMobileDevice::createDeviceInterface(const Solid::DeviceInterface::Type &type)
|
||||
{
|
||||
if (!queryDeviceInterface(type)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case Solid::DeviceInterface::PortableMediaPlayer:
|
||||
return new PortableMediaPlayer(this);
|
||||
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_imobiledevice.cpp"
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 MBition GmbH
|
||||
SPDX-FileContributor: Kai Uwe Broulik <kai_uwe.broulik@mbition.io>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_IMOBILE_IMOBILEDEVICE_H
|
||||
#define SOLID_BACKENDS_IMOBILE_IMOBILEDEVICE_H
|
||||
|
||||
#include <QStringList>
|
||||
#include <solid/devices/ifaces/device.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace IMobile
|
||||
{
|
||||
class IMobileDevice : public Solid::Ifaces::Device
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit IMobileDevice(const QString &udi);
|
||||
~IMobileDevice() override;
|
||||
|
||||
QString udi() const override;
|
||||
QString parentUdi() const override;
|
||||
|
||||
QString vendor() const override;
|
||||
QString product() const override;
|
||||
QString icon() const override;
|
||||
QStringList emblems() const override;
|
||||
QString description() const override;
|
||||
|
||||
bool queryDeviceInterface(const Solid::DeviceInterface::Type &type) const override;
|
||||
|
||||
QObject *createDeviceInterface(const Solid::DeviceInterface::Type &type) override;
|
||||
|
||||
private:
|
||||
QString m_udi;
|
||||
|
||||
QString m_name;
|
||||
QString m_deviceClass;
|
||||
};
|
||||
|
||||
} // namespace IMobile
|
||||
} // namespace Backends
|
||||
} // namespace Solid
|
||||
|
||||
#endif // SOLID_BACKENDS_IMOBILE_IMOBILEDEVICE_H
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 MBition GmbH
|
||||
SPDX-FileContributor: Kai Uwe Broulik <kai_uwe.broulik@mbition.io>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "imobiledeviceinterface.h"
|
||||
|
||||
#include "imobiledevice.h"
|
||||
|
||||
using namespace Solid::Backends::IMobile;
|
||||
|
||||
DeviceInterface::DeviceInterface(IMobileDevice *device)
|
||||
: QObject(device)
|
||||
, m_device(device)
|
||||
{
|
||||
}
|
||||
|
||||
DeviceInterface::~DeviceInterface() = default;
|
||||
|
||||
#include "moc_imobiledeviceinterface.cpp"
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 MBition GmbH
|
||||
SPDX-FileContributor: Kai Uwe Broulik <kai_uwe.broulik@mbition.io>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_IMOBILE_IMOBILEDEVICEINTERFACE_H
|
||||
#define SOLID_BACKENDS_IMOBILE_IMOBILEDEVICEINTERFACE_H
|
||||
|
||||
#include <solid/devices/ifaces/deviceinterface.h>
|
||||
//#include "udevdevice.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace IMobile
|
||||
{
|
||||
class IMobileDevice;
|
||||
|
||||
class DeviceInterface : public QObject, virtual public Solid::Ifaces::DeviceInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::DeviceInterface)
|
||||
|
||||
public:
|
||||
explicit DeviceInterface(IMobileDevice *device);
|
||||
~DeviceInterface() override;
|
||||
|
||||
protected:
|
||||
IMobileDevice *m_device;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_IMOBILE_IMOBILEDEVICEINTERFACE_H
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 MBition GmbH
|
||||
SPDX-FileContributor: Kai Uwe Broulik <kai_uwe.broulik@mbition.io>
|
||||
SPDX-FileCopyrightText: 2023 Harald Sitter <sitter@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "imobilemanager.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QFileSystemWatcher>
|
||||
|
||||
#include "imobile_debug.h"
|
||||
|
||||
#include "../shared/rootdevice.h"
|
||||
#include "imobile.h"
|
||||
#include "imobiledevice.h"
|
||||
|
||||
using namespace Solid::Backends::IMobile;
|
||||
using namespace Solid::Backends::Shared;
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr auto VAR_RUN = "/var/run/"_L1;
|
||||
constexpr auto MUXD_SOCKET = "/var/run/usbmuxd"_L1;
|
||||
} // namespace
|
||||
|
||||
Manager::Manager(QObject *parent)
|
||||
: Solid::Ifaces::DeviceManager(parent)
|
||||
, m_watcher(new QFileSystemWatcher)
|
||||
{
|
||||
// Lazy initialize. If usbmuxd isn't running we don't need to do anything yet.
|
||||
// This is in part to prevent libusbmuxd from setting up extra inotifies and polling when
|
||||
// we know that it won't find anything yet. Works around a bunch of whoopsies.
|
||||
// https://github.com/libimobiledevice/libusbmuxd/pull/133
|
||||
// https://github.com/libimobiledevice/libusbmuxd/issues/135
|
||||
connect(m_watcher.get(), &QFileSystemWatcher::directoryChanged, this, [this](const QString &) {
|
||||
if (QFile::exists(MUXD_SOCKET)) {
|
||||
spinUp();
|
||||
}
|
||||
});
|
||||
m_watcher->addPath(VAR_RUN);
|
||||
if (QFile::exists(MUXD_SOCKET)) {
|
||||
spinUp();
|
||||
}
|
||||
}
|
||||
|
||||
Manager::~Manager()
|
||||
{
|
||||
if (m_spunUp) {
|
||||
idevice_event_unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
void Manager::spinUp()
|
||||
{
|
||||
if (m_spunUp) {
|
||||
return;
|
||||
}
|
||||
m_spunUp = true;
|
||||
// Handing over watching to libusbmuxd. Don't need our watcher anymore.
|
||||
// Deleting later because this function gets called by a signal from m_watcher so we mustn't delete it just now.
|
||||
m_watcher.release()->deleteLater();
|
||||
|
||||
auto ret = idevice_event_subscribe(
|
||||
[](const idevice_event_t *event, void *user_data) {
|
||||
// NOTE this is called from a different thread.
|
||||
static_cast<Manager *>(user_data)->onDeviceEvent(event);
|
||||
},
|
||||
this);
|
||||
if (ret != IDEVICE_E_SUCCESS) {
|
||||
qCWarning(IMOBILE) << "Failed to subscribe to device events";
|
||||
}
|
||||
|
||||
char **devices = nullptr;
|
||||
int count = 0;
|
||||
|
||||
ret = idevice_get_device_list(&devices, &count);
|
||||
if (ret != IDEVICE_E_SUCCESS && ret != IDEVICE_E_NO_DEVICE) {
|
||||
qCWarning(IMOBILE) << "Failed to get list of iOS devices" << ret;
|
||||
return;
|
||||
}
|
||||
|
||||
m_deviceUdis.reserve(count);
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
m_deviceUdis.append(Solid::Backends::IMobile::udiPrefix() + QLatin1Char('/') + QString::fromLatin1(devices[i]));
|
||||
}
|
||||
|
||||
if (devices) {
|
||||
idevice_device_list_free(devices);
|
||||
}
|
||||
}
|
||||
|
||||
QObject *Manager::createDevice(const QString &udi)
|
||||
{
|
||||
if (udi == udiPrefix()) {
|
||||
RootDevice *root = new RootDevice(udi);
|
||||
root->setProduct(tr("iDevice"));
|
||||
root->setDescription(tr("iOS devices"));
|
||||
root->setIcon(QStringLiteral("phone-apple-iphone"));
|
||||
return root;
|
||||
}
|
||||
|
||||
if (m_deviceUdis.contains(udi)) {
|
||||
return new IMobileDevice(udi);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QStringList Manager::devicesFromQuery(const QString &parentUdi, Solid::DeviceInterface::Type type)
|
||||
{
|
||||
QStringList devices;
|
||||
|
||||
if (!parentUdi.isEmpty() || type != Solid::DeviceInterface::Unknown) {
|
||||
for (const QString &udi : m_deviceUdis) {
|
||||
IMobileDevice device(udi);
|
||||
if (!device.queryDeviceInterface(type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!parentUdi.isEmpty() && device.parentUdi() != parentUdi) {
|
||||
continue;
|
||||
}
|
||||
|
||||
devices << udi;
|
||||
}
|
||||
}
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
QStringList Manager::allDevices()
|
||||
{
|
||||
return m_deviceUdis;
|
||||
}
|
||||
|
||||
QSet<Solid::DeviceInterface::Type> Manager::supportedInterfaces() const
|
||||
{
|
||||
return {Solid::DeviceInterface::PortableMediaPlayer};
|
||||
}
|
||||
|
||||
QString Manager::udiPrefix() const
|
||||
{
|
||||
return Solid::Backends::IMobile::udiPrefix();
|
||||
}
|
||||
|
||||
void Manager::onDeviceEvent(const idevice_event_t *event)
|
||||
{
|
||||
const QString udi = Solid::Backends::IMobile::udiPrefix() + QLatin1Char('/') + QString::fromLatin1(event->udid);
|
||||
|
||||
switch (event->event) {
|
||||
case IDEVICE_DEVICE_ADD:
|
||||
// Post it to the right thread.
|
||||
QMetaObject::invokeMethod(this, [this, udi] {
|
||||
if (!m_deviceUdis.contains(udi)) {
|
||||
m_deviceUdis.append(udi);
|
||||
Q_EMIT deviceAdded(udi);
|
||||
}
|
||||
});
|
||||
return;
|
||||
case IDEVICE_DEVICE_REMOVE:
|
||||
QMetaObject::invokeMethod(this, [this, udi] {
|
||||
if (m_deviceUdis.removeOne(udi)) {
|
||||
Q_EMIT deviceRemoved(udi);
|
||||
}
|
||||
});
|
||||
return;
|
||||
#if IMOBILEDEVICE_API >= QT_VERSION_CHECK(1, 3, 0)
|
||||
case IDEVICE_DEVICE_PAIRED:
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
qCDebug(IMOBILE) << "Unhandled device event" << event->event << "for" << event->udid;
|
||||
}
|
||||
|
||||
#include "moc_imobilemanager.cpp"
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 MBition GmbH
|
||||
SPDX-FileContributor: Kai Uwe Broulik <kai_uwe.broulik@mbition.io>
|
||||
SPDX-FileCopyrightText: 2023 Harald Sitter <sitter@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_IMOBILE_IMOBILEMANAGER_H
|
||||
#define SOLID_BACKENDS_IMOBILE_IMOBILEMANAGER_H
|
||||
|
||||
#include <solid/devices/ifaces/devicemanager.h>
|
||||
|
||||
#include <libimobiledevice/libimobiledevice.h>
|
||||
|
||||
class QFileSystemWatcher;
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace IMobile
|
||||
{
|
||||
class Manager : public Solid::Ifaces::DeviceManager
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Manager(QObject *parent);
|
||||
~Manager() override;
|
||||
|
||||
QObject *createDevice(const QString &udi) override;
|
||||
QStringList devicesFromQuery(const QString &parentUdi, Solid::DeviceInterface::Type type) override;
|
||||
QStringList allDevices() override;
|
||||
QSet<Solid::DeviceInterface::Type> supportedInterfaces() const override;
|
||||
QString udiPrefix() const override;
|
||||
|
||||
void onDeviceEvent(const idevice_event_t *event);
|
||||
|
||||
private:
|
||||
void spinUp();
|
||||
bool m_spunUp = false;
|
||||
QStringList m_deviceUdis;
|
||||
std::unique_ptr<QFileSystemWatcher> m_watcher;
|
||||
};
|
||||
|
||||
} // namespace IMobile
|
||||
} // namespace Backends
|
||||
} // namespace Solid
|
||||
|
||||
#endif // SOLID_BACKENDS_IMOBILE_IMOBILEMANAGER_H
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 MBition GmbH
|
||||
SPDX-FileContributor: Kai Uwe Broulik <kai_uwe.broulik@mbition.io>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "imobileportablemediaplayer.h"
|
||||
|
||||
#include "imobile.h"
|
||||
#include "imobiledevice.h"
|
||||
|
||||
using namespace Solid::Backends::IMobile;
|
||||
|
||||
PortableMediaPlayer::PortableMediaPlayer(IMobileDevice *device)
|
||||
: DeviceInterface(device)
|
||||
{
|
||||
}
|
||||
|
||||
PortableMediaPlayer::~PortableMediaPlayer()
|
||||
{
|
||||
}
|
||||
|
||||
QStringList PortableMediaPlayer::supportedProtocols() const
|
||||
{
|
||||
return {QStringLiteral("afc")};
|
||||
}
|
||||
|
||||
QStringList PortableMediaPlayer::supportedDrivers(QString protocol) const
|
||||
{
|
||||
Q_UNUSED(protocol)
|
||||
return {// libimobiledevice goes via usbmuxd
|
||||
QStringLiteral("usbmux")};
|
||||
}
|
||||
|
||||
QVariant PortableMediaPlayer::driverHandle(const QString &driver) const
|
||||
{
|
||||
if (driver == QLatin1String("usbmux")) {
|
||||
// as per docs "usbmux" should return the device UDID
|
||||
// which we use as part of our UDI
|
||||
return m_device->udi().mid(udiPrefix().length() + 1);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
#include "moc_imobileportablemediaplayer.cpp"
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Rafael Fernández López <ereslibre@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_IMOBILE_IMOBILEPORTABLEMEDIAPLAYER_H
|
||||
#define SOLID_BACKENDS_IMOBILE_IMOBILEPORTABLEMEDIAPLAYER_H
|
||||
|
||||
#include <solid/devices/ifaces/portablemediaplayer.h>
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
#include "imobiledeviceinterface.h"
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace IMobile
|
||||
{
|
||||
class IMobileDevice;
|
||||
|
||||
class PortableMediaPlayer : public DeviceInterface, virtual public Solid::Ifaces::PortableMediaPlayer
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::PortableMediaPlayer)
|
||||
|
||||
public:
|
||||
PortableMediaPlayer(IMobileDevice *device);
|
||||
~PortableMediaPlayer() override;
|
||||
|
||||
QStringList supportedProtocols() const override;
|
||||
QStringList supportedDrivers(QString protocol = QString()) const override;
|
||||
QVariant driverHandle(const QString &driver) const override;
|
||||
};
|
||||
|
||||
} // namespace IMobile
|
||||
} // namespace Backends
|
||||
} // namespace Solid
|
||||
|
||||
#endif // SOLID_BACKENDS_IMOBILE_IMOBILEPORTABLEMEDIAPLAYER_H
|
||||
@@ -0,0 +1,17 @@
|
||||
set(backend_sources
|
||||
iokitmanager.cpp
|
||||
iokitdevice.cpp
|
||||
cfhelper.cpp
|
||||
dadictionary.cpp
|
||||
iokitdeviceinterface.cpp
|
||||
iokitgenericinterface.cpp
|
||||
iokitprocessor.cpp
|
||||
iokitbattery.cpp
|
||||
iokitblock.cpp
|
||||
iokitstorage.cpp
|
||||
iokitvolume.cpp
|
||||
iokitstorageaccess.cpp
|
||||
iokitopticaldrive.cpp
|
||||
iokitopticaldisc.cpp
|
||||
)
|
||||
set(backend_libs ${IOKIT_LIBRARY} "-framework DiskArbitration")
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Harald Fernengel <harry@kdevelop.org>
|
||||
SPDX-FileCopyrightText: 2017 René J.V. Bertin <rjvbertin@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include <qdatetime.h>
|
||||
#include <qdebug.h>
|
||||
#include <qstring.h>
|
||||
#include <qstringlist.h>
|
||||
#include <qvariant.h>
|
||||
#include <qvarlengtharray.h>
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
/* helper classes to convert from CF types to Qt */
|
||||
|
||||
static QString q_toString(const CFStringRef &str)
|
||||
{
|
||||
CFIndex length = CFStringGetLength(str);
|
||||
QVarLengthArray<UniChar> buffer(length);
|
||||
|
||||
CFRange range = {0, length};
|
||||
CFStringGetCharacters(str, range, buffer.data());
|
||||
return QString(reinterpret_cast<const QChar *>(buffer.data()), length);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline T convertCFNumber(const CFNumberRef &num, CFNumberType type)
|
||||
{
|
||||
T n;
|
||||
CFNumberGetValue(num, type, &n);
|
||||
return n;
|
||||
}
|
||||
|
||||
static QVariant q_toVariant(const CFTypeRef &obj)
|
||||
{
|
||||
const CFTypeID typeId = CFGetTypeID(obj);
|
||||
|
||||
if (typeId == CFStringGetTypeID()) {
|
||||
return QVariant(q_toString(static_cast<const CFStringRef>(obj)));
|
||||
}
|
||||
|
||||
if (typeId == CFNumberGetTypeID()) {
|
||||
const CFNumberRef num = static_cast<const CFNumberRef>(obj);
|
||||
const CFNumberType type = CFNumberGetType(num);
|
||||
switch (type) {
|
||||
case kCFNumberSInt8Type:
|
||||
return QVariant::fromValue(convertCFNumber<char>(num, type));
|
||||
case kCFNumberSInt16Type:
|
||||
return QVariant::fromValue(convertCFNumber<qint16>(num, type));
|
||||
case kCFNumberSInt32Type:
|
||||
return QVariant::fromValue(convertCFNumber<qint32>(num, type));
|
||||
case kCFNumberSInt64Type:
|
||||
return QVariant::fromValue(convertCFNumber<qint64>(num, type));
|
||||
case kCFNumberCharType:
|
||||
return QVariant::fromValue(convertCFNumber<uchar>(num, type));
|
||||
case kCFNumberShortType:
|
||||
return QVariant::fromValue(convertCFNumber<short>(num, type));
|
||||
case kCFNumberIntType:
|
||||
return QVariant::fromValue(convertCFNumber<int>(num, type));
|
||||
case kCFNumberLongType:
|
||||
return QVariant::fromValue(convertCFNumber<long>(num, type));
|
||||
case kCFNumberLongLongType:
|
||||
return QVariant::fromValue(convertCFNumber<long long>(num, type));
|
||||
case kCFNumberFloatType:
|
||||
return QVariant::fromValue(convertCFNumber<float>(num, type));
|
||||
case kCFNumberDoubleType:
|
||||
return QVariant::fromValue(convertCFNumber<double>(num, type));
|
||||
default:
|
||||
if (CFNumberIsFloatType(num)) {
|
||||
return QVariant::fromValue(convertCFNumber<double>(num, kCFNumberDoubleType));
|
||||
}
|
||||
return QVariant::fromValue(convertCFNumber<quint64>(num, kCFNumberLongLongType));
|
||||
}
|
||||
}
|
||||
|
||||
if (typeId == CFDateGetTypeID()) {
|
||||
QDateTime dt;
|
||||
dt.setSecsSinceEpoch(qint64(kCFAbsoluteTimeIntervalSince1970));
|
||||
return dt.addSecs(int(CFDateGetAbsoluteTime(static_cast<const CFDateRef>(obj))));
|
||||
}
|
||||
|
||||
if (typeId == CFDataGetTypeID()) {
|
||||
const CFDataRef cfdata = static_cast<const CFDataRef>(obj);
|
||||
return QByteArray(reinterpret_cast<const char *>(CFDataGetBytePtr(cfdata)), CFDataGetLength(cfdata));
|
||||
}
|
||||
|
||||
if (typeId == CFBooleanGetTypeID()) {
|
||||
return QVariant(bool(CFBooleanGetValue(static_cast<const CFBooleanRef>(obj))));
|
||||
}
|
||||
|
||||
if (typeId == CFArrayGetTypeID()) {
|
||||
const CFArrayRef cfarray = static_cast<const CFArrayRef>(obj);
|
||||
QList<QVariant> list;
|
||||
CFIndex size = CFArrayGetCount(cfarray);
|
||||
bool metNonString = false;
|
||||
for (CFIndex i = 0; i < size; ++i) {
|
||||
QVariant value = q_toVariant(CFArrayGetValueAtIndex(cfarray, i));
|
||||
if (value.userType() != QMetaType::QString) {
|
||||
metNonString = true;
|
||||
}
|
||||
list << value;
|
||||
}
|
||||
if (metNonString) {
|
||||
return list;
|
||||
} else {
|
||||
return QVariant(list).toStringList();
|
||||
}
|
||||
}
|
||||
|
||||
if (typeId == CFDictionaryGetTypeID()) {
|
||||
const CFDictionaryRef cfdict = static_cast<const CFDictionaryRef>(obj);
|
||||
const CFTypeID arrayTypeId = CFArrayGetTypeID();
|
||||
int size = int(CFDictionaryGetCount(cfdict));
|
||||
QVarLengthArray<CFPropertyListRef> keys(size);
|
||||
QVarLengthArray<CFPropertyListRef> values(size);
|
||||
CFDictionaryGetKeysAndValues(cfdict, keys.data(), values.data());
|
||||
|
||||
QMultiMap<QString, QVariant> map;
|
||||
for (int i = 0; i < size; ++i) {
|
||||
QString key = q_toString(static_cast<const CFStringRef>(keys[i]));
|
||||
|
||||
if (CFGetTypeID(values[i]) == arrayTypeId) {
|
||||
const CFArrayRef cfarray = static_cast<const CFArrayRef>(values[i]);
|
||||
CFIndex arraySize = CFArrayGetCount(cfarray);
|
||||
for (CFIndex j = arraySize - 1; j >= 0; --j) {
|
||||
map.insert(key, q_toVariant(CFArrayGetValueAtIndex(cfarray, j)));
|
||||
}
|
||||
} else {
|
||||
map.insert(key, q_toVariant(values[i]));
|
||||
}
|
||||
}
|
||||
return QVariant::fromValue(map);
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QMap<QString, QVariant> q_toVariantMap(const CFMutableDictionaryRef &dict)
|
||||
{
|
||||
Q_ASSERT(dict);
|
||||
|
||||
QMap<QString, QVariant> result;
|
||||
|
||||
const int count = CFDictionaryGetCount(dict);
|
||||
QVarLengthArray<void *> keys(count);
|
||||
QVarLengthArray<void *> values(count);
|
||||
|
||||
CFDictionaryGetKeysAndValues(dict, const_cast<const void **>(keys.data()), const_cast<const void **>(values.data()));
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const QString key = q_toString((CFStringRef)keys[i]);
|
||||
const QVariant value = q_toVariant((CFTypeRef)values[i]);
|
||||
result[key] = value;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool q_sysctlbyname(const char *name, QString &result)
|
||||
{
|
||||
char *property = nullptr;
|
||||
size_t size = 0;
|
||||
int error = 0;
|
||||
if (name && sysctlbyname(name, nullptr, &size, nullptr, 0) == 0 && size > 0) {
|
||||
property = new char[size];
|
||||
error = sysctlbyname(name, property, &size, nullptr, 0);
|
||||
if (!error) {
|
||||
result = QLatin1String(property);
|
||||
}
|
||||
delete[] property;
|
||||
}
|
||||
return !error;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2018 René J.V. Bertin <rjvbertin@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "dadictionary_p.h"
|
||||
|
||||
using namespace Solid::Backends::IOKit;
|
||||
|
||||
DADictionary::DADictionary(const IOKitDevice *device)
|
||||
: device(device)
|
||||
, daSession(DASessionCreate(kCFAllocatorDefault))
|
||||
, daDict(nullptr)
|
||||
{
|
||||
if (daSession) {
|
||||
const QString devName = device->property(QStringLiteral("BSD Name")).toString();
|
||||
daRef = DADiskCreateFromBSDName(kCFAllocatorDefault, daSession, devName.toStdString().c_str());
|
||||
} else {
|
||||
daRef = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
DADictionary::~DADictionary()
|
||||
{
|
||||
releaseDict();
|
||||
if (daRef) {
|
||||
CFRelease(daRef);
|
||||
daRef = nullptr;
|
||||
}
|
||||
if (daSession) {
|
||||
CFRelease(daSession);
|
||||
daSession = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool DADictionary::getDict()
|
||||
{
|
||||
// daDict may cache the latest disk description dict;
|
||||
// we will refresh it now.
|
||||
releaseDict();
|
||||
if (daRef) {
|
||||
daDict = DADiskCopyDescription(daRef);
|
||||
}
|
||||
return daDict != nullptr;
|
||||
}
|
||||
|
||||
void DADictionary::releaseDict()
|
||||
{
|
||||
if (daDict) {
|
||||
CFRelease(daDict);
|
||||
daDict = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
const QString DADictionary::stringForKey(const CFStringRef key)
|
||||
{
|
||||
QString ret;
|
||||
if (getDict()) {
|
||||
ret = QString::fromCFString((const CFStringRef)CFDictionaryGetValue(daDict, key));
|
||||
releaseDict();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
CFURLRef DADictionary::cfUrLRefForKey(const CFStringRef key)
|
||||
{
|
||||
CFURLRef ret = nullptr;
|
||||
if (getDict()) {
|
||||
ret = (const CFURLRef)CFDictionaryGetValue(daDict, key);
|
||||
}
|
||||
// we cannot release the dictionary here, or else we'd need to
|
||||
// copy the CFURLRef and oblige our caller to release the return value.
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool DADictionary::boolForKey(const CFStringRef key, bool &value)
|
||||
{
|
||||
if (getDict()) {
|
||||
const CFBooleanRef boolRef = (const CFBooleanRef)CFDictionaryGetValue(daDict, key);
|
||||
if (boolRef) {
|
||||
value = CFBooleanGetValue(boolRef);
|
||||
}
|
||||
releaseDict();
|
||||
return boolRef != nullptr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2018 René J.V. Bertin <rjvbertin@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_IOKIT_DADICTIONARY_P_H
|
||||
#define SOLID_BACKENDS_IOKIT_DADICTIONARY_P_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include "iokitdevice.h"
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <DiskArbitration/DiskArbitration.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace IOKit
|
||||
{
|
||||
class DADictionary
|
||||
{
|
||||
public:
|
||||
DADictionary(const IOKitDevice *device);
|
||||
virtual ~DADictionary();
|
||||
|
||||
/**
|
||||
* get a fresh copy of the DA disk description dict;
|
||||
* the result is stored in daRef (after releasing any
|
||||
* dict it may currently point to).
|
||||
*/
|
||||
bool getDict();
|
||||
/**
|
||||
* release the DA disk description dict and reset daRef.
|
||||
*/
|
||||
void releaseDict();
|
||||
|
||||
/**
|
||||
* fetch the value of @p key as a string, from the current
|
||||
* disk description (calls getDict() and releaseDict()).
|
||||
*/
|
||||
const QString stringForKey(const CFStringRef key);
|
||||
/**
|
||||
* fetch the value of @p key as a CFURLRef, from the current
|
||||
* disk description. Calls getDict() but not releaseDict().
|
||||
*The contents of the CFURLRef must be retrieved before
|
||||
* calling releaseDict() (and thus getDict()).
|
||||
*/
|
||||
CFURLRef cfUrLRefForKey(const CFStringRef key);
|
||||
/**
|
||||
* fetch the value of @p key as a boolean, from the current
|
||||
* disk description (calls getDict() and releaseDict()).
|
||||
*/
|
||||
bool boolForKey(const CFStringRef key, bool &value);
|
||||
|
||||
const IOKitDevice *device;
|
||||
DASessionRef daSession;
|
||||
DADiskRef daRef;
|
||||
CFDictionaryRef daDict;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_IOKIT_DADICTIONARY_P_H
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Harald Fernengel <harry@kdevelop.org>
|
||||
SPDX-FileCopyrightText: 2017 René J.V. Bertin <rjvbertin@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "iokitbattery.h"
|
||||
#include "iokitdevice.h"
|
||||
|
||||
// TODO - emit the signals
|
||||
|
||||
using namespace Solid::Backends::IOKit;
|
||||
|
||||
Battery::Battery(IOKitDevice *device)
|
||||
: DeviceInterface(device)
|
||||
{
|
||||
}
|
||||
|
||||
Battery::~Battery()
|
||||
{
|
||||
}
|
||||
|
||||
// properties: QMap(("AdapterInfo", QVariant(int, 0))
|
||||
// ("Amperage", QVariant(int, 0))
|
||||
// ("AvgTimeToEmpty", QVariant(int, 65535))
|
||||
// ("AvgTimeToFull", QVariant(int, 65535))
|
||||
// ("BatteryInstalled", QVariant(bool, true))
|
||||
// ("BatteryInvalidWakeSeconds", QVariant(int, 30))
|
||||
// ("BatterySerialNumber", QVariant(QString, "W01286PEED3BA"))
|
||||
// ("BootPathUpdated", QVariant(int, 1501532930))
|
||||
// ("CellVoltage", QVariant(QVariantList, (QVariant(int, 4136), QVariant(int, 4134), QVariant(int, 4134), QVariant(int, 0))))
|
||||
// ("CurrentCapacity", QVariant(int, 5552))
|
||||
// ("CycleCount", QVariant(int, 16))
|
||||
// ("DesignCapacity", QVariant(int, 5770))
|
||||
// ("DesignCycleCount", QVariant(int, 1000))
|
||||
// ("DeviceName", QVariant(QString, "bq20z451"))
|
||||
// ("ExternalChargeCapable", QVariant(bool, true))
|
||||
// ("ExternalConnected", QVariant(bool, true))
|
||||
// ("FirmwareSerialNumber", QVariant(int, 48))
|
||||
// ("FullPathUpdated", QVariant(int, 1502790621))
|
||||
// ("FullyCharged", QVariant(bool, true))
|
||||
// ("IOGeneralInterest", QVariant(QString, "IOCommand is not serializable"))
|
||||
// ("InstantAmperage", QVariant(int, 0))
|
||||
// ("InstantTimeToEmpty", QVariant(int, 65535))
|
||||
// ("IsCharging", QVariant(bool, false))
|
||||
// ("LegacyBatteryInfo", QVariant(QVariantMap, QMap(("Amperage", QVariant(int, 0))
|
||||
// ("Capacity", QVariant(int, 5814))
|
||||
// ("Current", QVariant(int, 5552))
|
||||
// ("Cycle Count", QVariant(int, 16))
|
||||
// ("Flags", QVariant(int, 5))
|
||||
// ("Voltage", QVariant(int, 12403)))))
|
||||
// ("Location", QVariant(int, 0))
|
||||
// ("ManufactureDate", QVariant(int, 16106))
|
||||
// ("Manufacturer", QVariant(QString, "SMP"))
|
||||
// ("ManufacturerData", QVariant(QByteArray, "\x00\x00\x00\x00\x02\x01\x00\n\x01X\x00\x00\x02K6c\x03""00A\x03""ATL\x00\x12\x00\x00"))
|
||||
// ("MaxCapacity", QVariant(int, 5814))
|
||||
// ("MaxErr", QVariant(int, 1))
|
||||
// ("OperationStatus", QVariant(int, 58435))
|
||||
// ("PackReserve", QVariant(int, 200))
|
||||
// ("PermanentFailureStatus", QVariant(int, 0))
|
||||
// ("PostChargeWaitSeconds", QVariant(int, 120))
|
||||
// ("PostDischargeWaitSeconds", QVariant(int, 120))
|
||||
// ("Temperature", QVariant(int, 2965))
|
||||
// ("TimeRemaining", QVariant(int, 0))
|
||||
// ("UserVisiblePathUpdated", QVariant(int, 1502790679))
|
||||
// ("Voltage", QVariant(int, 12403))
|
||||
// ("className", QVariant(QString, "AppleSmartBattery")))
|
||||
|
||||
qlonglong Battery::timeToEmpty() const
|
||||
{
|
||||
if (chargeState() != Solid::Battery::Charging) {
|
||||
int t = m_device->property(QStringLiteral("AvgTimeToEmpty")).toInt();
|
||||
return t == 65535 ? -1 : t * 60;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
qlonglong Battery::timeToFull() const
|
||||
{
|
||||
if (chargeState() == Solid::Battery::Charging) {
|
||||
int t = m_device->property(QStringLiteral("AvgTimeToFull")).toInt();
|
||||
return t == 65535 ? -1 : t * 60;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
double Battery::voltage() const
|
||||
{
|
||||
return m_device->property(QStringLiteral("Voltage")).toInt() / 1000.0;
|
||||
}
|
||||
|
||||
double Battery::temperature() const
|
||||
{
|
||||
return m_device->property(QStringLiteral("Temperature")).toInt() / 100.0;
|
||||
}
|
||||
|
||||
QString Battery::serial() const
|
||||
{
|
||||
return m_device->property(QStringLiteral("BatterySerialNumber")).toString();
|
||||
}
|
||||
|
||||
bool Battery::isPresent() const
|
||||
{
|
||||
return m_device->property(QStringLiteral("ExternalConnected")).toBool();
|
||||
}
|
||||
|
||||
Solid::Battery::BatteryType Battery::type() const
|
||||
{
|
||||
// TODO - how to figure that one out? Just presume we're
|
||||
// only called with the main battery.
|
||||
return Solid::Battery::PrimaryBattery;
|
||||
}
|
||||
|
||||
int Battery::chargePercent() const
|
||||
{
|
||||
// always calculate since FullyCharged remains true down to 92% or so.
|
||||
int maxCapacity = m_device->property(QStringLiteral("MaxCapacity")).toInt();
|
||||
if (maxCapacity == 0) {
|
||||
return 0; // prevent divide by 0
|
||||
}
|
||||
return int(m_device->property(QStringLiteral("CurrentCapacity")).toInt() * 100.0 / maxCapacity + 0.5);
|
||||
}
|
||||
|
||||
int Battery::capacity() const
|
||||
{
|
||||
if (m_device->iOKitPropertyExists(QStringLiteral("PermanentFailureStatus")) //
|
||||
&& m_device->property(QStringLiteral("PermanentFailureStatus")).toInt()) {
|
||||
return 0;
|
||||
}
|
||||
return 100;
|
||||
}
|
||||
|
||||
int Battery::cycleCount() const
|
||||
{
|
||||
return m_device->property(QStringLiteral("CycleCount")).toInt();
|
||||
}
|
||||
|
||||
bool Battery::isRechargeable() const
|
||||
{
|
||||
return m_device->property(QStringLiteral("CycleCount")).toInt() > 1;
|
||||
}
|
||||
|
||||
bool Battery::isPowerSupply() const
|
||||
{
|
||||
/* clang-format off */
|
||||
return m_device->iOKitPropertyExists(QStringLiteral("BatteryInstalled"))
|
||||
? m_device->property(QStringLiteral("BatteryInstalled")).toBool()
|
||||
: true;
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
Solid::Battery::ChargeState Battery::chargeState() const
|
||||
{
|
||||
if (m_device->property(QStringLiteral("IsCharging")).toBool()) {
|
||||
return Solid::Battery::Charging;
|
||||
}
|
||||
if (m_device->property(QStringLiteral("FullyCharged")).toBool()) {
|
||||
return Solid::Battery::FullyCharged;
|
||||
}
|
||||
return Solid::Battery::Discharging;
|
||||
}
|
||||
|
||||
#include "moc_iokitbattery.cpp"
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Harald Fernengel <harry@kdevelop.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_IOKIT_BATTERY_H
|
||||
#define SOLID_BACKENDS_IOKIT_BATTERY_H
|
||||
|
||||
#include "iokitdeviceinterface.h"
|
||||
#include <solid/devices/ifaces/battery.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace IOKit
|
||||
{
|
||||
class IOKitDevice;
|
||||
|
||||
class Battery : public DeviceInterface, virtual public Solid::Ifaces::Battery
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::Battery)
|
||||
|
||||
public:
|
||||
Battery(IOKitDevice *device);
|
||||
virtual ~Battery();
|
||||
|
||||
bool isPresent() const override;
|
||||
Solid::Battery::BatteryType type() const override;
|
||||
|
||||
int chargePercent() const override;
|
||||
int capacity() const override;
|
||||
int cycleCount() const override;
|
||||
|
||||
bool isRechargeable() const override;
|
||||
bool isPowerSupply() const override;
|
||||
|
||||
Solid::Battery::ChargeState chargeState() const override;
|
||||
|
||||
qlonglong timeToEmpty() const override;
|
||||
qlonglong timeToFull() const override;
|
||||
double voltage() const override;
|
||||
double temperature() const override;
|
||||
QString serial() const override;
|
||||
|
||||
// ### the ones below are TODO
|
||||
// clang-format off
|
||||
Solid::Battery::Technology technology() const override { return Solid::Battery::UnknownTechnology; }
|
||||
double energy() const override { return 0.0; }
|
||||
double energyFull() const override { return 0.0; }
|
||||
double energyFullDesign() const override { return 0.0; }
|
||||
double energyRate() const override { return 0.0; }
|
||||
|
||||
qlonglong remainingTime() const override { return -1; }
|
||||
// clang-format on
|
||||
|
||||
Q_SIGNALS:
|
||||
void energyChanged(double energy, const QString &udi) override;
|
||||
void energyFullChanged(double energyFull, const QString &udi) override;
|
||||
void energyFullDesignChanged(double energyFullDesign, const QString &udi) override;
|
||||
void energyRateChanged(double energyRate, const QString &udi) override;
|
||||
void chargePercentChanged(int value, const QString &udi) override;
|
||||
void capacityChanged(int value, const QString &udi) override;
|
||||
void cycleCountChanged(int value, const QString &udi) override;
|
||||
void chargeStateChanged(int newState, const QString &udi) override;
|
||||
void presentStateChanged(bool newState, const QString &udi) override;
|
||||
void powerSupplyStateChanged(bool newState, const QString &udi) override;
|
||||
void timeToEmptyChanged(qlonglong time, const QString &udi) override;
|
||||
void timeToFullChanged(qlonglong time, const QString &udi) override;
|
||||
void temperatureChanged(double temperature, const QString &udi) override;
|
||||
void voltageChanged(double voltage, const QString &udi) override;
|
||||
void remainingTimeChanged(qlonglong time, const QString &udi) override;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_IOKIT_BATTERY_H
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2017 René J.V. Bertin <rjvbertin@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "iokitblock.h"
|
||||
|
||||
#include "iokitdevice.h"
|
||||
|
||||
using namespace Solid::Backends::IOKit;
|
||||
|
||||
Block::Block(IOKitDevice *device)
|
||||
: DeviceInterface(device)
|
||||
{
|
||||
}
|
||||
|
||||
Block::Block(const IOKitDevice *device)
|
||||
: DeviceInterface(device)
|
||||
{
|
||||
}
|
||||
|
||||
Block::~Block()
|
||||
{
|
||||
}
|
||||
|
||||
int Block::deviceMajor() const
|
||||
{
|
||||
return m_device->property(QLatin1String("BSD Major")).toInt();
|
||||
}
|
||||
|
||||
int Block::deviceMinor() const
|
||||
{
|
||||
return m_device->property(QLatin1String("BSD Minor")).toInt();
|
||||
}
|
||||
|
||||
QString Block::device() const
|
||||
{
|
||||
if (m_device->iOKitPropertyExists(QStringLiteral("BSD Name"))) {
|
||||
return QStringLiteral("/dev/") + m_device->property(QLatin1String("BSD Name")).toString();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
#include "moc_iokitblock.cpp"
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2017 René J.V. Bertin <rjvbertin@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_IOKIT_BLOCK_H
|
||||
#define SOLID_BACKENDS_IOKIT_BLOCK_H
|
||||
|
||||
#include "iokitdeviceinterface.h"
|
||||
#include <solid/devices/ifaces/block.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace IOKit
|
||||
{
|
||||
class Block : public DeviceInterface, virtual public Solid::Ifaces::Block
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::Block)
|
||||
|
||||
public:
|
||||
Block(IOKitDevice *device);
|
||||
Block(const IOKitDevice *device);
|
||||
virtual ~Block();
|
||||
|
||||
int deviceMajor() const override;
|
||||
int deviceMinor() const override;
|
||||
QString device() const override;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_IOKIT_BLOCK_H
|
||||
@@ -0,0 +1,520 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Harald Fernengel <harry@kdevelop.org>
|
||||
SPDX-FileCopyrightText: 2017 René J.V. Bertin <rjvbertin@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "iokitdevice.h"
|
||||
#include "iokitbattery.h"
|
||||
#include "iokitgenericinterface.h"
|
||||
#include "iokitopticaldisc.h"
|
||||
#include "iokitopticaldrive.h"
|
||||
#include "iokitprocessor.h"
|
||||
#include "iokitstorage.h"
|
||||
#include "iokitstorageaccess.h"
|
||||
#include "iokitvolume.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QSet>
|
||||
#include <QUrl>
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <IOKit/network/IOEthernetInterface.h>
|
||||
#include <IOKit/usb/IOUSBLib.h>
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
// from cfhelper.cpp
|
||||
extern QMap<QString, QVariant> q_toVariantMap(const CFMutableDictionaryRef &dict);
|
||||
extern bool q_sysctlbyname(const char *name, QString &result);
|
||||
|
||||
typedef QSet<Solid::DeviceInterface::Type> DeviceInterfaceTypes;
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace IOKit
|
||||
{
|
||||
// returns a solid type from an entry and its properties
|
||||
static DeviceInterfaceTypes typesFromEntry(const io_registry_entry_t &entry, const QMap<QString, QVariant> &properties, Solid::DeviceInterface::Type &mainType)
|
||||
{
|
||||
DeviceInterfaceTypes types;
|
||||
mainType = Solid::DeviceInterface::Unknown;
|
||||
if (IOObjectConformsTo(entry, "AppleACPICPU")) {
|
||||
mainType = Solid::DeviceInterface::Processor;
|
||||
types << mainType;
|
||||
}
|
||||
if (IOObjectConformsTo(entry, "AppleSmartBattery")) {
|
||||
mainType = Solid::DeviceInterface::Battery;
|
||||
types << mainType;
|
||||
}
|
||||
const QString bsdName = QStringLiteral("BSD Name");
|
||||
const QString leaf = QStringLiteral("Leaf");
|
||||
if (IOObjectConformsTo(entry, "IOCDMedia") //
|
||||
|| IOObjectConformsTo(entry, "IODVDMedia") //
|
||||
|| IOObjectConformsTo(entry, "IOBDMedia")) {
|
||||
mainType = Solid::DeviceInterface::OpticalDrive;
|
||||
types << mainType << Solid::DeviceInterface::OpticalDisc;
|
||||
}
|
||||
if (properties.contains(bsdName) && properties.value(bsdName).toString().startsWith(QStringLiteral("disk"))) {
|
||||
if ((properties.contains(leaf) && properties.value(leaf).toBool() == false) //
|
||||
|| mainType == Solid::DeviceInterface::OpticalDrive) {
|
||||
if (mainType == Solid::DeviceInterface::Unknown) {
|
||||
mainType = Solid::DeviceInterface::StorageDrive;
|
||||
}
|
||||
types << Solid::DeviceInterface::StorageDrive;
|
||||
} else if (mainType == Solid::DeviceInterface::Unknown) {
|
||||
mainType = Solid::DeviceInterface::StorageVolume;
|
||||
}
|
||||
types << Solid::DeviceInterface::StorageVolume;
|
||||
}
|
||||
|
||||
if (types.isEmpty()) {
|
||||
types << mainType;
|
||||
// qWarning() << "unsupported entry" << entry << "with properties" << properties;
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
// gets all properties from an entry into a QMap
|
||||
static QMap<QString, QVariant> getProperties(const io_registry_entry_t &entry)
|
||||
{
|
||||
CFMutableDictionaryRef propertyDict = 0;
|
||||
|
||||
if (IORegistryEntryCreateCFProperties(entry, &propertyDict, kCFAllocatorDefault, kNilOptions) != KERN_SUCCESS) {
|
||||
return QMap<QString, QVariant>();
|
||||
}
|
||||
|
||||
QMap<QString, QVariant> result = q_toVariantMap(propertyDict);
|
||||
|
||||
CFRelease(propertyDict);
|
||||
|
||||
io_name_t className;
|
||||
IOObjectGetClass(entry, className);
|
||||
result[QStringLiteral("className")] = QString::fromUtf8(className);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// gets the parent's Udi from an entry
|
||||
static QString getParentDeviceUdi(const io_registry_entry_t &entry)
|
||||
{
|
||||
io_registry_entry_t parent = 0;
|
||||
kern_return_t ret = IORegistryEntryGetParentEntry(entry, kIOServicePlane, &parent);
|
||||
if (ret != KERN_SUCCESS) {
|
||||
// don't release parent here - docs say only on success
|
||||
return QString();
|
||||
}
|
||||
|
||||
CFStringRef path = IORegistryEntryCopyPath(parent, kIOServicePlane);
|
||||
QString result = QString::fromCFString(path);
|
||||
CFRelease(path);
|
||||
|
||||
// now we can release the parent
|
||||
IOObjectRelease(parent);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static const QString computerModel()
|
||||
{
|
||||
QString qModel;
|
||||
q_sysctlbyname("hw.model", qModel);
|
||||
return qModel;
|
||||
}
|
||||
|
||||
class IOKitDevicePrivate
|
||||
{
|
||||
public:
|
||||
inline IOKitDevicePrivate()
|
||||
: type({Solid::DeviceInterface::Unknown})
|
||||
, parentDevice(nullptr)
|
||||
{
|
||||
}
|
||||
~IOKitDevicePrivate()
|
||||
{
|
||||
if (parentDevice) {
|
||||
delete parentDevice;
|
||||
parentDevice = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void init(const QString &udiString, const io_registry_entry_t &entry);
|
||||
IOKitDevice *getParentDevice();
|
||||
|
||||
QString udi;
|
||||
QString parentUdi;
|
||||
QMap<QString, QVariant> properties;
|
||||
DeviceInterfaceTypes type;
|
||||
Solid::DeviceInterface::Type mainType;
|
||||
IOKitDevice *parentDevice;
|
||||
};
|
||||
|
||||
void IOKitDevicePrivate::init(const QString &udiString, const io_registry_entry_t &entry)
|
||||
{
|
||||
Q_ASSERT(entry != MACH_PORT_NULL);
|
||||
|
||||
udi = udiString;
|
||||
|
||||
properties = getProperties(entry);
|
||||
|
||||
parentUdi = getParentDeviceUdi(entry);
|
||||
type = typesFromEntry(entry, properties, mainType);
|
||||
if (udi.contains(QStringLiteral("IOBD")) || udi.contains(QStringLiteral("BD PX"))) {
|
||||
qWarning() << "Solid: BlueRay entry" << entry << "mainType=" << mainType << "typeList:" << type << "with properties" << properties;
|
||||
}
|
||||
if (mainType != Solid::DeviceInterface::Unknown) { }
|
||||
|
||||
IOObjectRelease(entry);
|
||||
}
|
||||
|
||||
IOKitDevice *IOKitDevicePrivate::getParentDevice()
|
||||
{
|
||||
if (!parentDevice) {
|
||||
parentDevice = new IOKitDevice(parentUdi);
|
||||
}
|
||||
return parentDevice;
|
||||
}
|
||||
|
||||
IOKitDevice::IOKitDevice(const QString &udi, const io_registry_entry_t &entry)
|
||||
: d(new IOKitDevicePrivate)
|
||||
{
|
||||
d->init(udi, entry);
|
||||
}
|
||||
|
||||
IOKitDevice::IOKitDevice(const QString &udi)
|
||||
: d(new IOKitDevicePrivate)
|
||||
{
|
||||
if (udi.isEmpty()) {
|
||||
qWarning() << Q_FUNC_INFO << "Tried to create Device from empty UDI";
|
||||
return;
|
||||
}
|
||||
|
||||
CFStringRef path = udi.toCFString();
|
||||
io_registry_entry_t entry = IORegistryEntryCopyFromPath(kIOMasterPortDefault, path);
|
||||
CFRelease(path);
|
||||
|
||||
if (entry == MACH_PORT_NULL) {
|
||||
qWarning() << Q_FUNC_INFO << "Tried to create Device from invalid UDI" << udi;
|
||||
return;
|
||||
}
|
||||
|
||||
d->init(udi, entry);
|
||||
}
|
||||
|
||||
IOKitDevice::IOKitDevice(const IOKitDevice &device)
|
||||
: d(new IOKitDevicePrivate)
|
||||
{
|
||||
if (device.udi().isEmpty()) {
|
||||
qWarning() << Q_FUNC_INFO << "Tried to create Device from empty UDI";
|
||||
return;
|
||||
}
|
||||
|
||||
CFStringRef path = device.udi().toCFString();
|
||||
io_registry_entry_t entry = IORegistryEntryCopyFromPath(kIOMasterPortDefault, path);
|
||||
CFRelease(path);
|
||||
|
||||
if (entry == MACH_PORT_NULL) {
|
||||
qWarning() << Q_FUNC_INFO << "Tried to create Device from invalid UDI" << device.udi();
|
||||
return;
|
||||
}
|
||||
|
||||
d->init(device.udi(), entry);
|
||||
}
|
||||
|
||||
IOKitDevice::~IOKitDevice()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
bool IOKitDevice::conformsToIOKitClass(const QString &className) const
|
||||
{
|
||||
bool conforms = false;
|
||||
if (!className.isEmpty()) {
|
||||
CFStringRef path = udi().toCFString();
|
||||
io_registry_entry_t entry = IORegistryEntryCopyFromPath(kIOMasterPortDefault, path);
|
||||
CFRelease(path);
|
||||
if (entry != MACH_PORT_NULL) {
|
||||
conforms = IOObjectConformsTo(entry, className.toLocal8Bit().constData());
|
||||
IOObjectRelease(entry);
|
||||
}
|
||||
}
|
||||
return conforms;
|
||||
}
|
||||
|
||||
QString IOKitDevice::udi() const
|
||||
{
|
||||
return d->udi;
|
||||
}
|
||||
|
||||
QString IOKitDevice::parentUdi() const
|
||||
{
|
||||
return d->parentUdi;
|
||||
}
|
||||
|
||||
QString IOKitDevice::vendor() const
|
||||
{
|
||||
if (parentUdi().isEmpty()) {
|
||||
return QStringLiteral("Apple");
|
||||
}
|
||||
switch (d->mainType) {
|
||||
case Solid::DeviceInterface::Processor:
|
||||
return Processor::vendor();
|
||||
break;
|
||||
case Solid::DeviceInterface::Battery:
|
||||
return property(QStringLiteral("Manufacturer")).toString();
|
||||
break;
|
||||
case Solid::DeviceInterface::StorageDrive:
|
||||
case Solid::DeviceInterface::OpticalDrive:
|
||||
case Solid::DeviceInterface::OpticalDisc:
|
||||
return IOKitStorage(this).vendor();
|
||||
break;
|
||||
case Solid::DeviceInterface::StorageVolume:
|
||||
return IOKitVolume(this).vendor();
|
||||
break;
|
||||
default:
|
||||
return QString();
|
||||
break;
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString IOKitDevice::product() const
|
||||
{
|
||||
if (parentUdi().isEmpty()) {
|
||||
return computerModel();
|
||||
}
|
||||
switch (d->mainType) {
|
||||
case Solid::DeviceInterface::Processor:
|
||||
return Processor::product();
|
||||
break;
|
||||
case Solid::DeviceInterface::Battery:
|
||||
return property(QStringLiteral("DeviceName")).toString();
|
||||
break;
|
||||
case Solid::DeviceInterface::StorageDrive:
|
||||
case Solid::DeviceInterface::OpticalDrive:
|
||||
case Solid::DeviceInterface::OpticalDisc:
|
||||
return IOKitStorage(this).product();
|
||||
break;
|
||||
case Solid::DeviceInterface::StorageVolume:
|
||||
return IOKitVolume(this).product();
|
||||
break;
|
||||
}
|
||||
return QString(); // TODO
|
||||
}
|
||||
|
||||
QString IOKitDevice::description() const
|
||||
{
|
||||
switch (d->mainType) {
|
||||
case Solid::DeviceInterface::Processor:
|
||||
return QStringLiteral("Processor");
|
||||
break;
|
||||
case Solid::DeviceInterface::Battery:
|
||||
return QStringLiteral("Apple Smart Battery");
|
||||
break;
|
||||
case Solid::DeviceInterface::StorageDrive:
|
||||
case Solid::DeviceInterface::OpticalDrive:
|
||||
case Solid::DeviceInterface::OpticalDisc:
|
||||
return IOKitStorage(this).description();
|
||||
break;
|
||||
case Solid::DeviceInterface::StorageVolume: {
|
||||
const QString volLabel = IOKitVolume(this).description();
|
||||
const QString mountPoint = IOKitStorageAccess(this).filePath();
|
||||
if (volLabel.isEmpty()) {
|
||||
return QUrl::fromLocalFile(mountPoint).fileName();
|
||||
} else if (mountPoint.startsWith(QStringLiteral("/Volumes/"))) {
|
||||
// Mac users will expect to see the name under which the volume is mounted here.
|
||||
return QString(QStringLiteral("%1 (%2)")).arg(QUrl::fromLocalFile(mountPoint).fileName()).arg(volLabel);
|
||||
}
|
||||
return volLabel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return product(); // TODO
|
||||
}
|
||||
|
||||
QString IOKitDevice::icon() const
|
||||
{
|
||||
// adapted from HalDevice::icon()
|
||||
if (parentUdi().isEmpty()) {
|
||||
if (computerModel().contains(QStringLiteral("MacBook"))) {
|
||||
return QStringLiteral("computer-laptop");
|
||||
} else {
|
||||
return QStringLiteral("computer");
|
||||
}
|
||||
|
||||
} else if (d->type.contains(Solid::DeviceInterface::StorageDrive)) {
|
||||
IOKitStorage drive(this);
|
||||
Solid::StorageDrive::DriveType driveType = drive.driveType();
|
||||
|
||||
switch (driveType) {
|
||||
case Solid::StorageDrive::Floppy:
|
||||
// why not :)
|
||||
return QStringLiteral("media-floppy");
|
||||
break;
|
||||
case Solid::StorageDrive::CdromDrive: {
|
||||
const IOKitOpticalDisc disc(this);
|
||||
if (disc.availableContent() == Solid::OpticalDisc::Audio) {
|
||||
return QStringLiteral("media-optical-audio");
|
||||
} else
|
||||
switch (disc.discType()) {
|
||||
case Solid::OpticalDisc::CdRom:
|
||||
return QStringLiteral("media-optical-data");
|
||||
break;
|
||||
case Solid::OpticalDisc::CdRecordable:
|
||||
case Solid::OpticalDisc::CdRewritable:
|
||||
return QStringLiteral("media-optical-recordable");
|
||||
break;
|
||||
case Solid::OpticalDisc::BluRayRom:
|
||||
case Solid::OpticalDisc::BluRayRecordable:
|
||||
case Solid::OpticalDisc::BluRayRewritable:
|
||||
return QStringLiteral("media-optical-blu-ray");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Solid::StorageDrive::SdMmc:
|
||||
return QStringLiteral("media-flash-sd-mmc");
|
||||
break;
|
||||
case Solid::StorageDrive::CompactFlash:
|
||||
return QStringLiteral("media-flash-cf");
|
||||
break;
|
||||
}
|
||||
if (drive.bus() == Solid::StorageDrive::Usb) {
|
||||
return QStringLiteral("drive-removable-media-usb");
|
||||
}
|
||||
if (drive.isRemovable()) {
|
||||
return QStringLiteral("drive-removable-media");
|
||||
}
|
||||
return QStringLiteral("drive-harddisk");
|
||||
|
||||
} else if (d->mainType == Solid::DeviceInterface::StorageVolume) {
|
||||
} else if (d->mainType == Solid::DeviceInterface::Battery) {
|
||||
return QStringLiteral("battery");
|
||||
} else if (d->mainType == Solid::DeviceInterface::Processor) {
|
||||
return QStringLiteral("cpu"); // FIXME: Doesn't follow icon spec
|
||||
} else {
|
||||
QString iconName = d->getParentDevice()->icon();
|
||||
|
||||
if (!iconName.isEmpty()) {
|
||||
return iconName;
|
||||
}
|
||||
|
||||
return QStringLiteral("drive-harddisk");
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QStringList IOKitDevice::emblems() const
|
||||
{
|
||||
return QStringList(); // TODO
|
||||
}
|
||||
|
||||
QVariant IOKitDevice::property(const QString &key) const
|
||||
{
|
||||
if (!d->properties.contains(key)) {
|
||||
return QObject::property(key.toUtf8().constData());
|
||||
}
|
||||
return d->properties.value(key);
|
||||
}
|
||||
|
||||
QMap<QString, QVariant> IOKitDevice::allProperties() const
|
||||
{
|
||||
return d->properties;
|
||||
}
|
||||
|
||||
bool IOKitDevice::iOKitPropertyExists(const QString &key) const
|
||||
{
|
||||
return d->properties.contains(key);
|
||||
}
|
||||
|
||||
bool IOKitDevice::queryDeviceInterface(const Solid::DeviceInterface::Type &type) const
|
||||
{
|
||||
switch (type) {
|
||||
case Solid::DeviceInterface::GenericInterface:
|
||||
return true;
|
||||
break;
|
||||
case Solid::DeviceInterface::StorageAccess:
|
||||
if (d->type.contains(Solid::DeviceInterface::StorageDrive) //
|
||||
|| d->type.contains(Solid::DeviceInterface::StorageVolume)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return d->type.contains(type);
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QObject *IOKitDevice::createDeviceInterface(const Solid::DeviceInterface::Type &type)
|
||||
{
|
||||
QObject *iface = nullptr;
|
||||
|
||||
switch (type) {
|
||||
case Solid::DeviceInterface::GenericInterface:
|
||||
iface = new GenericInterface(this);
|
||||
break;
|
||||
case Solid::DeviceInterface::Processor:
|
||||
if (d->type.contains(Solid::DeviceInterface::Processor)) {
|
||||
iface = new Processor(this);
|
||||
}
|
||||
break;
|
||||
case Solid::DeviceInterface::Battery:
|
||||
if (d->type.contains(Solid::DeviceInterface::Battery)) {
|
||||
iface = new Battery(this);
|
||||
}
|
||||
break;
|
||||
case Solid::DeviceInterface::OpticalDrive:
|
||||
if (d->type.contains(Solid::DeviceInterface::OpticalDrive)) {
|
||||
iface = new IOKitOpticalDrive(this);
|
||||
}
|
||||
break;
|
||||
case Solid::DeviceInterface::OpticalDisc:
|
||||
if (d->type.contains(Solid::DeviceInterface::OpticalDisc)) {
|
||||
iface = new IOKitOpticalDisc(this);
|
||||
}
|
||||
break;
|
||||
case Solid::DeviceInterface::StorageDrive:
|
||||
if (d->type.contains(Solid::DeviceInterface::StorageDrive)) {
|
||||
iface = new IOKitStorage(this);
|
||||
}
|
||||
break;
|
||||
case Solid::DeviceInterface::Block:
|
||||
if (d->type.contains(Solid::DeviceInterface::OpticalDisc)) {
|
||||
iface = new IOKitOpticalDisc(this);
|
||||
} else if (d->type.contains(Solid::DeviceInterface::OpticalDrive)) {
|
||||
iface = new IOKitOpticalDrive(this);
|
||||
} else if (d->type.contains(Solid::DeviceInterface::StorageVolume)) {
|
||||
iface = new IOKitVolume(this);
|
||||
} else if (d->type.contains(Solid::DeviceInterface::StorageDrive)) {
|
||||
iface = new IOKitStorage(this);
|
||||
}
|
||||
break;
|
||||
case Solid::DeviceInterface::StorageVolume:
|
||||
if (d->type.contains(Solid::DeviceInterface::StorageVolume)) {
|
||||
iface = new IOKitVolume(this);
|
||||
}
|
||||
break;
|
||||
case Solid::DeviceInterface::StorageAccess:
|
||||
if (d->type.contains(Solid::DeviceInterface::StorageDrive) //
|
||||
|| d->type.contains(Solid::DeviceInterface::StorageVolume)) {
|
||||
iface = new IOKitStorageAccess(this);
|
||||
}
|
||||
break;
|
||||
// the rest is TODO
|
||||
}
|
||||
|
||||
return iface;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // namespaces
|
||||
|
||||
#include "moc_iokitdevice.cpp"
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Harald Fernengel <harry@kdevelop.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_IOKIT_IOKITDEVICE_H
|
||||
#define SOLID_BACKENDS_IOKIT_IOKITDEVICE_H
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <solid/devices/ifaces/device.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace IOKit
|
||||
{
|
||||
class IOKitDevicePrivate;
|
||||
class IOKitManager;
|
||||
|
||||
class IOKitDevice : public Solid::Ifaces::Device
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
IOKitDevice(const QString &udi);
|
||||
IOKitDevice(const IOKitDevice &device);
|
||||
virtual ~IOKitDevice();
|
||||
|
||||
QString udi() const override;
|
||||
QString parentUdi() const override;
|
||||
|
||||
QString vendor() const override;
|
||||
QString product() const override;
|
||||
QString icon() const override;
|
||||
QStringList emblems() const override;
|
||||
QString description() const override;
|
||||
|
||||
virtual QVariant property(const QString &key) const;
|
||||
|
||||
virtual QMap<QString, QVariant> allProperties() const;
|
||||
|
||||
virtual bool iOKitPropertyExists(const QString &key) const;
|
||||
|
||||
bool queryDeviceInterface(const Solid::DeviceInterface::Type &type) const override;
|
||||
QObject *createDeviceInterface(const Solid::DeviceInterface::Type &type) override;
|
||||
|
||||
bool conformsToIOKitClass(const QString &className) const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void propertyChanged(const QMap<QString, int> &changes);
|
||||
void conditionRaised(const QString &condition, const QString &reason);
|
||||
|
||||
private:
|
||||
friend class IOKitManager;
|
||||
IOKitDevice(const QString &udi, const io_registry_entry_t &entry);
|
||||
IOKitDevicePrivate *const d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_IOKIT_IOKITDEVICE_H
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Harald Fernengel <harry@kdevelop.org>
|
||||
SPDX-FileCopyrightText: 2017 René J.V. Bertin <rjvbertin@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "iokitdeviceinterface.h"
|
||||
|
||||
using namespace Solid::Backends::IOKit;
|
||||
|
||||
DeviceInterface::DeviceInterface(IOKitDevice *device)
|
||||
: QObject(device)
|
||||
, m_device(device)
|
||||
, m_deviceCopy(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
DeviceInterface::DeviceInterface(const IOKitDevice *device)
|
||||
: QObject(device->parent())
|
||||
, m_deviceCopy(new IOKitDevice(*device))
|
||||
{
|
||||
m_device = m_deviceCopy;
|
||||
}
|
||||
|
||||
DeviceInterface::~DeviceInterface()
|
||||
{
|
||||
if (m_deviceCopy) {
|
||||
delete m_deviceCopy;
|
||||
m_deviceCopy = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_iokitdeviceinterface.cpp"
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Harald Fernengel <harry@kdevelop.org>
|
||||
SPDX-FileCopyrightText: 2017 René J.V. Bertin <rjvbertin@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_IOKIT_DEVICEINTERFACE_H
|
||||
#define SOLID_BACKENDS_IOKIT_DEVICEINTERFACE_H
|
||||
|
||||
#include "iokitdevice.h"
|
||||
#include <solid/devices/ifaces/deviceinterface.h>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace IOKit
|
||||
{
|
||||
class DeviceInterface : public QObject, virtual public Solid::Ifaces::DeviceInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::DeviceInterface)
|
||||
public:
|
||||
DeviceInterface(IOKitDevice *device);
|
||||
// the ctor taking a const device* argument makes a deep
|
||||
// copy of the IOKitDevice; any property changes made via
|
||||
// the resulting instance will not affect the original device.
|
||||
DeviceInterface(const IOKitDevice *device);
|
||||
virtual ~DeviceInterface();
|
||||
|
||||
protected:
|
||||
IOKitDevice *m_device;
|
||||
IOKitDevice *m_deviceCopy;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_IOKIT_DEVICEINTERFACE_H
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Harald Fernengel <harry@kdevelop.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "iokitgenericinterface.h"
|
||||
|
||||
#include "iokitdevice.h"
|
||||
|
||||
using namespace Solid::Backends::IOKit;
|
||||
|
||||
GenericInterface::GenericInterface(IOKitDevice *device)
|
||||
: DeviceInterface(device)
|
||||
{
|
||||
}
|
||||
|
||||
GenericInterface::~GenericInterface()
|
||||
{
|
||||
}
|
||||
|
||||
QVariant GenericInterface::property(const QString &key) const
|
||||
{
|
||||
return m_device->property(key);
|
||||
}
|
||||
|
||||
QMap<QString, QVariant> GenericInterface::allProperties() const
|
||||
{
|
||||
return m_device->allProperties();
|
||||
}
|
||||
|
||||
bool GenericInterface::propertyExists(const QString &key) const
|
||||
{
|
||||
return m_device->iOKitPropertyExists(key);
|
||||
}
|
||||
|
||||
#include "moc_iokitgenericinterface.cpp"
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Harald Fernengel <harry@kdevelop.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_IOKIT_GENERICINTERFACE_H
|
||||
#define SOLID_BACKENDS_IOKIT_GENERICINTERFACE_H
|
||||
|
||||
#include "iokitdeviceinterface.h"
|
||||
#include <solid/devices/ifaces/genericinterface.h>
|
||||
#include <solid/genericinterface.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace IOKit
|
||||
{
|
||||
class IOKitDevice;
|
||||
|
||||
class GenericInterface : public DeviceInterface, virtual public Solid::Ifaces::GenericInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::GenericInterface)
|
||||
|
||||
public:
|
||||
GenericInterface(IOKitDevice *device);
|
||||
virtual ~GenericInterface();
|
||||
|
||||
virtual QVariant property(const QString &key) const;
|
||||
virtual QMap<QString, QVariant> allProperties() const;
|
||||
virtual bool propertyExists(const QString &key) const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void propertyChanged(const QMap<QString, int> &changes);
|
||||
void conditionRaised(const QString &condition, const QString &reason);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_IOKIT_GENERICINTERFACE_H
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Harald Fernengel <harry@kdevelop.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "iokitmanager.h"
|
||||
#include "iokitdevice.h"
|
||||
|
||||
#include <qdebug.h>
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/network/IOEthernetInterface.h>
|
||||
#include <IOKit/usb/IOUSBLib.h>
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
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<Solid::DeviceInterface::Type> supportedInterfaces;
|
||||
};
|
||||
|
||||
// gets all registry paths from an iterator
|
||||
QStringList IOKitManagerPrivate::devicesFromRegistry(io_iterator_t it)
|
||||
{
|
||||
QStringList result;
|
||||
io_object_t obj;
|
||||
while ((obj = IOIteratorNext(it))) {
|
||||
CFStringRef pathRef = IORegistryEntryCopyPath(obj, kIOServicePlane);
|
||||
const QString path = QString::fromCFString(pathRef);
|
||||
CFRelease(pathRef);
|
||||
|
||||
if (path.isEmpty()) {
|
||||
qWarning() << Q_FUNC_INFO << "IORegistryEntryCopyPath failed";
|
||||
continue;
|
||||
}
|
||||
result += path;
|
||||
const kern_return_t 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);
|
||||
// clang-format off
|
||||
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;
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
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<Solid::DeviceInterface::Type> 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;
|
||||
for (const QString &udi : std::as_const(result)) {
|
||||
if (udi.startsWith(parentUdi)) {
|
||||
filtered += udi;
|
||||
}
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
QObject *IOKitManager::createDevice(const QString &udi)
|
||||
{
|
||||
CFStringRef path = udi.toCFString();
|
||||
io_registry_entry_t entry = IORegistryEntryCopyFromPath(kIOMasterPortDefault, path);
|
||||
CFRelease(path);
|
||||
|
||||
// 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
|
||||
|
||||
#include "moc_iokitmanager.cpp"
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Harald Fernengel <harry@kdevelop.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_IOKIT_IOKITMANAGER_H
|
||||
#define SOLID_BACKENDS_IOKIT_IOKITMANAGER_H
|
||||
|
||||
#include <solid/deviceinterface.h>
|
||||
#include <solid/devices/ifaces/devicemanager.h>
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace IOKit
|
||||
{
|
||||
class IOKitManagerPrivate;
|
||||
|
||||
class IOKitManager : public Solid::Ifaces::DeviceManager
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
IOKitManager(QObject *parent);
|
||||
virtual ~IOKitManager();
|
||||
|
||||
virtual QString udiPrefix() const;
|
||||
virtual QSet<Solid::DeviceInterface::Type> supportedInterfaces() const;
|
||||
|
||||
virtual QStringList allDevices();
|
||||
virtual QStringList devicesFromQuery(const QString &parentUdi, Solid::DeviceInterface::Type type);
|
||||
virtual QObject *createDevice(const QString &udi);
|
||||
|
||||
private:
|
||||
IOKitManagerPrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_IOKIT_IOKITMANAGER_H
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2006 Kevin Ottens <ervin@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "iokitopticaldisc.h"
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
using namespace Solid::Backends::IOKit;
|
||||
|
||||
IOKitOpticalDisc::IOKitOpticalDisc(IOKitDevice *device)
|
||||
: IOKitVolume(device)
|
||||
{
|
||||
}
|
||||
|
||||
IOKitOpticalDisc::IOKitOpticalDisc(const IOKitDevice *device)
|
||||
: IOKitVolume(device)
|
||||
{
|
||||
}
|
||||
|
||||
IOKitOpticalDisc::~IOKitOpticalDisc()
|
||||
{
|
||||
}
|
||||
|
||||
QString IOKitOpticalDisc::device() const
|
||||
{
|
||||
const QString devName = m_device->property(QLatin1String("BSD Name")).toString();
|
||||
if (devName.startsWith(QLatin1Char('r'))) {
|
||||
return QStringLiteral("/dev/") + devName;
|
||||
} else {
|
||||
return QStringLiteral("/dev/r") + devName;
|
||||
}
|
||||
}
|
||||
|
||||
Solid::OpticalDisc::ContentTypes IOKitOpticalDisc::availableContent() const
|
||||
{
|
||||
if (fsType() == QStringLiteral("cddafs")) {
|
||||
return Solid::OpticalDisc::Audio;
|
||||
}
|
||||
return Solid::OpticalDisc::Data;
|
||||
}
|
||||
|
||||
Solid::OpticalDisc::DiscType IOKitOpticalDisc::discType() const
|
||||
{
|
||||
QString type = m_device->property(QStringLiteral("Type")).toString();
|
||||
|
||||
if (type == QLatin1String("CD-ROM")) {
|
||||
return Solid::OpticalDisc::CdRom;
|
||||
} else if (type == QLatin1String("CD-R")) {
|
||||
return Solid::OpticalDisc::CdRecordable;
|
||||
} else if (type == QLatin1String("CD-RW")) {
|
||||
return Solid::OpticalDisc::CdRewritable;
|
||||
} else if (type == QLatin1String("DVD-ROM")) {
|
||||
return Solid::OpticalDisc::DvdRom;
|
||||
} else if (type == QLatin1String("DVD-RAM")) {
|
||||
return Solid::OpticalDisc::DvdRam;
|
||||
} else if (type == QLatin1String("DVD-R")) {
|
||||
return Solid::OpticalDisc::DvdRecordable;
|
||||
} else if (type == QLatin1String("DVD-RW")) {
|
||||
return Solid::OpticalDisc::DvdRewritable;
|
||||
} else if (type == QLatin1String("DVD+R")) {
|
||||
return Solid::OpticalDisc::DvdPlusRecordable;
|
||||
} else if (type == QLatin1String("DVD+RW")) {
|
||||
return Solid::OpticalDisc::DvdPlusRewritable;
|
||||
} else if (type == QLatin1String("BD-ROM")) {
|
||||
return Solid::OpticalDisc::BluRayRom;
|
||||
} else if (type == QLatin1String("BD-R")) {
|
||||
return Solid::OpticalDisc::BluRayRecordable;
|
||||
} else if (type == QLatin1String("BD-RE")) {
|
||||
return Solid::OpticalDisc::BluRayRewritable;
|
||||
} else if (type == QLatin1String("HD DVD-ROM")) {
|
||||
return Solid::OpticalDisc::HdDvdRom;
|
||||
} else if (type == QLatin1String("HD DVD-R")) {
|
||||
return Solid::OpticalDisc::HdDvdRecordable;
|
||||
} else if (type == QLatin1String("HD DVD-RW")) {
|
||||
return Solid::OpticalDisc::HdDvdRewritable;
|
||||
} else {
|
||||
return Solid::OpticalDisc::UnknownDiscType;
|
||||
}
|
||||
}
|
||||
|
||||
bool IOKitOpticalDisc::isAppendable() const
|
||||
{
|
||||
// TODO!
|
||||
return isRewritable();
|
||||
}
|
||||
|
||||
bool IOKitOpticalDisc::isBlank() const
|
||||
{
|
||||
// TODO!
|
||||
return isRewritable();
|
||||
}
|
||||
|
||||
bool IOKitOpticalDisc::isRewritable() const
|
||||
{
|
||||
return m_device->property(QStringLiteral("Writable")).toBool();
|
||||
}
|
||||
|
||||
qulonglong IOKitOpticalDisc::capacity() const
|
||||
{
|
||||
return size();
|
||||
}
|
||||
|
||||
#include "moc_iokitopticaldisc.cpp"
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2017 René J.V. Bertin <rjvbertin@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_IOKIT_OPTICALDISC_H
|
||||
#define SOLID_BACKENDS_IOKIT_OPTICALDISC_H
|
||||
|
||||
#include "iokitvolume.h"
|
||||
#include <solid/devices/ifaces/opticaldisc.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace IOKit
|
||||
{
|
||||
class IOKitOpticalDisc : public IOKitVolume, virtual public Solid::Ifaces::OpticalDisc
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::OpticalDisc)
|
||||
|
||||
public:
|
||||
IOKitOpticalDisc(IOKitDevice *device);
|
||||
IOKitOpticalDisc(const IOKitDevice *device);
|
||||
virtual ~IOKitOpticalDisc();
|
||||
|
||||
// overridden from IOKit::Block because optical discs must
|
||||
// be accessed through the raw device.
|
||||
QString device() const override;
|
||||
|
||||
Solid::OpticalDisc::ContentTypes availableContent() const override;
|
||||
Solid::OpticalDisc::DiscType discType() const override;
|
||||
bool isAppendable() const override;
|
||||
bool isBlank() const override;
|
||||
bool isRewritable() const override;
|
||||
qulonglong capacity() const override;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_IOKIT_OPTICALDISC_H
|
||||
+343
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2017 René J.V. Bertin <rjvbertin@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "iokitopticaldrive.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QProcess>
|
||||
|
||||
#ifdef EJECT_USING_DISKARBITRATION
|
||||
// for QCFType:
|
||||
#include <private/qcore_mac_p.h>
|
||||
#else
|
||||
#include <QStandardPaths>
|
||||
#endif
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <DiskArbitration/DiskArbitration.h>
|
||||
#include <IOKit/scsi/IOSCSIMultimediaCommandsDevice.h>
|
||||
|
||||
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<Solid::OpticalDrive::MediumType, uint32_t> cdTypeMap;
|
||||
static const QMap<Solid::OpticalDrive::MediumType, uint32_t> dvdTypeMap;
|
||||
static const QMap<Solid::OpticalDrive::MediumType, uint32_t> 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-hardware6 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<DAContext *>(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<CFRunLoopSourceRef> cancel = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &cancelRunLoopSourceContext);
|
||||
if (!(daContext.cancel_signal = cancel)) {
|
||||
qWarning() << Q_FUNC_INFO << "failed to create cancel runloop source";
|
||||
return false;
|
||||
}
|
||||
QCFType<DASessionRef> 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<DADiskRef> 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<Solid::OpticalDrive::MediumType, uint32_t> IOKitOpticalDrive::Private::cdTypeMap = {
|
||||
{Solid::OpticalDrive::Cdr, kCDFeaturesWriteOnceMask},
|
||||
{Solid::OpticalDrive::Cdrw, kCDFeaturesReWriteableMask},
|
||||
};
|
||||
const QMap<Solid::OpticalDrive::MediumType, uint32_t> 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<Solid::OpticalDrive::MediumType, uint32_t> 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()
|
||||
{
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
// // 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")))
|
||||
/* clang-format on */
|
||||
|
||||
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;
|
||||
|
||||
for (auto it = d->cdTypeMap.cbegin(); it != d->cdTypeMap.cend(); ++it) {
|
||||
if (cdFeatures & it.value()) {
|
||||
supported |= it.key();
|
||||
}
|
||||
}
|
||||
for (auto it = d->dvdTypeMap.cbegin(); it != d->dvdTypeMap.cend(); ++it) {
|
||||
if (dvdFeatures & it.value()) {
|
||||
supported |= it.key();
|
||||
}
|
||||
}
|
||||
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<int> 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) {
|
||||
Q_EMIT ejectDone(Solid::ErrorType::OperationFailed, QVariant(), m_device->udi());
|
||||
return false;
|
||||
} else {
|
||||
Q_EMIT ejectDone(Solid::ErrorType::NoError, QVariant(), m_device->udi());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_iokitopticaldrive.cpp"
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2017 René J.V. Bertin <rjvbertin@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_IOKIT_OPTICALDRIVE_H
|
||||
#define SOLID_BACKENDS_IOKIT_OPTICALDRIVE_H
|
||||
|
||||
#include "iokitstorage.h"
|
||||
#include <solid/devices/ifaces/opticaldrive.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace IOKit
|
||||
{
|
||||
class IOKitOpticalDrive : public IOKitStorage, virtual public Solid::Ifaces::OpticalDrive
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::OpticalDrive)
|
||||
|
||||
public:
|
||||
explicit IOKitOpticalDrive(IOKitDevice *device);
|
||||
virtual ~IOKitOpticalDrive();
|
||||
|
||||
public Q_SLOTS:
|
||||
Solid::OpticalDrive::MediumTypes supportedMedia() const override;
|
||||
int readSpeed() const override;
|
||||
int writeSpeed() const override;
|
||||
QList<int> writeSpeeds() const override;
|
||||
bool eject() override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void ejectPressed(const QString &udi) override;
|
||||
void ejectDone(Solid::ErrorType error, QVariant errorData, const QString &udi) override;
|
||||
void ejectRequested(const QString &udi);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_IOKIT_OPTICALDRIVE_H
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Harald Fernengel <harry@kdevelop.org>
|
||||
SPDX-FileCopyrightText: 2017 René J.V. Bertin <rjvbertin@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "iokitprocessor.h"
|
||||
#include "iokitdevice.h"
|
||||
|
||||
#include <qdebug.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "../shared/cpufeatures.h"
|
||||
|
||||
// from cfhelper.cpp
|
||||
extern bool q_sysctlbyname(const char *name, QString &result);
|
||||
|
||||
using namespace Solid::Backends::IOKit;
|
||||
|
||||
Processor::Processor(IOKitDevice *device)
|
||||
: DeviceInterface(device)
|
||||
{
|
||||
// IOKitDevice parent(device->parentUdi());
|
||||
}
|
||||
|
||||
Processor::~Processor()
|
||||
{
|
||||
}
|
||||
|
||||
int Processor::number() const
|
||||
{
|
||||
return m_device->property(QLatin1String("IOCPUNumber")).toInt();
|
||||
}
|
||||
|
||||
int Processor::maxSpeed() const
|
||||
{
|
||||
uint64_t freq = 0;
|
||||
size_t size = sizeof(freq);
|
||||
|
||||
if (sysctlbyname("hw.cpufrequency", &freq, &size, nullptr, 0) < 0) {
|
||||
qWarning() << "sysctl error reading hw.cpufrequency:" << strerror(errno);
|
||||
return 0;
|
||||
} else {
|
||||
return int(freq / 1000000);
|
||||
}
|
||||
}
|
||||
|
||||
bool Processor::canChangeFrequency() const
|
||||
{
|
||||
uint64_t minFreq = 0, maxFreq = 0;
|
||||
size_t size = sizeof(uint64_t);
|
||||
|
||||
if (sysctlbyname("hw.cpufrequency_min", &minFreq, &size, nullptr, 0) == 0 //
|
||||
&& sysctlbyname("hw.cpufrequency_max", &maxFreq, &size, nullptr, 0) == 0) {
|
||||
return maxFreq > minFreq;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Solid::Processor::InstructionSets Processor::instructionSets() const
|
||||
{
|
||||
// use sysctlbyname() and "machdep.cpu.features" + "machdep.cpu.extfeatures"
|
||||
static Solid::Processor::InstructionSets cpuextensions = Solid::Backends::Shared::cpuFeatures();
|
||||
|
||||
return cpuextensions;
|
||||
}
|
||||
|
||||
QString Processor::vendor()
|
||||
{
|
||||
QString qVendor;
|
||||
q_sysctlbyname("machdep.cpu.vendor", qVendor);
|
||||
return qVendor;
|
||||
}
|
||||
|
||||
QString Processor::product()
|
||||
{
|
||||
QString product;
|
||||
q_sysctlbyname("machdep.cpu.brand_string", product);
|
||||
return product;
|
||||
}
|
||||
|
||||
#include "moc_iokitprocessor.cpp"
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Harald Fernengel <harry@kdevelop.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_IOKIT_PROCESSOR_H
|
||||
#define SOLID_BACKENDS_IOKIT_PROCESSOR_H
|
||||
|
||||
#include "iokitdeviceinterface.h"
|
||||
#include <solid/devices/ifaces/processor.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace IOKit
|
||||
{
|
||||
class IOKitDevice;
|
||||
|
||||
class Processor : public DeviceInterface, virtual public Solid::Ifaces::Processor
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::Processor)
|
||||
|
||||
public:
|
||||
Processor(IOKitDevice *device);
|
||||
virtual ~Processor();
|
||||
|
||||
int number() const override;
|
||||
int maxSpeed() const override;
|
||||
bool canChangeFrequency() const override;
|
||||
Solid::Processor::InstructionSets instructionSets() const override;
|
||||
static QString vendor();
|
||||
static QString product();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_IOKIT_PROCESSOR_H
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2017 René J.V. Bertin <rjvbertin@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "iokitstorage.h"
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <DiskArbitration/DiskArbitration.h>
|
||||
|
||||
using namespace Solid::Backends::IOKit;
|
||||
|
||||
IOKitStorage::IOKitStorage(IOKitDevice *device)
|
||||
: Block(device)
|
||||
, daDict(new DADictionary(device))
|
||||
{
|
||||
}
|
||||
|
||||
IOKitStorage::IOKitStorage(const IOKitDevice *device)
|
||||
: Block(device)
|
||||
, daDict(new DADictionary(device))
|
||||
{
|
||||
}
|
||||
|
||||
IOKitStorage::~IOKitStorage()
|
||||
{
|
||||
delete daDict;
|
||||
}
|
||||
|
||||
Solid::StorageDrive::Bus IOKitStorage::bus() const
|
||||
{
|
||||
const QString udi = m_device->udi();
|
||||
// TODO: figure out how to return something useful here.
|
||||
if (udi.contains(QStringLiteral("/SATA@"))) {
|
||||
return Solid::StorageDrive::Sata;
|
||||
}
|
||||
if (udi.contains(QStringLiteral("/SDXC@"))) {
|
||||
// TODO: return something finer grained; the built-in card reader
|
||||
// is NOT connected via USB on Macs, for instance (but there's no PCI option)
|
||||
return Solid::StorageDrive::Usb;
|
||||
}
|
||||
if (udi.contains(QStringLiteral("/IOUSBInterface@"))) {
|
||||
return Solid::StorageDrive::Usb;
|
||||
}
|
||||
if (daDict->stringForKey(kDADiskDescriptionDeviceProtocolKey) == QStringLiteral("USB")) {
|
||||
return Solid::StorageDrive::Usb;
|
||||
}
|
||||
return Solid::StorageDrive::Platform;
|
||||
}
|
||||
|
||||
Solid::StorageDrive::DriveType IOKitStorage::driveType() const
|
||||
{
|
||||
const QString udi = m_device->udi();
|
||||
const QString type = m_device->property(QLatin1String("className")).toString();
|
||||
|
||||
if (type == QStringLiteral("IOCDMedia") //
|
||||
|| type == QStringLiteral("IOBDMedia") //
|
||||
|| type == QStringLiteral("IODVDMedia")) {
|
||||
return Solid::StorageDrive::CdromDrive;
|
||||
}
|
||||
if (udi.contains(QStringLiteral("/SDXC@"))) {
|
||||
return Solid::StorageDrive::SdMmc;
|
||||
}
|
||||
if (daDict->stringForKey(kDADiskDescriptionDeviceModelKey) == QStringLiteral("Compact Flash")) {
|
||||
return Solid::StorageDrive::CompactFlash;
|
||||
}
|
||||
return Solid::StorageDrive::HardDisk;
|
||||
}
|
||||
|
||||
bool IOKitStorage::isRemovable() const
|
||||
{
|
||||
bool isInternal = false;
|
||||
daDict->boolForKey(kDADiskDescriptionDeviceInternalKey, isInternal);
|
||||
return !isInternal || m_device->property(QLatin1String("Removable")).toBool();
|
||||
}
|
||||
|
||||
bool IOKitStorage::isHotpluggable() const
|
||||
{
|
||||
const Solid::StorageDrive::DriveType type = driveType();
|
||||
return bus() == Solid::StorageDrive::Usb //
|
||||
|| type == Solid::StorageDrive::CdromDrive //
|
||||
|| type == Solid::StorageDrive::SdMmc;
|
||||
}
|
||||
|
||||
qulonglong IOKitStorage::size() const
|
||||
{
|
||||
return m_device->property(QLatin1String("Size")).toULongLong();
|
||||
}
|
||||
|
||||
QString IOKitStorage::vendor() const
|
||||
{
|
||||
return daDict->stringForKey(kDADiskDescriptionDeviceVendorKey);
|
||||
}
|
||||
|
||||
QString IOKitStorage::product() const
|
||||
{
|
||||
return daDict->stringForKey(kDADiskDescriptionDeviceModelKey);
|
||||
}
|
||||
|
||||
QString IOKitStorage::description() const
|
||||
{
|
||||
return daDict->stringForKey(kDADiskDescriptionMediaNameKey);
|
||||
}
|
||||
|
||||
#include "moc_iokitstorage.cpp"
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2017 René J.V. Bertin <rjvbertin@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_IOKIT_IOKITSTORAGE_H
|
||||
#define SOLID_BACKENDS_IOKIT_IOKITSTORAGE_H
|
||||
|
||||
#include "dadictionary_p.h"
|
||||
#include "iokitblock.h"
|
||||
|
||||
#include <solid/devices/ifaces/storagedrive.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace IOKit
|
||||
{
|
||||
class IOKitStorage : public Block, virtual public Solid::Ifaces::StorageDrive
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::StorageDrive)
|
||||
|
||||
public:
|
||||
explicit IOKitStorage(IOKitDevice *device);
|
||||
explicit IOKitStorage(const IOKitDevice *device);
|
||||
~IOKitStorage();
|
||||
|
||||
QString vendor() const;
|
||||
QString product() const;
|
||||
QString description() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
Solid::StorageDrive::Bus bus() const override;
|
||||
Solid::StorageDrive::DriveType driveType() const override;
|
||||
|
||||
bool isRemovable() const override;
|
||||
bool isHotpluggable() const override;
|
||||
qulonglong size() const override;
|
||||
|
||||
private:
|
||||
DADictionary *daDict;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_IOKIT_IOKITSTORAGE_H
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2017 René J.V. Bertin <rjvbertin@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "iokitstorageaccess.h"
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <DiskArbitration/DiskArbitration.h>
|
||||
|
||||
using namespace Solid::Backends::IOKit;
|
||||
|
||||
IOKitStorageAccess::IOKitStorageAccess(IOKitDevice *device)
|
||||
: DeviceInterface(device)
|
||||
, daDict(new DADictionary(device))
|
||||
{
|
||||
connect(device, SIGNAL(propertyChanged(QMap<QString, int>)), this, SLOT(onPropertyChanged(QMap<QString, int>)));
|
||||
}
|
||||
|
||||
IOKitStorageAccess::IOKitStorageAccess(const IOKitDevice *device)
|
||||
: DeviceInterface(device)
|
||||
, daDict(new DADictionary(device))
|
||||
{
|
||||
connect(device, SIGNAL(propertyChanged(QMap<QString, int>)), this, SLOT(onPropertyChanged(QMap<QString, int>)));
|
||||
}
|
||||
|
||||
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<QString, int>{{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::isEncrypted() const
|
||||
{
|
||||
// TODO: Implementation left for IOKit developer
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IOKitStorageAccess::setup()
|
||||
{
|
||||
// TODO?
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IOKitStorageAccess::teardown()
|
||||
{
|
||||
// TODO?
|
||||
return false;
|
||||
}
|
||||
|
||||
void IOKitStorageAccess::onPropertyChanged(const QMap<QString, int> &changes)
|
||||
{
|
||||
for (auto it = changes.cbegin(); it != changes.cend(); ++it) {
|
||||
if (it.key() == QLatin1String("isMounted")) {
|
||||
Q_EMIT accessibilityChanged(m_device->property(QStringLiteral("isMounted")).toBool(), m_device->udi());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_iokitstorageaccess.cpp"
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2017 René J.V. Bertin <rjvbertin@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_IOKIT_STORAGEACCESS_H
|
||||
#define SOLID_BACKENDS_IOKIT_STORAGEACCESS_H
|
||||
|
||||
#include "dadictionary_p.h"
|
||||
#include "iokitdeviceinterface.h"
|
||||
#include <solid/devices/ifaces/storageaccess.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace IOKit
|
||||
{
|
||||
class IOKitStorageAccess : public DeviceInterface, virtual public Solid::Ifaces::StorageAccess
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::StorageAccess)
|
||||
|
||||
public:
|
||||
IOKitStorageAccess(IOKitDevice *device);
|
||||
IOKitStorageAccess(const IOKitDevice *device);
|
||||
virtual ~IOKitStorageAccess();
|
||||
|
||||
bool isAccessible() const override;
|
||||
QString filePath() const override;
|
||||
bool isIgnored() const override;
|
||||
bool isEncrypted() const override;
|
||||
public Q_SLOTS:
|
||||
bool setup() override;
|
||||
bool teardown() override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void accessibilityChanged(bool accessible, const QString &udi) override;
|
||||
void setupDone(Solid::ErrorType error, QVariant errorData, const QString &udi) override;
|
||||
void teardownDone(Solid::ErrorType error, QVariant errorData, const QString &udi) override;
|
||||
void setupRequested(const QString &udi) override;
|
||||
void teardownRequested(const QString &udi) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void onPropertyChanged(const QMap<QString, int> &changes);
|
||||
|
||||
private:
|
||||
DADictionary *daDict;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_IOKIT_STORAGEACCESS_H
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2017 René J.V. Bertin <rjvbertin@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "iokitvolume.h"
|
||||
#include "iokitgenericinterface.h"
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
using namespace Solid::Backends::IOKit;
|
||||
|
||||
IOKitVolume::IOKitVolume(IOKitDevice *device)
|
||||
: Block(device)
|
||||
, daDict(new DADictionary(device))
|
||||
{
|
||||
}
|
||||
|
||||
IOKitVolume::IOKitVolume(const IOKitDevice *device)
|
||||
: Block(device)
|
||||
, daDict(new DADictionary(device))
|
||||
{
|
||||
}
|
||||
|
||||
IOKitVolume::~IOKitVolume()
|
||||
{
|
||||
delete daDict;
|
||||
}
|
||||
|
||||
bool IOKitVolume::isIgnored() const
|
||||
{
|
||||
// ignore storage volumes that aren't mounted
|
||||
bool isIgnored = m_device->property(QStringLiteral("Open")).toBool() == false;
|
||||
m_device->setProperty("isIgnored", isIgnored);
|
||||
m_device->setProperty("isMounted", !isIgnored);
|
||||
return isIgnored;
|
||||
}
|
||||
|
||||
Solid::StorageVolume::UsageType IOKitVolume::usage() const
|
||||
{
|
||||
const QString content = m_device->property(QStringLiteral("Content")).toString();
|
||||
if (content == QStringLiteral("CD_DA")) {
|
||||
// this is (probably) a CD track
|
||||
return Solid::StorageVolume::Other;
|
||||
}
|
||||
if (content.contains(QStringLiteral("partition_scheme"))) {
|
||||
return Solid::StorageVolume::PartitionTable;
|
||||
}
|
||||
return Solid::StorageVolume::FileSystem;
|
||||
}
|
||||
|
||||
QString IOKitVolume::fsType() const
|
||||
{
|
||||
return daDict->stringForKey(kDADiskDescriptionVolumeKindKey);
|
||||
}
|
||||
|
||||
QString IOKitVolume::label() const
|
||||
{
|
||||
return daDict->stringForKey(kDADiskDescriptionVolumeNameKey);
|
||||
}
|
||||
|
||||
QString IOKitVolume::uuid() const
|
||||
{
|
||||
return m_device->property(QStringLiteral("UUID")).toString();
|
||||
}
|
||||
|
||||
qulonglong IOKitVolume::size() const
|
||||
{
|
||||
return m_device->property(QStringLiteral("Size")).toULongLong();
|
||||
}
|
||||
|
||||
QString IOKitVolume::encryptedContainerUdi() const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString IOKitVolume::vendor() const
|
||||
{
|
||||
return daDict->stringForKey(kDADiskDescriptionDeviceVendorKey);
|
||||
}
|
||||
|
||||
QString IOKitVolume::product() const
|
||||
{
|
||||
return daDict->stringForKey(kDADiskDescriptionDeviceModelKey);
|
||||
}
|
||||
|
||||
QString IOKitVolume::description() const
|
||||
{
|
||||
return daDict->stringForKey(kDADiskDescriptionMediaNameKey);
|
||||
}
|
||||
|
||||
DADiskRef IOKitVolume::daRef() const
|
||||
{
|
||||
return daDict->daRef;
|
||||
}
|
||||
|
||||
#include "moc_iokitvolume.cpp"
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2017 René J.V. Bertin <rjvbertin@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_IOKIT_VOLUME_H
|
||||
#define SOLID_BACKENDS_IOKIT_VOLUME_H
|
||||
|
||||
#include "dadictionary_p.h"
|
||||
#include "iokitblock.h"
|
||||
#include <solid/devices/ifaces/storagevolume.h>
|
||||
|
||||
#include <DiskArbitration/DiskArbitration.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace IOKit
|
||||
{
|
||||
class IOKitVolume : public Block, virtual public Solid::Ifaces::StorageVolume
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Solid::Ifaces::StorageVolume)
|
||||
|
||||
public:
|
||||
IOKitVolume(IOKitDevice *device);
|
||||
IOKitVolume(const IOKitDevice *device);
|
||||
virtual ~IOKitVolume();
|
||||
|
||||
bool isIgnored() const override;
|
||||
Solid::StorageVolume::UsageType usage() const override;
|
||||
QString fsType() const override;
|
||||
QString label() const override;
|
||||
QString uuid() const override;
|
||||
qulonglong size() const override;
|
||||
QString encryptedContainerUdi() const override;
|
||||
|
||||
QString vendor() const;
|
||||
QString product() const;
|
||||
QString description() const;
|
||||
|
||||
DADiskRef daRef() const;
|
||||
|
||||
private:
|
||||
DADictionary *daDict;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOLID_BACKENDS_IOKIT_VOLUME_H
|
||||
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Kevin Ottens <ervin@kde.org>
|
||||
SPDX-FileCopyrightText: 2013 Patrick Spendrin <ps_ml@gmx.de>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
// clang-format off
|
||||
|
||||
#include "cpufeatures.h"
|
||||
|
||||
#ifndef _MSC_VER
|
||||
//for cpuFeatures
|
||||
#include <csignal>
|
||||
#include <csetjmp>
|
||||
#else
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
#include <config-processor.h>
|
||||
|
||||
#if defined(__GNUC__) || defined(__INTEL_COMPILER)
|
||||
# define HAVE_GNU_INLINE_ASM
|
||||
#endif
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Shared
|
||||
{
|
||||
|
||||
#ifndef _MSC_VER
|
||||
typedef void (*kde_sighandler_t)(int);
|
||||
|
||||
#if defined( __i386__ ) || defined( __x86_64__ )
|
||||
static jmp_buf env;
|
||||
|
||||
#if HAVE_X86_SSE
|
||||
// Sighandler for the SSE OS support check
|
||||
static void sighandler(int)
|
||||
{
|
||||
std::longjmp(env, 1);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __i386__
|
||||
#define ASM_REG(reg) "%e" reg
|
||||
#define ASM_POP(reg) "popl %%e" reg " \n\t"
|
||||
#define ASM_PUSH(reg) "pushl %%e" reg " \n\t"
|
||||
#define ASM_XOR_REG(reg1, reg2) "xorl %%e" reg1 ", %%e" reg2 " \n\t"
|
||||
#define ASM_XOR_VAR(var, reg) "xorl " var ", %%e" reg " \n\t"
|
||||
#define ASM_CMP_REG(reg1, reg2) "cmpl %%e" reg1 ", %%e" reg2 " \n\t"
|
||||
#define ASM_MOV_REG(reg1, reg2) "movl %%e" reg1 ", %%e" reg2 " \n\t"
|
||||
#define ASM_MOV_VAR(var, reg) "movl " var ", %%e" reg " \n\t"
|
||||
#elif defined(__x86_64__)
|
||||
#define ASM_REG(reg) "%r" reg
|
||||
#define ASM_POP(reg) "popq %%r" reg " \n\t"
|
||||
#define ASM_PUSH(reg) "pushq %%r" reg " \n\t"
|
||||
#define ASM_XOR_REG(reg1, reg2) "xorq %%r" reg1 ", %%r" reg2 " \n\t"
|
||||
#define ASM_XOR_VAR(var, reg) "xorq " var ", %%r" reg " \n\t"
|
||||
#define ASM_CMP_REG(reg1, reg2) "cmpq %%r" reg1 ", %%r" reg2 " \n\t"
|
||||
#define ASM_MOV_REG(reg1, reg2) "movq %%r" reg1 ", %%r" reg2 " \n\t"
|
||||
#define ASM_MOV_VAR(var, reg) "movq " var ", %%r" reg " \n\t"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __PPC__
|
||||
static sigjmp_buf jmpbuf;
|
||||
static sig_atomic_t canjump = 0;
|
||||
|
||||
static void sigill_handler(int sig)
|
||||
{
|
||||
if (!canjump) {
|
||||
signal(sig, SIG_DFL);
|
||||
raise(sig);
|
||||
}
|
||||
canjump = 0;
|
||||
siglongjmp(jmpbuf, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
Solid::Processor::InstructionSets cpuFeatures()
|
||||
{
|
||||
volatile unsigned int features = 0;
|
||||
|
||||
#if defined( HAVE_GNU_INLINE_ASM )
|
||||
#if defined( __i386__ ) || defined( __x86_64__ )
|
||||
bool haveCPUID = false;
|
||||
unsigned int result = 0;
|
||||
unsigned int result2 = 0;
|
||||
|
||||
// First check if the CPU supports the CPUID instruction
|
||||
__asm__ __volatile__(
|
||||
// Try to toggle the CPUID bit in the EFLAGS register
|
||||
"pushf \n\t" // Push the EFLAGS register onto the stack
|
||||
ASM_POP("cx") // Pop the value into ECX
|
||||
ASM_MOV_REG("cx", "dx") // Copy ECX to EDX
|
||||
ASM_XOR_VAR("$0x00200000", "cx") // Toggle bit 21 (CPUID) in ECX
|
||||
ASM_PUSH("cx") // Push the modified value onto the stack
|
||||
"popf \n\t" // Pop it back into EFLAGS
|
||||
|
||||
// Check if the CPUID bit was successfully toggled
|
||||
"pushf \n\t" // Push EFLAGS back onto the stack
|
||||
ASM_POP("cx") // Pop the value into ECX
|
||||
ASM_XOR_REG("ax", "ax") // Zero out the EAX register
|
||||
ASM_CMP_REG("cx", "dx") // Compare ECX with EDX
|
||||
"je .Lno_cpuid_support%= \n\t" // Jump if they're identical
|
||||
ASM_MOV_VAR("$1", "ax") // Set EAX to true
|
||||
".Lno_cpuid_support%=: \n\t"
|
||||
: "=a"(haveCPUID) : : ASM_REG("cx"), ASM_REG("dx"));
|
||||
|
||||
// If we don't have CPUID we won't have the other extensions either
|
||||
if (haveCPUID) {
|
||||
// Execute CPUID with the feature request bit set
|
||||
__asm__ __volatile__(
|
||||
ASM_PUSH("bx") // Save EBX
|
||||
ASM_MOV_VAR("$1", "ax") // Set EAX to 1 (features request)
|
||||
"cpuid \n\t" // Call CPUID
|
||||
ASM_POP("bx") // Restore EBX
|
||||
: "=d"(result), "=c"(result2) : : ASM_REG("ax"));
|
||||
|
||||
features = result & 0x06800000; //copy the mmx and sse & sse2 bits to features
|
||||
features |= result2 & 0x00180101; //copy the ssse3, sse3 and sse4.1, sse4.2 bits to features
|
||||
|
||||
__asm__ __volatile__(
|
||||
ASM_PUSH("bx")
|
||||
ASM_PUSH("dx")
|
||||
ASM_MOV_VAR("$0x80000000", "ax")
|
||||
ASM_MOV_VAR("$0x80000000", "dx")
|
||||
"cpuid \n\t"
|
||||
ASM_CMP_REG("dx", "ax")
|
||||
"jbe .Lno_extended%= \n\t"
|
||||
ASM_MOV_VAR("$0x80000001", "ax")
|
||||
"cpuid \n\t"
|
||||
".Lno_extended%=: \n\t"
|
||||
ASM_POP("dx")
|
||||
ASM_POP("bx") // Restore EBX
|
||||
: "=d"(result) : : ASM_REG("ax"), ASM_REG("cx"));
|
||||
|
||||
if (result & 0x80000000) {
|
||||
features |= 0x80000000;
|
||||
}
|
||||
|
||||
#if HAVE_X86_SSE
|
||||
// Test bit 25 (SSE support)
|
||||
if (features & 0x02000000) {
|
||||
// OS support test for SSE.
|
||||
// Install our own sighandler for SIGILL.
|
||||
kde_sighandler_t oldhandler = std::signal(SIGILL, sighandler);
|
||||
|
||||
// Try executing an SSE insn to see if we get a SIGILL
|
||||
if (setjmp(env)) {
|
||||
features &= ~0x06080001; // The OS support test failed
|
||||
} else {
|
||||
__asm__ __volatile__("xorps %xmm0, %xmm0");
|
||||
}
|
||||
|
||||
// Restore the default sighandler
|
||||
std::signal(SIGILL, oldhandler);
|
||||
|
||||
// Note: The OS requirements for SSE2 are the same as for SSE
|
||||
// so we don't have to do any additional tests for that.
|
||||
}
|
||||
#endif // HAVE_X86_SSE
|
||||
}
|
||||
#elif defined __PPC__ && HAVE_PPC_ALTIVEC
|
||||
signal(SIGILL, sigill_handler);
|
||||
if (sigsetjmp(jmpbuf, 1)) {
|
||||
signal(SIGILL, SIG_DFL);
|
||||
} else {
|
||||
canjump = 1;
|
||||
__asm__ __volatile__("mtspr 256, %0\n\t"
|
||||
"vand %%v0, %%v0, %%v0"
|
||||
: /* none */
|
||||
: "r"(-1));
|
||||
signal(SIGILL, SIG_DFL);
|
||||
features = 0x2;
|
||||
}
|
||||
#endif // __i386__ || __x86_64__
|
||||
#elif defined(_MSC_VER)
|
||||
int array[4], ft = 1;
|
||||
__cpuid(array, ft);
|
||||
|
||||
features = array[3] & 0x06800000; //copy the mmx and sse & sse2 bits to features
|
||||
features |= array[2] & 0x00180101; //copy the ssse3, sse3 and sse4.1, sse4.2 bits to features
|
||||
|
||||
if (array[3] & 0x80000000) {
|
||||
features |= 0x80000000;
|
||||
}
|
||||
#endif //HAVE_GNU_INLINE_ASM
|
||||
Solid::Processor::InstructionSets featureflags;
|
||||
|
||||
if (features & 0x80000000) {
|
||||
featureflags |= Solid::Processor::Amd3DNow;
|
||||
}
|
||||
if (features & 0x00800000) {
|
||||
featureflags |= Solid::Processor::IntelMmx;
|
||||
}
|
||||
if (features & 0x02000000) {
|
||||
featureflags |= Solid::Processor::IntelSse;
|
||||
}
|
||||
if (features & 0x04000000) {
|
||||
featureflags |= Solid::Processor::IntelSse2;
|
||||
}
|
||||
if (features & 0x00000001) {
|
||||
featureflags |= Solid::Processor::IntelSse3;
|
||||
}
|
||||
if (features & 0x00000100) {
|
||||
featureflags |= Solid::Processor::IntelSsse3;
|
||||
}
|
||||
if (features & 0x00080000) {
|
||||
featureflags |= Solid::Processor::IntelSse41;
|
||||
}
|
||||
if (features & 0x00100000) {
|
||||
featureflags |= Solid::Processor::IntelSse42;
|
||||
}
|
||||
|
||||
if (features & 0x2) {
|
||||
featureflags |= Solid::Processor::AltiVec;
|
||||
}
|
||||
|
||||
return featureflags;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Rafael Fernández López <ereslibre@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef CPUFEATURES_H
|
||||
#define CPUFEATURES_H
|
||||
|
||||
#include <solid/processor.h>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Shared
|
||||
{
|
||||
Solid::Processor::InstructionSets cpuFeatures();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CPUFEATURES_H
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Mario Bensi <mbensi@ipsquad.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "rootdevice.h"
|
||||
|
||||
using namespace Solid::Backends::Shared;
|
||||
|
||||
RootDevice::RootDevice(const QString &udi, const QString &parentUdi)
|
||||
: Solid::Ifaces::Device()
|
||||
, m_udi(udi)
|
||||
, m_parentUdi(parentUdi)
|
||||
, m_vendor(QStringLiteral("KDE"))
|
||||
{
|
||||
}
|
||||
|
||||
RootDevice::~RootDevice()
|
||||
{
|
||||
}
|
||||
|
||||
QString RootDevice::udi() const
|
||||
{
|
||||
return m_udi;
|
||||
}
|
||||
|
||||
QString RootDevice::parentUdi() const
|
||||
{
|
||||
return m_parentUdi;
|
||||
}
|
||||
|
||||
QString RootDevice::vendor() const
|
||||
{
|
||||
return m_vendor;
|
||||
}
|
||||
|
||||
void RootDevice::setVendor(const QString &vendor)
|
||||
{
|
||||
m_vendor = vendor;
|
||||
}
|
||||
|
||||
QString RootDevice::product() const
|
||||
{
|
||||
return m_product;
|
||||
}
|
||||
|
||||
void RootDevice::setProduct(const QString &product)
|
||||
{
|
||||
m_product = product;
|
||||
}
|
||||
|
||||
QString RootDevice::icon() const
|
||||
{
|
||||
return m_icon;
|
||||
}
|
||||
|
||||
void RootDevice::setIcon(const QString &icon)
|
||||
{
|
||||
m_icon = icon;
|
||||
}
|
||||
|
||||
QStringList RootDevice::emblems() const
|
||||
{
|
||||
return m_emblems;
|
||||
}
|
||||
|
||||
void RootDevice::setEmblems(const QStringList &emblems)
|
||||
{
|
||||
m_emblems = emblems;
|
||||
}
|
||||
|
||||
QString RootDevice::description() const
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
void RootDevice::setDescription(const QString &description)
|
||||
{
|
||||
m_description = description;
|
||||
}
|
||||
|
||||
bool RootDevice::queryDeviceInterface(const Solid::DeviceInterface::Type &) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QObject *RootDevice::createDeviceInterface(const Solid::DeviceInterface::Type &)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#include "moc_rootdevice.cpp"
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2010 Mario Bensi <mbensi@ipsquad.net>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef SOLID_BACKENDS_SHARED_ROOT_DEVICE_H
|
||||
#define SOLID_BACKENDS_SHARED_ROOT_DEVICE_H
|
||||
|
||||
#include <solid/devices/ifaces/device.h>
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
namespace Solid
|
||||
{
|
||||
namespace Backends
|
||||
{
|
||||
namespace Shared
|
||||
{
|
||||
class RootDevice : public Solid::Ifaces::Device
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RootDevice(const QString &udi, const QString &parentUdi = QString());
|
||||
|
||||
~RootDevice() override;
|
||||
|
||||
QString udi() const override;
|
||||
QString parentUdi() const override;
|
||||
|
||||
QString vendor() const override;
|
||||
void setVendor(const QString &vendor);
|
||||
|
||||
QString product() const override;
|
||||
void setProduct(const QString &product);
|
||||
|
||||
QString icon() const override;
|
||||
void setIcon(const QString &icon);
|
||||
|
||||
QStringList emblems() const override;
|
||||
void setEmblems(const QStringList &emblems);
|
||||
|
||||
QString description() const override;
|
||||
void setDescription(const QString &description);
|
||||
|
||||
bool queryDeviceInterface(const Solid::DeviceInterface::Type &type) const override;
|
||||
|
||||
QObject *createDeviceInterface(const Solid::DeviceInterface::Type &type) override;
|
||||
|
||||
private:
|
||||
QString m_udi;
|
||||
QString m_parentUdi;
|
||||
QString m_vendor;
|
||||
QString m_product;
|
||||
QString m_icon;
|
||||
QStringList m_emblems;
|
||||
QString m_description;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef UDEVQT_H
|
||||
#define UDEVQT_H
|
||||
|
||||
#include "udevqtclient.h"
|
||||
#include "udevqtdevice.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Benjamin K. Stuhl <bks24@cornell.edu>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef UDEVQT_P_H
|
||||
#define UDEVQT_P_H
|
||||
|
||||
extern "C" {
|
||||
#define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE
|
||||
#include <libudev.h>
|
||||
}
|
||||
|
||||
class QByteArray;
|
||||
class QSocketNotifier;
|
||||
|
||||
namespace UdevQt
|
||||
{
|
||||
class DevicePrivate
|
||||
{
|
||||
public:
|
||||
DevicePrivate(struct udev_device *udev_, bool ref = true);
|
||||
~DevicePrivate();
|
||||
DevicePrivate &operator=(const DevicePrivate &other);
|
||||
|
||||
QString decodePropertyValue(const QByteArray &encoded) const;
|
||||
|
||||
struct udev_device *udev;
|
||||
};
|
||||
|
||||
class Client;
|
||||
class ClientPrivate
|
||||
{
|
||||
public:
|
||||
enum ListenToWhat { ListenToList, ListenToNone };
|
||||
|
||||
ClientPrivate(Client *q_);
|
||||
~ClientPrivate();
|
||||
|
||||
void init(const QStringList &subsystemList, ListenToWhat what);
|
||||
void setWatchedSubsystems(const QStringList &subsystemList);
|
||||
void dispatchEvent();
|
||||
DeviceList deviceListFromEnumerate(struct udev_enumerate *en);
|
||||
|
||||
struct udev *udev;
|
||||
struct udev_monitor *monitor;
|
||||
Client *q;
|
||||
QSocketNotifier *monitorNotifier;
|
||||
QStringList watchedSubsystems;
|
||||
};
|
||||
|
||||
inline QStringList listFromListEntry(struct udev_list_entry *list)
|
||||
{
|
||||
QStringList ret;
|
||||
struct udev_list_entry *entry;
|
||||
|
||||
udev_list_entry_foreach(entry, list)
|
||||
{
|
||||
ret << QString::fromLatin1(udev_list_entry_get_name(entry));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+282
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Benjamin K. Stuhl <bks24@cornell.edu>
|
||||
|
||||
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 "devices_debug.h"
|
||||
|
||||
#include <QSocketNotifier>
|
||||
#include <qplatformdefs.h>
|
||||
|
||||
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
|
||||
for (const QString &subsysDevtype : subsystemList) {
|
||||
int ix = subsysDevtype.indexOf(QLatin1String("/"));
|
||||
|
||||
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, &QSocketNotifier::activated, q, [this]() {
|
||||
dispatchEvent();
|
||||
});
|
||||
|
||||
// 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::dispatchEvent()
|
||||
{
|
||||
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") {
|
||||
Q_EMIT q->deviceAdded(device);
|
||||
} else if (action == "remove") {
|
||||
Q_EMIT q->deviceRemoved(device);
|
||||
} else if (action == "change") {
|
||||
Q_EMIT q->deviceChanged(device);
|
||||
} else if (action == "online") {
|
||||
Q_EMIT q->deviceOnlined(device);
|
||||
} else if (action == "offline") {
|
||||
Q_EMIT q->deviceOfflined(device);
|
||||
} else if (action == "bind") {
|
||||
Q_EMIT q->deviceBound(device);
|
||||
} else if (action == "unbind") {
|
||||
Q_EMIT q->deviceUnbound(device);
|
||||
} else {
|
||||
qCDebug(Solid::Frontend::DeviceManager::DEVICEMANAGER) << "UdevQt: unhandled action:" << action.constData() << "for device:" << device.sysfsPath();
|
||||
}
|
||||
}
|
||||
|
||||
DeviceList ClientPrivate::deviceListFromEnumerate(struct udev_enumerate *en)
|
||||
{
|
||||
DeviceList ret;
|
||||
struct udev_list_entry *list;
|
||||
struct udev_list_entry *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"
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Benjamin K. Stuhl <bks24@cornell.edu>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef UDEVQTCLIENT_H
|
||||
#define UDEVQTCLIENT_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QVariant>
|
||||
|
||||
#include "udevqtdevice.h"
|
||||
|
||||
namespace UdevQt
|
||||
{
|
||||
class ClientPrivate;
|
||||
class Client : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QStringList watchedSubsystems READ watchedSubsystems WRITE setWatchedSubsystems)
|
||||
|
||||
public:
|
||||
Client(QObject *parent = nullptr);
|
||||
Client(const QStringList &subsystemList, QObject *parent = nullptr);
|
||||
~Client() override;
|
||||
|
||||
QStringList watchedSubsystems() const;
|
||||
void setWatchedSubsystems(const QStringList &subsystemList);
|
||||
|
||||
DeviceList allDevices();
|
||||
DeviceList devicesByProperty(const QString &property, const QVariant &value);
|
||||
DeviceList devicesBySubsystem(const QString &subsystem);
|
||||
/**
|
||||
* Returns a list of devices matching any of the given subsystems AND any of the properties.
|
||||
*
|
||||
* (subsystem1 || subsystem2 || ...) && (property1 || property2 || ...)
|
||||
*/
|
||||
DeviceList devicesBySubsystemsAndProperties(const QStringList &subsystems, const QVariantMap &properties);
|
||||
Device deviceByDeviceFile(const QString &deviceFile);
|
||||
Device deviceBySysfsPath(const QString &sysfsPath);
|
||||
Device deviceBySubsystemAndName(const QString &subsystem, const QString &name);
|
||||
|
||||
Q_SIGNALS:
|
||||
void deviceAdded(const UdevQt::Device &dev);
|
||||
void deviceRemoved(const UdevQt::Device &dev);
|
||||
void deviceChanged(const UdevQt::Device &dev);
|
||||
void deviceOnlined(const UdevQt::Device &dev);
|
||||
void deviceOfflined(const UdevQt::Device &dev);
|
||||
void deviceBound(const UdevQt::Device &dev);
|
||||
void deviceUnbound(const UdevQt::Device &dev);
|
||||
|
||||
private:
|
||||
friend class ClientPrivate;
|
||||
ClientPrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+278
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Benjamin K. Stuhl <bks24@cornell.edu>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "udevqtdevice.h"
|
||||
#include "udevqt_p.h"
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
namespace UdevQt
|
||||
{
|
||||
DevicePrivate::DevicePrivate(struct udev_device *udev_, bool ref)
|
||||
: udev(udev_)
|
||||
{
|
||||
if (ref) {
|
||||
udev_device_ref(udev);
|
||||
}
|
||||
}
|
||||
|
||||
DevicePrivate::~DevicePrivate()
|
||||
{
|
||||
udev_device_unref(udev);
|
||||
}
|
||||
|
||||
DevicePrivate &DevicePrivate::operator=(const DevicePrivate &other)
|
||||
{
|
||||
udev_device_unref(udev);
|
||||
udev = udev_device_ref(other.udev);
|
||||
return *this;
|
||||
}
|
||||
|
||||
QString DevicePrivate::decodePropertyValue(const QByteArray &encoded) const
|
||||
{
|
||||
QByteArray decoded;
|
||||
const int len = encoded.length();
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
quint8 ch = encoded.at(i);
|
||||
|
||||
if (ch == '\\') {
|
||||
if (i + 1 < len && encoded.at(i + 1) == '\\') {
|
||||
decoded.append('\\');
|
||||
i++;
|
||||
continue;
|
||||
} else if (i + 3 < len && encoded.at(i + 1) == 'x') {
|
||||
QByteArray hex = encoded.mid(i + 2, 2);
|
||||
bool ok;
|
||||
int code = hex.toInt(&ok, 16);
|
||||
if (ok) {
|
||||
decoded.append(char(code));
|
||||
}
|
||||
i += 3;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
decoded.append(ch);
|
||||
}
|
||||
}
|
||||
return QString::fromUtf8(decoded);
|
||||
}
|
||||
|
||||
Device::Device()
|
||||
: d(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Device::Device(const Device &other)
|
||||
{
|
||||
if (other.d) {
|
||||
d = new DevicePrivate(other.d->udev);
|
||||
} else {
|
||||
d = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Device::Device(DevicePrivate *devPrivate)
|
||||
: d(devPrivate)
|
||||
{
|
||||
}
|
||||
|
||||
Device::~Device()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
Device &Device::operator=(const Device &other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
if (!other.d) {
|
||||
delete d;
|
||||
d = nullptr;
|
||||
return *this;
|
||||
}
|
||||
if (!d) {
|
||||
d = new DevicePrivate(other.d->udev);
|
||||
} else {
|
||||
*d = *other.d;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Device::isValid() const
|
||||
{
|
||||
return (d != nullptr);
|
||||
}
|
||||
|
||||
QString Device::subsystem() const
|
||||
{
|
||||
if (!d) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return QString::fromLatin1(udev_device_get_subsystem(d->udev));
|
||||
}
|
||||
|
||||
QString Device::devType() const
|
||||
{
|
||||
if (!d) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return QString::fromLatin1(udev_device_get_devtype(d->udev));
|
||||
}
|
||||
|
||||
QString Device::name() const
|
||||
{
|
||||
if (!d) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return QString::fromLatin1(udev_device_get_sysname(d->udev));
|
||||
}
|
||||
|
||||
QString Device::sysfsPath() const
|
||||
{
|
||||
if (!d) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return QString::fromLatin1(udev_device_get_syspath(d->udev));
|
||||
}
|
||||
|
||||
int Device::sysfsNumber() const
|
||||
{
|
||||
if (!d) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
QString value = QString::fromLatin1(udev_device_get_sysnum(d->udev));
|
||||
bool success = false;
|
||||
int number = value.toInt(&success);
|
||||
if (success) {
|
||||
return number;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
QString Device::driver() const
|
||||
{
|
||||
if (!d) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return QString::fromLatin1(udev_device_get_driver(d->udev));
|
||||
}
|
||||
|
||||
QString Device::primaryDeviceFile() const
|
||||
{
|
||||
if (!d) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return QString::fromLatin1(udev_device_get_devnode(d->udev));
|
||||
}
|
||||
|
||||
QStringList Device::alternateDeviceSymlinks() const
|
||||
{
|
||||
if (!d) {
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
return listFromListEntry(udev_device_get_devlinks_list_entry(d->udev));
|
||||
}
|
||||
|
||||
QStringList Device::deviceProperties() const
|
||||
{
|
||||
if (!d) {
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
return listFromListEntry(udev_device_get_properties_list_entry(d->udev));
|
||||
}
|
||||
|
||||
#ifdef UDEV_HAVE_GET_SYSATTR_LIST_ENTRY
|
||||
QStringList Device::sysfsProperties() const
|
||||
{
|
||||
if (!d) {
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
return listFromListEntry(udev_device_get_sysattr_list_entry(d->udev));
|
||||
}
|
||||
#endif
|
||||
|
||||
Device Device::parent() const
|
||||
{
|
||||
if (!d) {
|
||||
return Device();
|
||||
}
|
||||
|
||||
struct udev_device *p = udev_device_get_parent(d->udev);
|
||||
|
||||
if (!p) {
|
||||
return Device();
|
||||
}
|
||||
|
||||
return Device(new DevicePrivate(p));
|
||||
}
|
||||
|
||||
QVariant Device::deviceProperty(const QString &name) const
|
||||
{
|
||||
if (!d) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QByteArray propName = name.toLatin1();
|
||||
QString propValue = QString::fromLatin1(udev_device_get_property_value(d->udev, propName.constData()));
|
||||
if (!propValue.isEmpty()) {
|
||||
return QVariant::fromValue(propValue);
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QString Device::decodedDeviceProperty(const QString &name) const
|
||||
{
|
||||
if (!d) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
QByteArray propName = name.toLatin1();
|
||||
return d->decodePropertyValue(udev_device_get_property_value(d->udev, propName.constData()));
|
||||
}
|
||||
|
||||
QVariant Device::sysfsProperty(const QString &name) const
|
||||
{
|
||||
if (!d) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QByteArray propName = name.toLatin1();
|
||||
QString propValue = QString::fromLatin1(udev_device_get_sysattr_value(d->udev, propName.constData()));
|
||||
if (!propValue.isEmpty()) {
|
||||
return QVariant::fromValue(propValue);
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Device Device::ancestorOfType(const QString &subsys, const QString &devtype) const
|
||||
{
|
||||
if (!d) {
|
||||
return Device();
|
||||
}
|
||||
|
||||
struct udev_device *p = udev_device_get_parent_with_subsystem_devtype(d->udev, subsys.toLatin1().constData(), devtype.toLatin1().constData());
|
||||
|
||||
if (!p) {
|
||||
return Device();
|
||||
}
|
||||
|
||||
return Device(new DevicePrivate(p));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2009 Benjamin K. Stuhl <bks24@cornell.edu>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef UDEVQTDEVICE_H
|
||||
#define UDEVQTDEVICE_H
|
||||
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QVariant>
|
||||
|
||||
namespace UdevQt
|
||||
{
|
||||
class DevicePrivate;
|
||||
class Device
|
||||
{
|
||||
public:
|
||||
Device();
|
||||
Device(const Device &other);
|
||||
~Device();
|
||||
Device &operator=(const Device &other);
|
||||
|
||||
bool isValid() const;
|
||||
QString subsystem() const;
|
||||
QString devType() const;
|
||||
QString name() const;
|
||||
QString sysfsPath() const;
|
||||
int sysfsNumber() const;
|
||||
QString driver() const;
|
||||
QString primaryDeviceFile() const;
|
||||
QStringList alternateDeviceSymlinks() const;
|
||||
QStringList deviceProperties() const;
|
||||
#ifdef UDEV_HAVE_GET_SYSATTR_LIST_ENTRY
|
||||
QStringList sysfsProperties() const;
|
||||
#endif
|
||||
Device parent() const;
|
||||
|
||||
// ### should this really be a QVariant? as far as udev knows, everything is a string...
|
||||
// see also Client::devicesByProperty
|
||||
QVariant deviceProperty(const QString &name) const;
|
||||
QString decodedDeviceProperty(const QString &name) const;
|
||||
QVariant sysfsProperty(const QString &name) const;
|
||||
Device ancestorOfType(const QString &subsys, const QString &devtype) const;
|
||||
|
||||
private:
|
||||
Device(DevicePrivate *devPrivate);
|
||||
friend class Client;
|
||||
friend class ClientPrivate;
|
||||
|
||||
DevicePrivate *d;
|
||||
};
|
||||
|
||||
typedef QList<Device> DeviceList;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user