Decode full monitor vendor name from EDID using hwdata
Test Plan: KScreen now shows "Dell Inc." instead of DEL and "Eizo Nano Corporation" instead of ENC in output names, which matches closer to what's written on my monitors. Reviewers: graesslin, davidedmundson, #plasma Reviewed By: davidedmundson, #plasma Subscribers: apol, feverfew, ngraham, davidedmundson, mart, kwin, sebas Tags: #kwin Differential Revision: https://phabricator.kde.org/D10041
This commit is contained in:
parent
ce306a598a
commit
33a1777a5a
6 changed files with 121 additions and 20 deletions
|
@ -287,6 +287,14 @@ set_package_properties(Libcap PROPERTIES
|
|||
)
|
||||
set(HAVE_LIBCAP ${Libcap_FOUND})
|
||||
|
||||
find_package(hwdata)
|
||||
set_package_properties(hwdata PROPERTIES
|
||||
TYPE RUNTIME
|
||||
PURPOSE "Runtime-only dependency needed for mapping monitor hardware vendor IDs to full names"
|
||||
URL "https://github.com/vcrhonek/hwdata"
|
||||
)
|
||||
set(HAVE_HWDATA ${hwdata_FOUND})
|
||||
|
||||
include(ECMQMLModules)
|
||||
ecm_find_qmlmodule(QtQuick 2.3)
|
||||
ecm_find_qmlmodule(QtQuick.Controls 1.2)
|
||||
|
|
47
cmake/modules/Findhwdata.cmake
Normal file
47
cmake/modules/Findhwdata.cmake
Normal file
|
@ -0,0 +1,47 @@
|
|||
# - Try to find hwdata
|
||||
# Once done this will define
|
||||
#
|
||||
# hwdata_DIR - The hwdata directory
|
||||
# hwdata_PNPIDS_FILE - File with mapping of hw vendor IDs to names
|
||||
# hwdata_FOUND - The hwdata directory exists and contains pnp.ids file
|
||||
|
||||
# Copyright (c) 2020 Daniel Vrátil <dvratil@kde.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
find_path(hwdata_DIR NAMES hwdata/pnp.ids HINTS /usr/share ENV XDG_DATA_DIRS)
|
||||
find_file(hwdata_PNPIDS_FILE NAMES hwdata/pnp.ids HINTS /usr/share)
|
||||
if (hwdata_DIR-NOTFOUND OR hwdata_PNPIDS_FILE-NOTFOUND)
|
||||
set(hwdata_FOUND FALSE)
|
||||
else()
|
||||
set(hwdata_FOUND TRUE)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(hwdata DEFAULT_MSG hwdata_FOUND hwdata_DIR hwdata_PNPIDS_FILE)
|
||||
|
||||
mark_as_advanced(hwdata_FOUND hwdata_DIR hwdata_PNPIDS_FILE)
|
||||
endif()
|
|
@ -25,6 +25,7 @@
|
|||
#cmakedefine01 HAVE_BREEZE_DECO
|
||||
#cmakedefine01 HAVE_LIBCAP
|
||||
#cmakedefine01 HAVE_SCHED_RESET_ON_FORK
|
||||
#cmakedefine01 HAVE_HWDATA
|
||||
#if HAVE_BREEZE_DECO
|
||||
#define BREEZE_KDECORATION_PLUGIN_ID "${BREEZE_KDECORATION_PLUGIN_ID}"
|
||||
#endif
|
||||
|
@ -41,3 +42,7 @@
|
|||
#define XCB_ICCCM_WM_STATE_NORMAL 1
|
||||
#define XCB_ICCCM_WM_STATE_ICONIC 3
|
||||
#endif
|
||||
|
||||
#if HAVE_HWDATA
|
||||
#cmakedefine HWDATA_PNPIDS_FILE "@hwdata_PNPIDS_FILE@"
|
||||
#endif
|
||||
|
|
|
@ -301,7 +301,9 @@ void DrmOutput::initUuid()
|
|||
void DrmOutput::initOutputDevice(drmModeConnector *connector)
|
||||
{
|
||||
QString manufacturer;
|
||||
if (!m_edid.eisaId().isEmpty()) {
|
||||
if (!m_edid.vendor().isEmpty()) {
|
||||
manufacturer = QString::fromLatin1(m_edid.vendor());
|
||||
} else if (!m_edid.eisaId().isEmpty()) {
|
||||
manufacturer = QString::fromLatin1(m_edid.eisaId());
|
||||
}
|
||||
|
||||
|
@ -379,7 +381,6 @@ bool DrmOutput::isCurrentMode(const drmModeModeInfo *mode) const
|
|||
&& mode->type == m_mode.type
|
||||
&& qstrcmp(mode->name, m_mode.name) == 0;
|
||||
}
|
||||
|
||||
void DrmOutput::initEdid(drmModeConnector *connector)
|
||||
{
|
||||
DrmScopedPointer<drmModePropertyBlobRes> edid;
|
||||
|
|
|
@ -20,6 +20,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*********************************************************************/
|
||||
|
||||
#include "edid.h"
|
||||
#include "config-kwin.h"
|
||||
|
||||
#include <QFile>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
@ -40,25 +43,9 @@ static QSize parsePhysicalSize(const uint8_t *data)
|
|||
return QSize(data[0x15], data[0x16]) * 10;
|
||||
}
|
||||
|
||||
static QByteArray parseEisaId(const uint8_t *data)
|
||||
static QByteArray parsePnpId(const uint8_t *data)
|
||||
{
|
||||
for (int i = 72; i <= 108; i += 18) {
|
||||
// Skip the block if it isn't used as monitor descriptor.
|
||||
if (data[i]) {
|
||||
continue;
|
||||
}
|
||||
if (data[i + 1]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We have found the EISA ID, it's stored as ASCII.
|
||||
if (data[i + 3] == 0xfe) {
|
||||
return QByteArray(reinterpret_cast<const char *>(&data[i + 5]), 12).trimmed();
|
||||
}
|
||||
}
|
||||
|
||||
// If there isn't an ASCII EISA ID descriptor, try to decode PNP ID from
|
||||
// three 5 bit words packed into 2 bytes:
|
||||
// Decode PNP ID from three 5 bit words packed into 2 bytes:
|
||||
//
|
||||
// | Byte | Bit |
|
||||
// | | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||
|
@ -80,6 +67,28 @@ static QByteArray parseEisaId(const uint8_t *data)
|
|||
return QByteArray(pnpId);
|
||||
}
|
||||
|
||||
|
||||
static QByteArray parseEisaId(const uint8_t *data)
|
||||
{
|
||||
for (int i = 72; i <= 108; i += 18) {
|
||||
// Skip the block if it isn't used as monitor descriptor.
|
||||
if (data[i]) {
|
||||
continue;
|
||||
}
|
||||
if (data[i + 1]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We have found the EISA ID, it's stored as ASCII.
|
||||
if (data[i + 3] == 0xfe) {
|
||||
return QByteArray(reinterpret_cast<const char *>(&data[i + 5]), 12).trimmed();
|
||||
}
|
||||
}
|
||||
|
||||
// If there isn't an ASCII EISA ID descriptor, try to decode PNP ID
|
||||
return parsePnpId(data);
|
||||
}
|
||||
|
||||
static QByteArray parseMonitorName(const uint8_t *data)
|
||||
{
|
||||
for (int i = 72; i <= 108; i += 18) {
|
||||
|
@ -131,6 +140,25 @@ static QByteArray parseSerialNumber(const uint8_t *data)
|
|||
return QByteArray();
|
||||
}
|
||||
|
||||
static QByteArray parseVendor(const uint8_t *data)
|
||||
{
|
||||
#if HAVE_HWDATA
|
||||
const auto pnpId = parsePnpId(data);
|
||||
|
||||
// Map to vendor name
|
||||
QFile pnpFile(QStringLiteral(HWDATA_PNPIDS_FILE));
|
||||
if (pnpFile.exists() && pnpFile.open(QIODevice::ReadOnly)) {
|
||||
while (!pnpFile.atEnd()) {
|
||||
const auto line = pnpFile.readLine();
|
||||
if (line.startsWith(pnpId)) {
|
||||
return line.mid(4).trimmed();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return {};
|
||||
}
|
||||
|
||||
Edid::Edid()
|
||||
{
|
||||
}
|
||||
|
@ -151,6 +179,7 @@ Edid::Edid(const void *data, uint32_t size)
|
|||
m_eisaId = parseEisaId(bytes);
|
||||
m_monitorName = parseMonitorName(bytes);
|
||||
m_serialNumber = parseSerialNumber(bytes);
|
||||
m_vendor = parseVendor(bytes);
|
||||
|
||||
m_isValid = true;
|
||||
}
|
||||
|
@ -180,4 +209,9 @@ QByteArray Edid::serialNumber() const
|
|||
return m_serialNumber;
|
||||
}
|
||||
|
||||
QByteArray Edid::vendor() const
|
||||
{
|
||||
return m_vendor;
|
||||
}
|
||||
|
||||
} // namespace KWin
|
||||
|
|
|
@ -62,8 +62,14 @@ public:
|
|||
*/
|
||||
QByteArray serialNumber() const;
|
||||
|
||||
/**
|
||||
* Returns the name of the vendor.
|
||||
*/
|
||||
QByteArray vendor() const;
|
||||
|
||||
private:
|
||||
QSize m_physicalSize;
|
||||
QByteArray m_vendor;
|
||||
QByteArray m_eisaId;
|
||||
QByteArray m_monitorName;
|
||||
QByteArray m_serialNumber;
|
||||
|
|
Loading…
Reference in a new issue