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
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
#include "DDLog.h"

#include <QLoggingCategory>
#include <QProcess>

Check warning on line 16 in deepin-devicemanager-server/deepin-devicecontrol/src/controlinterface.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 <QDir>

Check warning on line 17 in deepin-devicemanager-server/deepin-devicecontrol/src/controlinterface.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

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

Check warning on line 18 in deepin-devicemanager-server/deepin-devicecontrol/src/controlinterface.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 <QFileInfo>

Check warning on line 19 in deepin-devicemanager-server/deepin-devicecontrol/src/controlinterface.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

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

Check warning on line 20 in deepin-devicemanager-server/deepin-devicecontrol/src/controlinterface.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

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

Check warning on line 21 in deepin-devicemanager-server/deepin-devicecontrol/src/controlinterface.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.
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <polkit-qt5-1/PolkitQt1/Authority>
#else
Expand Down Expand Up @@ -204,6 +206,93 @@
return true;
}

bool ControlInterface::enableKeyboard(const QString& vid, const QString& pid, const QString &hclass, const QString &name, const QString &sPath, const QString &value, bool enable_device, const QString strDriver)
{
qCInfo(appLog) << "Enable keyboard request:" << hclass << name << sPath << value << "enable:" << enable_device;

if (!getUserAuthorPasswd()) {
qCWarning(appLog) << "Authorization failed for keyboard enable operation";
return false;
}

// Use EnableUtils's validation function
QString safeVid, safePid;
if (!EnableUtils::validateAndNormalizeVidPid(vid, pid, safeVid, safePid)) {
qCWarning(appLog) << "VID or PID validation failed. VID:" << vid << "PID:" << pid;
return false;
}

QString rulesFile = QString(UDEV_RULES_PATH_LOCAL "/99-keyboard-device-control-%1-%2.rules").arg(vid).arg(pid);

QString ruleContent;
if (enable_device) {
ruleContent = QString("# enable keyboard - VID:%1 PID:%2\n"
"ACTION==\"add|change\", SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%1\", ATTRS{idProduct}==\"%2\", "
"ATTR{authorized}=\"1\"").arg(safeVid, safePid);
qCInfo(appLog) << "Creating rule to enable keyboard";
} else {
ruleContent = QString("# disable keyboard - VID:%1 PID:%2\n"
"ACTION==\"add|change\", SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%1\", ATTRS{idProduct}==\"%2\", "
"ATTR{authorized}=\"0\"").arg(safeVid, safePid);
qCInfo(appLog) << "Creating rule to disable keyboard";
}

QFileInfo fileInfo(rulesFile);
QDir rulesDir = fileInfo.absoluteDir();
if (!rulesDir.exists()) {
qCWarning(appLog) << "Udev rules directory does not exist:" << rulesDir.absolutePath();
return false;
}

QFile file(rulesFile);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
qCWarning(appLog) << "Failed to open udev rules file for writing:" << rulesFile;
qCWarning(appLog) << "Error:" << file.errorString();
return false;
}

QTextStream out(&file);
out << ruleContent;
file.close();

if (file.error() != QFile::NoError) {
qCWarning(appLog) << "Failed to write udev rule. Error:" << file.errorString();
return false;
}

QProcess reloadProcess;
qCInfo(appLog) << "Reloading udev rules";
reloadProcess.start("udevadm", QStringList() << "control" << "--reload-rules");
reloadProcess.waitForFinished(10000);

if (reloadProcess.exitCode() != 0) {
qCWarning(appLog) << "Failed to reload udev rules. Error:" << reloadProcess.readAllStandardError();
return false;
}

QProcess triggerProcess;
qCInfo(appLog) << "Triggering udev rules";
triggerProcess.start("udevadm", QStringList() << "trigger");
triggerProcess.waitForFinished(10000);

if (triggerProcess.exitCode() != 0) {
qCWarning(appLog) << "Failed to trigger udev rules. Error:" << triggerProcess.readAllStandardError();
return false;
}

if (!enable_device) {
EnableSqlManager::getInstance()->insertDataToAuthorizedTable(hclass, name, sPath, value, true, strDriver);
qCInfo(appLog) << "insertDataToAuthorizedTable";
} else {
EnableSqlManager::getInstance()->removeDataFromAuthorizedTable(value);
qCInfo(appLog) << "removeDataFromAuthorizedTable";
}

qCInfo(appLog) << "Keyboard udev rule created and applied successfully";
emit sigUpdate();
return true;
}

void ControlInterface::disableInDevice()
{
if (!getUserAuthorPasswd())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,26 @@
#include "commonfunction.h"

#include <qdbusservice.h>
#include <QObject>

Check warning on line 13 in deepin-devicemanager-server/deepin-devicecontrol/src/controlinterface.h

View workflow job for this annotation

GitHub Actions / cppcheck

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

Check warning on line 14 in deepin-devicemanager-server/deepin-devicecontrol/src/controlinterface.h

View workflow job for this annotation

GitHub Actions / cppcheck

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

// Udev rules directory paths
/*
* Udev rules are read from the following directories in priority order:
* 1. /etc/udev/rules.d/ - Highest priority, for local administrator custom rules
* 2. /run/udev/rules.d/ - Runtime rules (may not exist on all systems)
* 3. /usr/local/lib/udev/rules.d/ - Local software rules (recommended for applications)
* 4. /usr/lib/udev/rules.d/ - System default rules
*
* All rules files are processed in lexical order, regardless of the directory they live in.
* Files with identical filenames replace each other. Files in /etc have the highest priority.
* Rule files must have the extension .rules; other extensions are ignored.
*/
#define UDEV_RULES_PATH_LOCAL "/usr/local/lib/udev/rules.d"
#define UDEV_RULES_PATH_SYSTEM "/etc/udev/rules.d"
#define UDEV_RULES_PATH_RUNTIME "/run/udev/rules.d"
#define UDEV_RULES_PATH_LIB "/usr/lib/udev/rules.d"

class DriverManager;
class ModCore;
class ControlInterface : public QDBusService, protected QDBusContext
Expand Down Expand Up @@ -69,6 +86,17 @@
* @return
*/
Q_SCRIPTABLE bool enablePrinter(const QString &hclass, const QString &name, const QString &path, bool enable_device);
/**
* @brief enableKeyboard 启用/禁用键盘设备
* @param hclass 设备类型
* @param name 设备名称
* @param sPath 设备路径
* @param value 设备唯一标识
* @param enable_device 是否启用
* @param strDriver 驱动名称
* @return 操作是否成功
*/
Q_SCRIPTABLE bool enableKeyboard(const QString& vid, const QString& pid, const QString &hclass, const QString &name, const QString &sPath, const QString &value, bool enable_device, const QString strDriver);
/**
* @brief disableOutDevice 禁用设备
* @param devInfo 设备信息
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,45 @@
return true;
}

bool EnableUtils::validateAndNormalizeVidPid(const QString &vid, const QString &pid, QString &normalizedVid, QString &normalizedPid)

Check warning on line 207 in deepin-devicemanager-server/deepin-devicecontrol/src/enablecontrol/enableutils.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'validateAndNormalizeVidPid' is never used.
{
qCDebug(appLog) << "Validating and normalizing VID:" << vid << "PID:" << pid;

// Check if VID or PID is empty
if (vid.isEmpty() || pid.isEmpty()) {
qCWarning(appLog) << "VID or PID is empty for validation";
return false;
}

// Normalize VID
normalizedVid = vid.toLower();
if (normalizedVid.startsWith("0x")) {
normalizedVid = normalizedVid.mid(2);
}

// Normalize PID
normalizedPid = pid.toLower();
if (normalizedPid.startsWith("0x")) {
normalizedPid = normalizedPid.mid(2);
}

// Validate VID and PID format (should be 4 characters each after normalization)
if (normalizedVid.length() != 4 || normalizedPid.length() != 4) {
qCWarning(appLog) << "Invalid VID or PID format after normalization. VID:" << normalizedVid << "PID:" << normalizedPid;
return false;
}

// Validate that VID and PID contain only hex characters
QRegularExpression hexPattern("^[0-9a-f]{4}$");
if (!hexPattern.match(normalizedVid).hasMatch() || !hexPattern.match(normalizedPid).hasMatch()) {
qCWarning(appLog) << "VID or PID contains non-hex characters. VID:" << normalizedVid << "PID:" << normalizedPid;
return false;
}

qCDebug(appLog) << "VID and PID validation successful. Normalized VID:" << normalizedVid << "Normalized PID:" << normalizedPid;
return true;
}

bool EnableUtils::getMapInfo(const QString &item, QMap<QString, QString> &mapInfo)
{
qCDebug(appLog) << "Parsing device info map";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ class EnableUtils
*/
static void disableOutDevice(const QString &info);


/**
* @brief disableInDevice 禁用非外设
*/
Expand All @@ -31,7 +30,17 @@ class EnableUtils
* @return
*/
static bool ioctlOperateNetworkLogicalName(const QString &logicalName, bool enable);


/**
* @brief validateAndNormalizeVidPid 验证并标准化VID和PID
* @param vid 输入的VID
* @param pid 输入的PID
* @param normalizedVid 输出的标准化VID
* @param normalizedPid 输出的标准化PID
* @return 验证是否成功
*/
static bool validateAndNormalizeVidPid(const QString &vid, const QString &pid, QString &normalizedVid, QString &normalizedPid);

/**
* @brief getMapInfo 解析usb信息
* @param item
Expand Down
65 changes: 59 additions & 6 deletions deepin-devicemanager/src/DeviceManager/DeviceInput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,24 @@ TomlFixMethod DeviceInput::setInfoFromTomlOneByOne(const QMap<QString, QString>
void DeviceInput::setInfoFromHwinfo(const QMap<QString, QString> &mapInfo)
{
qCDebug(appLog) << "setInfoFromHwinfo";
if (mapInfo.find("path") != mapInfo.end()) {
qCDebug(appLog) << "Path found in mapInfo, setting basic attributes.";
setAttribute(mapInfo, "name", m_Name);
setAttribute(mapInfo, "driver", m_Driver);
setAttribute(mapInfo, "path", m_SysPath);
setAttribute(mapInfo, "unique_id", m_VID_PID);
if (m_SysPath.contains("usb", Qt::CaseInsensitive)) {
m_Interface = "USB";
}
if (m_VID_PID.size() == 10) {
m_VID = m_VID_PID.mid(2, 4);
m_PID = m_VID_PID.last(4);
}
m_Enable = false;
// m_CanUninstall = !driverIsKernelIn(m_Driver);
qCWarning(appLog) << "Device disabled, skip further processing";
return;
}

//取触摸板的状态
if (mapInfo.find("Model") != mapInfo.end() && mapInfo["Model"].contains("Touchpad", Qt::CaseInsensitive)) {
Expand All @@ -125,6 +143,8 @@ void DeviceInput::setInfoFromHwinfo(const QMap<QString, QString> &mapInfo)
setAttribute(mapInfo, "Unique ID", m_UniqueID);
setAttribute(mapInfo, "Module Alias", m_Modalias);
setAttribute(mapInfo, "VID_PID", m_VID_PID);
setAttribute(mapInfo, "PID", m_PID);
setAttribute(mapInfo, "VID", m_VID);
m_PhysID = m_VID_PID;
// 防止Serial ID为空
if (m_SerialID.isEmpty()) {
Expand Down Expand Up @@ -500,6 +520,45 @@ const QString DeviceInput::getOverviewInfo()
EnableDeviceStatus DeviceInput::setEnable(bool e)
{
qCDebug(appLog) << "setEnable";

// 处理键盘设备
if (m_HardwareClass == "keyboard") {
qCDebug(appLog) << "setEnable keyboard device";

if (m_Interface.contains("USB", Qt::CaseInsensitive)) {
qCDebug(appLog) << "USB keyboard detected, using backend service";

QString vid = getVID();
QString pid = getPID();

if (vid.isEmpty() || pid.isEmpty()) {
qCWarning(appLog) << "Cannot enable keyboard: VID or PID is empty. VID:" << vid << "PID:" << pid;
return EDS_Faild;
}

// Use DeviceManager's validation function
QString safeVid, safePid;
if (!DeviceManager::instance()->validateKeyboardVidPid(vid, pid, safeVid, safePid)) {
qCWarning(appLog) << "VID or PID validation failed. VID:" << vid << "PID:" << pid;
return EDS_Faild;
}

bool res = DBusEnableInterface::getInstance()->enableKeyboard(safeVid, safePid, m_HardwareClass, m_Name, m_SysPath, m_VID_PID, e, m_Driver);
if (res) {
m_Enable = e;
qCDebug(appLog) << "Keyboard enable operation successful:" << e;
} else {
qCWarning(appLog) << "Keyboard enable operation failed";
}

return res ? EDS_Success : EDS_Faild;
} else {
qCDebug(appLog) << "Non-USB keyboard detected, cannot disable/enable using udev rules";
return EDS_Faild;
}
}

// 处理触摸板设备
if (m_Name.contains("Touchpad", Qt::CaseInsensitive)) {
qCDebug(appLog) << "setEnable touchpad";
DBusTouchPad::instance()->setEnable(e);
Expand Down Expand Up @@ -537,12 +596,6 @@ EnableDeviceStatus DeviceInput::setEnable(bool e)
bool DeviceInput::enable()
{
// qCDebug(appLog) << "enable";
// 键盘不可禁用
if (m_HardwareClass == "keyboard") {
// qCDebug(appLog) << "enable keyboard";
m_Enable = true;
}
// qCDebug(appLog) << "enable end";
return m_Enable;
}

Expand Down
1 change: 0 additions & 1 deletion deepin-devicemanager/src/DeviceManager/DeviceInput.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@ class DeviceInput : public DeviceBaseInfo
* @brief loadTableData:加载表头信息
*/
void loadTableData() override;

private:

/**
Expand Down
Loading