Вопрос или проблема
Цель состоит в том, чтобы получить идентификатор производителя и продукта, а также серийный номер дисплея на платформе Linux. В конечном итоге мне нужно получить эту информацию в программе на C++. Но я также принимаю способ получения информации через командную строку.
Такая информация доступна через подсистему /sys/class/drm
. Инструменты, такие как xrandr
, широко используют ее. В этой подсистеме теперь имеется директория для каждого дисплея с файлом edid
, Расширенные данные идентификации дисплея.
На системах на базе Debian доступны два пакета: edid-decode
и read-edid
. Оба, похоже, работают нормально, но на старых моделях read-edid
работает достаточно хорошо, в то время как edid-decode
выдает ошибки:
EDID block does NOT conform to EDID 1.3!
Detailed block string not properly terminated
EDID block does not conform at all!
Bad year of manufacture
Поэтому я бы рекомендовал установить пакет read-edid
. После установки используйте команду parse-edid
, как показано ниже:
$ parse-edid < /sys/class/drm/card0-HDMI-A-1/edid
Checksum Correct
Section "Monitor"
Identifier "X20G-NagaIII"
ModelName "X20G-NagaIII"
VendorName "SPT"
# Монитор произведен на 42-й неделе 2005 года
# Версия EDID 1.3
# Цифровой дисплей
DisplaySize 410 310
Gamma 2.20
Option "DPMS" "true"
Horizsync 30-92
VertRefresh 40-86
# Максимальная частота пикселей составляет 170 МГц
Другая команда get-edid
соединяется с шиной i2c и автоматически определяет, какие дисплеи подключены и какие данные доступны. Теперь, конечно, это не метод на C++, но эти два инструмента, скорее всего, написаны на C. Рассмотрите возможность ознакомления с их исходным кодом и обратите внимание на используемые библиотеки.
У меня было два монитора Dell U3014, которые были почти идентичны (разницы в выводе parse-edid не было), но я видел разные серийные номера при проверке файла edid для 5-го и 6-го Display Port:
# Сравнить вывод edid
diff -a /sys/class/drm/card0-DP-{5,6}/edid
1c1
PT�K���qO�@�����h��@.`0 6��!�P1V6N45V001L
---
PT�K���qO�@�����h��@.`0 6��!�P1V6N45V002L
4c4
< ��P� # �:�q8-@X,E��!�q X,%��!�rQ� n(U��!�
---
> ��P� # �:�q8-@X,E��!�q X,%��!�rQ� n(U��!�
# Более лучший вид только серийных номеров:
grep -ao 'P1V6N45V00.L' /sys/class/drm/card0-DP-*/edid
/sys/class/drm/card0-DP-5/edid:P1V6N45V001L
/sys/class/drm/card0-DP-6/edid:P1V6N45V002L
Также стоит отметить, что card0-DP были пронумерованы 1-8, в то время как в arandr они были указаны как 0-7. Таким образом, чтобы сопоставить edid с arandr, нужно вычитать один: DP-5=DP-4 и DP-6=DP-5.
на системе gnome:
$ grep -E 'product|serial' ~/.config/monitors.xml
Ответ или решение
Чтобы получить идентификатор производителя, идентификатор продукта и серийный номер дисплея на платформе Linux, вы можете воспользоваться механизмом /sys/class/drm
, который предоставляет доступ к информации о дисплеях через систему управления графическими устройствами в ядре Linux.
1. Использование командной строки
Существует несколько инструментов, которые помогут получить нужную информацию о дисплее:
Установка инструмента
Рекомендуется установить пакет read-edid
, который включает в себя команды parse-edid
и get-edid
. Чтобы установить его на Debian-подобной системе, используйте следующую команду:
sudo apt-get install read-edid
Получение информации из EDID
После установки read-edid
, вы можете использовать команду parse-edid
для извлечения информации о дисплее из файла edid
. Пример команды:
parse-edid < /sys/class/drm/card0-HDMI-A-1/edid
Заметьте, что путь к edid
может отличаться в зависимости от конфигурации вашего устройства. Для получения списка доступных дисплеев можно воспользоваться командой:
ls /sys/class/drm/
Это позволит вам увидеть все подключенные графические устройства, например, card0-DP-1
, card0-HDMI-A-1
и т.д.
Фильтрация данных
С помощью команды grep
можно фильтровать необходимую информацию. Например, чтобы извлечь только серийные номера из файлов edid
для нескольких дисплеев:
grep -ao 'P1V6N45V00.L' /sys/class/drm/card0-DP*/edid
Это даст вам список серийных номеров для всех дисплеев, подключенных через DisplayPort.
2. Получение информации программным способом на C++
Если вы хотите реализовать получение этой информации программным способом на C++, можно использовать системные вызовы для чтения файлов. Пример реализации может выглядеть следующим образом:
#include <iostream>
#include <fstream>
#include <string>
void readEdid(const std::string& filename) {
std::ifstream edidFile(filename);
if (!edidFile) {
std::cerr << "Could not open the file: " << filename << std::endl;
return;
}
std::string line;
while (std::getline(edidFile, line)) {
if (line.find("Serial Number") != std::string::npos ||
line.find("Name") != std::string::npos) {
std::cout << line << std::endl;
}
}
edidFile.close();
}
int main() {
readEdid("/sys/class/drm/card0-HDMI-A-1/edid"); // Укажите правильный путь
return 0;
}
3. Дополнительные советы
- Для более детального изучения, вы можете обратиться к коду утилит
get-edid
иparse-edid
, чтобы понять, какие библиотеки и методы они используют для работы с данными EDID. - Помните, что в зависимости от конфигурации вашей системы и оборудования, пути к устройствам могут варьироваться. Ознакомьтесь с выводом команды
ls /sys/class/drm/
для уточнения.
Заключение
Получение идентификатора производителя и серийного номера дисплея на Linux – это простая, но эффективная задача, которую можно выполнять как через командную строку, так и программно на C++. Следуя описанным шагам, вы сможете быстро получить необходимую информацию о вашем дисплее.