Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions deepin-devicemanager-server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ project(deepin-devicemanager-server C CXX)

add_subdirectory(deepin-deviceinfo)
add_subdirectory(deepin-devicecontrol)
add_subdirectory(customgpuinfo)

#TEST--------------------------------------------------
if (CMAKE_COVERAGE_ARG STREQUAL "CMAKE_COVERAGE_ARG_ON")
Expand Down
24 changes: 24 additions & 0 deletions deepin-devicemanager-server/customgpuinfo/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 3.7)

set(BIN_NAME "customgpuinfo")

find_package(Qt5 COMPONENTS Core REQUIRED)

file(GLOB_RECURSE SRC
"${CMAKE_CURRENT_SOURCE_DIR}/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/*.cpp"
)

add_executable(${BIN_NAME}
${SRC}
)

target_include_directories(${BIN_NAME} PUBLIC
Qt5::Core
)

target_link_libraries(${BIN_NAME} PRIVATE
Qt5::Core
)

install(TARGETS ${BIN_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/deepin-devicemanager)
120 changes: 120 additions & 0 deletions deepin-devicemanager-server/customgpuinfo/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include <QProcess>

Check warning on line 5 in deepin-devicemanager-server/customgpuinfo/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QProcess> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QMap>

Check warning on line 6 in deepin-devicemanager-server/customgpuinfo/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QMap> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QRegularExpression>

Check warning on line 7 in deepin-devicemanager-server/customgpuinfo/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QRegularExpression> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QFile>

Check warning on line 8 in deepin-devicemanager-server/customgpuinfo/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QFile> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QDebug>

Check warning on line 9 in deepin-devicemanager-server/customgpuinfo/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QDebug> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <iostream>

Check warning on line 11 in deepin-devicemanager-server/customgpuinfo/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <iostream> not found. Please note: Cppcheck does not need standard library headers to get proper results.

// 名称("Name") 厂商("Vendor") 型号("Model") 显存("Graphics Memory")

constexpr char kName[] { "Name" };
constexpr char kVendor[] { "Vendor" };
constexpr char kModel[] { "Model" };
constexpr char kGraphicsMemory[] { "Graphics Memory" };

bool getGpuBaseInfo(QMap<QString, QString> &mapInfo)
{
QProcess process;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
process.setProcessEnvironment(env);
process.start("/usr/bin/glxinfo", QStringList() << "-B");
if (!process.waitForFinished(3000)) {
qCritical() << "Error executing glxinfo:" << process.errorString();
return false;
}

QString output = QString::fromLocal8Bit(process.readAllStandardOutput());
QStringList lines = output.split('\n');
QRegularExpression regex("^([^:]+):\\s*(.+)$");
for (const QString &line : lines) {
QRegularExpressionMatch match = regex.match(line);
if (match.hasMatch()) {
QString key = match.captured(1).trimmed();
QString value = match.captured(2).trimmed();
if (key == "OpenGL renderer string") {
mapInfo.insert(kName, value);
mapInfo.insert(kModel, value);
} else if (key == "OpenGL vendor string") {
mapInfo.insert(kVendor, value);
}
}
}

return true;
}

bool getGpuMemInfoForFTDTM(QMap<QString, QString> &mapInfo)
{
const QString filePath = "/sys/kernel/debug/gc/meminfo";
QString totalValue;
bool foundTotal = false;

QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qCritical() << "Error opening /sys/kernel/debug/gc/meminfo:" << file.errorString();
return false;
}

QString content = QString::fromUtf8(file.readAll());
file.close();

if (content.isEmpty()) {
qCritical() << "Error: /sys/kernel/debug/gc/meminfo File is empty!";
return false;
}

QRegularExpression system0Regex(R"(POOL SYSTEM0:*(.*?)POOL VIRTUAL:)",
QRegularExpression::DotMatchesEverythingOption);
QRegularExpressionMatch system0Match = system0Regex.match(content);

if (!system0Match.hasMatch()) {
qCritical() << "Error: Failed to find SYSTEM0 section";
return false;
}

QString system0Content = system0Match.captured(1);
QRegularExpression totalRegex(R"(Total\s*:\s*(\d+)\s+B)");
QRegularExpressionMatch totalMatch = totalRegex.match(system0Content);
if (totalMatch.hasMatch()) {
totalValue = totalMatch.captured(1);
foundTotal = true;
}

if (!foundTotal || totalValue.isEmpty()) {
qCritical() << "Error: Failed to find Total value in SYSTEM0 content";
return false;
}

bool ok;
quint64 memSize = totalValue.trimmed().toULong(&ok, 10);
if (ok && memSize >= 1048576) {
memSize /= 1048576;
auto curSize = memSize / 1024.0;
if (curSize >= 1) {
totalValue = QString::number(curSize) + "GB";
} else {
totalValue = QString::number(memSize) + "MB";
}
}

mapInfo.insert(kGraphicsMemory, totalValue);

return true;
}

int main(int argc, char *argv[])
{
QMap<QString, QString> mapInfo;
if (getGpuBaseInfo(mapInfo) && getGpuMemInfoForFTDTM(mapInfo)) {
for (auto it = mapInfo.begin(); it != mapInfo.end(); ++it)
std::cout << it.key().toStdString() << ": " << it.value().toStdString() << std::endl;
return 0;
} else {
return 1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
#include "mainjob.h"
#include "DDLog.h"

#include <QDBusConnection>

Check warning on line 10 in deepin-devicemanager-server/deepin-deviceinfo/src/loadinfo/deviceinterface.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QDBusConnection> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QDBusMessage>

Check warning on line 11 in deepin-devicemanager-server/deepin-deviceinfo/src/loadinfo/deviceinterface.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QDBusMessage> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QProcess>

Check warning on line 12 in deepin-devicemanager-server/deepin-deviceinfo/src/loadinfo/deviceinterface.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QProcess> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QDebug>

Check warning on line 13 in deepin-devicemanager-server/deepin-deviceinfo/src/loadinfo/deviceinterface.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QDebug> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <polkit-qt5-1/PolkitQt1/Authority>
#else
Expand Down Expand Up @@ -88,3 +90,30 @@
qCWarning(appLog) << "Failed to set monitor flag - parent MainJob not found";
}
}

QString DeviceInterface::getGpuInfoByCustom(const QString &cmd, const QStringList &arguments)
{
static bool firstFlag = true;
static QString gpuinfo;
if (firstFlag) {
firstFlag = false;

QProcess process;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
if (arguments.size() > 1) {
env.insert("DISPLAY", arguments[0]);
env.insert("XAUTHORITY", arguments[1]);
}
process.setProcessEnvironment(env);
process.start(cmd, arguments);
if (!process.waitForFinished(4000)) {
qCritical() << QString("Error executing %1 :").arg(cmd) << process.errorString();
return gpuinfo;
}

if (process.exitCode() == 0)
gpuinfo = QString::fromLocal8Bit(process.readAllStandardOutput());
}

return gpuinfo;
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public slots:
*/
Q_SCRIPTABLE void setMonitorDeviceFlag(bool flag);

Q_SCRIPTABLE QString getGpuInfoByCustom(const QString &cmd, const QStringList &arguments);

private:
bool getUserAuthorPasswd();
};
Expand Down
12 changes: 12 additions & 0 deletions deepin-devicemanager/assets/org.deepin.devicemanager.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,18 @@
"description": "此配置项默认为无效的。如需让toml文件内容显示生效,请配置对应文件名。需保证操作者具备读取权限。",
"permissions": "readwrite",
"visibility": "private"
},
"CommandToGetGPUInfo": {
"value": "",
"serial": 0,
"flags": [
"global"
],
"name": "Command to get GPU infomation",
"name[zh_CN]": "获取GPU信息的命令",
"description": "此配置项默认为空。如果specialComType==8,程序则启用此项配置。",
"permissions": "readwrite",
"visibility": "private"
}
}
}
9 changes: 9 additions & 0 deletions deepin-devicemanager/src/DeviceManager/DeviceGpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,15 @@ void DeviceGpu::setGpuInfo(const QMap<QString, QString> &mapInfo)
getOtherMapInfo(mapInfo);
}

// 名称(Name) 厂商(Vendor) 型号(Model) 显存(Graphics Memory)
void DeviceGpu::setGpuInfoByCustom(const QMap<QString, QString> &mapInfo)
{
setAttribute(mapInfo, "Name", m_Name);
setAttribute(mapInfo, "Vendor", m_Vendor);
setAttribute(mapInfo, "Model", m_Model);
setAttribute(mapInfo, "Graphics Memory", m_GraphicsMemory);
}

const QString &DeviceGpu::name() const
{
// qCDebug(appLog) << "DeviceGpu::name called, returning: " << m_Name;
Expand Down
2 changes: 2 additions & 0 deletions deepin-devicemanager/src/DeviceManager/DeviceGpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ class DeviceGpu: public DeviceBaseInfo
*/
void setGpuInfo(const QMap<QString, QString> &mapInfo);

void setGpuInfoByCustom(const QMap<QString, QString> &mapInfo);

/**
* @brief name:获取名称属性值
* @return QString 名称属性值
Expand Down
92 changes: 92 additions & 0 deletions deepin-devicemanager/src/GenerateDevice/CustomGenerator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "CustomGenerator.h"
#include "DeviceGpu.h"
#include "DBusInterface.h"
#include "commontools.h"

#include <QProcess>
#include <QRegularExpression>
#include <QDir>
#include <QDBusInterface>
#include <QDBusReply>

CustomGenerator::CustomGenerator(QObject *parent)
: DeviceGenerator(parent)
{
}

void CustomGenerator::generatorGpuDevice()
{
QString cmd = CommonTools::getGpuInfoCommandFromDConfig();
if (cmd.isEmpty()) {
DeviceGenerator::generatorGpuDevice();
return;
}

QStringList arguments;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
QString display = env.value("DISPLAY");
QString xauthority = env.value("XAUTHORITY");
if (display.isEmpty() || xauthority.isEmpty()) {
qWarning() << "DISPLAY or XAUTHORITY is not set!";
} else {
arguments << display << xauthority;
}

QString tmpGpuInfo;
DBusInterface::getInstance()->getGpuInfoByCustom(cmd, arguments, tmpGpuInfo);
if (tmpGpuInfo.isEmpty()) {
qCritical() << "Failed to get gpu info by commad " << cmd;
return;
}

QList<QMap<QString, QString>> gpuInfo;
QStringList mapBlocks = tmpGpuInfo.split("\n\n");
for (const QString &block : mapBlocks) {
QMap<QString, QString> infoMap;
QStringList lines = block.split("\n");
for (const QString &line : lines) {
int colonIndex = line.indexOf(':');
if (colonIndex != -1) {
QString key = line.left(colonIndex).trimmed();
QString value = line.mid(colonIndex + 1).trimmed();
infoMap.insert(key, value);
}
}
if (!infoMap.isEmpty())
gpuInfo.push_back(infoMap);
}

for(int i = 0; i < gpuInfo.count(); ++i) {
DeviceGpu *device = new DeviceGpu();
device->setCanUninstall(false);
device->setForcedDisplay(true);
device->setGpuInfoByCustom(gpuInfo.at(i));
DeviceManager::instance()->addGpuDevice(device);
}
}

void CustomGenerator::generatorMonitorDevice()
{
QString toDir = "/sys/class/drm";
QDir toDir_(toDir);

if (!toDir_.exists())
return;

QFileInfoList fileInfoList = toDir_.entryInfoList(QDir::NoFilter, QDir::Name);
foreach(QFileInfo fileInfo, fileInfoList) {
if (fileInfo.fileName() == "." || fileInfo.fileName() == ".." || !fileInfo.fileName().startsWith("card"))
continue;

if (QFile::exists(fileInfo.filePath() + "/" + "edid")) {
QStringList allEDIDS_all;
allEDIDS_all.append(fileInfo.filePath() + "/" + "edid");
QString interface = fileInfo.fileName().remove("card0-").remove("card1-").remove("card2-");
CommonTools::parseEDID(allEDIDS_all, interface);
}
}
}
27 changes: 27 additions & 0 deletions deepin-devicemanager/src/GenerateDevice/CustomGenerator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (C) 2025 Uniontech Software Technology Co.,Ltd.
// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef CUSTOMGENERATOR_H
#define CUSTOMGENERATOR_H

#include "DeviceGenerator.h"

class CustomGenerator : public DeviceGenerator
{
public:
CustomGenerator(QObject *parent = nullptr);

/**
* @brief generatorGpuDevice:生成显卡信息
*/
void generatorGpuDevice() override;

/**
* @brief generatorMonitorDevice:生成显示设备信息
*/
void generatorMonitorDevice() override;
};

#endif // CUSTOMGENERATOR_H
12 changes: 12 additions & 0 deletions deepin-devicemanager/src/GenerateDevice/DBusInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ void DBusInterface::refreshInfo()
mp_Iface->asyncCall("refreshInfo");
}

bool DBusInterface::getGpuInfoByCustom(const QString &cmd, const QStringList &arguments, QString &gpuInfo)
{
QDBusReply<QString> replyList = mp_Iface->call("getGpuInfoByCustom", cmd, arguments);
if (replyList.isValid()) {
gpuInfo = replyList.value();
return true;
} else {
qCritical() << "Error: failed to call dbus to get gpu memery info! ";
return false;
}
}

void DBusInterface::init()
{
qCDebug(appLog) << "DBusInterface::init start";
Expand Down
2 changes: 2 additions & 0 deletions deepin-devicemanager/src/GenerateDevice/DBusInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ class DBusInterface
*/
void refreshInfo();

bool getGpuInfoByCustom(const QString &cmd, const QStringList &arguments, QString &gpuInfo);

protected:
DBusInterface();

Expand Down
Loading