From afa2f06b47a39372f81be00b9b165e29a6314acb Mon Sep 17 00:00:00 2001 From: Devin Lin Date: Mon, 15 Dec 2025 20:38:07 -0500 Subject: [PATCH] envmanager: Attempt to autodetect device id Attempt to use `/sys/firmware/devicetree/base/compatible` to autodetect the device id for device profiles. This approach is described here: https://phosh.mobi/posts/notch-support/#the-compatibles-string --- devices/README.md | 18 +++- .../{google-sargo.conf => google,sargo.conf} | 0 ...-enchilada.conf => oneplus,enchilada.conf} | 0 envmanager/devicepresets.cpp | 82 ++++++++++++++----- envmanager/devicepresets.h | 5 ++ 5 files changed, 82 insertions(+), 23 deletions(-) rename devices/configs/{google-sargo.conf => google,sargo.conf} (100%) rename devices/configs/{oneplus-enchilada.conf => oneplus,enchilada.conf} (100%) diff --git a/devices/README.md b/devices/README.md index 455b58b7..f501d461 100644 --- a/devices/README.md +++ b/devices/README.md @@ -7,17 +7,29 @@ This folder is where device-specific information is set. ### Usage as a distro -As a distribution, you can ship the device preset with the image by installing a file. +As a distribution, you can ship the device preset with the image by installing a file if the device id isn't autodetected. In `/etc/xdg/plasmamobilerc`, write: ```toml [Device] -device=oneplus-enchilada # replace with the device id +device=oneplus,enchilada # replace with the device id ``` This should be a file name that exists in `/usr/share/plasma-mobile-device-presets` (which are the files in the `configs` folder). +### Auto-detecting device names + +Envmanager reads `/sys/firmware/devicetree/base/compatible` to try to autodetect the device id. + +Use this command to determine your device's id: + +``` +$ sed -z 's/$/\n/' /sys/firmware/devicetree/base/compatible +oneplus,enchilada +qcom,sdm845 +``` + ### Adding a new device config See [spec.conf](spec.conf) for more details on the specification. If a setting is omitted in the file, then the system will use the default value. @@ -28,5 +40,5 @@ In order to test your changes, install the file to `/usr/share/plasma-mobile-dev ``` $ plasma-mobile-envmanager --apply-settings -$ plasmashell --replace +$ plasmashell -p org.kde.plasma.mobileshell --replace ``` diff --git a/devices/configs/google-sargo.conf b/devices/configs/google,sargo.conf similarity index 100% rename from devices/configs/google-sargo.conf rename to devices/configs/google,sargo.conf diff --git a/devices/configs/oneplus-enchilada.conf b/devices/configs/oneplus,enchilada.conf similarity index 100% rename from devices/configs/oneplus-enchilada.conf rename to devices/configs/oneplus,enchilada.conf diff --git a/envmanager/devicepresets.cpp b/envmanager/devicepresets.cpp index 3117e380..ea29a96e 100644 --- a/envmanager/devicepresets.cpp +++ b/envmanager/devicepresets.cpp @@ -20,17 +20,6 @@ DevicePresets::DevicePresets(QObject *parent) { } -void setKey(KConfigGroup &fallbackGroup, KConfigGroup &fromGroup, KConfigGroup &toGroup, QString fromKey, QString toKey) -{ - if (fromGroup.hasKey(fromKey)) { - toGroup.writeEntry(toKey, fromGroup.readEntry(fromKey), KConfigGroup::Notify); - } else if (fallbackGroup.hasKey(fromKey)) { - toGroup.writeEntry(toKey, fallbackGroup.readEntry(fromKey), KConfigGroup::Notify); - } else { - toGroup.deleteEntry(toKey, KConfigGroup::Notify); - } -} - void DevicePresets::initialize() { // Open mobile config to read from all locations (/etc/xdg/plasmamobilerc, ~/.config/plasmamobilerc, etc.) @@ -40,21 +29,36 @@ void DevicePresets::initialize() // Read device id const QString device = deviceGroup.readEntry(u"device"_s, {}); - QString presetFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, u"plasma-mobile-device-presets/"_s + device + ".conf"); - if (!QFile{presetFile}.exists()) { - presetFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, u"plasma-mobile-device-presets/default.conf"_s); - if (!QFile{presetFile}.exists()) { - qWarning() << "Failed to find any device preset file"; - return; + QString presetFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, u"plasma-mobile-device-presets/default.conf"_s); + + // Loop over detected devices and see if file exists + QString candidatePresetFile; + for (const QString &detectedDevice : detectDeviceString()) { + candidatePresetFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, u"plasma-mobile-device-presets/"_s + detectedDevice + ".conf"); + if (!candidatePresetFile.isEmpty()) { + presetFile = candidatePresetFile; + break; } } - // Open preset file /usr/share/plasma-mobile-device-presets/device.conf - auto presetConfig = KSharedConfig::openConfig(QFileInfo{presetFile}.absoluteFilePath(), KConfig::SimpleConfig); - if (!presetConfig) { + // Config-specified device has highest priority + candidatePresetFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, u"plasma-mobile-device-presets/"_s + device + ".conf"); + if (!candidatePresetFile.isEmpty()) { + presetFile = candidatePresetFile; + } else if (!device.isEmpty()) { + qWarning() << "Failed to find device preset file for" << device << "as defined in config"; + } + + if (QFile{presetFile}.exists()) { + qDebug() << "Using device preset file at" << presetFile; + } else { + qDebug() << "No device preset file could be found."; return; } + // Open preset file /usr/share/plasma-mobile-device-presets/[device].conf + auto presetConfig = KSharedConfig::openConfig(QFileInfo{presetFile}.absoluteFilePath(), KConfig::SimpleConfig); + // Write presets to ~/.config/plasma-mobile/plasmamobilerc // This is then read by components/mobileshellstate (PanelSettingsDBusObjectManager) auto presetPanelsGroup = KConfigGroup{presetConfig, u"Panels"_s}; @@ -86,3 +90,41 @@ void DevicePresets::initialize() m_mobileConfig->sync(); } + +void DevicePresets::setKey(KConfigGroup &fallbackGroup, KConfigGroup &fromGroup, KConfigGroup &toGroup, const QString &fromKey, const QString &toKey) +{ + if (fromGroup.hasKey(fromKey)) { + toGroup.writeEntry(toKey, fromGroup.readEntry(fromKey), KConfigGroup::Notify); + } else if (fallbackGroup.hasKey(fromKey)) { + toGroup.writeEntry(toKey, fallbackGroup.readEntry(fromKey), KConfigGroup::Notify); + } else { + toGroup.deleteEntry(toKey, KConfigGroup::Notify); + } +} + +QStringList DevicePresets::detectDeviceString() +{ + // On some systems, this file contains an identifier for the device + QFile deviceinfoFile{u"/sys/firmware/devicetree/base/compatible"_s}; + if (!deviceinfoFile.exists()) { + return {}; + } + + if (!deviceinfoFile.open(QIODevice::ReadOnly)) { + return {}; + } + + QByteArray data = deviceinfoFile.readAll(); + deviceinfoFile.close(); + + // Split by null bytes and convert to QStringList + QStringList result; + const QList parts = data.split('\0'); + for (const QByteArray &part : parts) { + if (!part.isEmpty()) { + result.append(QString::fromUtf8(part)); + } + } + + return result; +} diff --git a/envmanager/devicepresets.h b/envmanager/devicepresets.h index 0d5c57e9..18b9dd9c 100644 --- a/envmanager/devicepresets.h +++ b/envmanager/devicepresets.h @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2025 Devin Lin // SPDX-License-Identifier: GPL-2.0-or-later +#pragma once + #include #include @@ -16,5 +18,8 @@ public: void initialize(); private: + void setKey(KConfigGroup &fallbackGroup, KConfigGroup &fromGroup, KConfigGroup &toGroup, const QString &fromKey, const QString &toKey); + QStringList detectDeviceString(); + KSharedConfig::Ptr m_mobileConfig; };