Как зеркалировать последовательный вывод ttyS0 на HDMI /dev/dri/card0?

Вопрос или проблема

Когда я запускаю свой одноплатный компьютер, я могу столкнуться с выводом из UART, который также называется /dev/ttyS0. Я хочу зеркалить все на свой HDMI порт, который находится на /dev/dri/card0.

Как я могу это сделать? Здесь я запускаю команду drm_info. Я использую Ubuntu 24.04 LTS.

>> drm_info
[?2004l
Узел: /dev/dri/card0
├───Драйвер: stm (STMicroelectronics SoC DRM) версия 1.0.0 (20170330)
│   ├───Поддерживается DRM_CLIENT_CAP_STEREO_3D
│   ├───Поддерживается DRM_CLIENT_CAP_UNIVERSAL_PLANES
│   ├───Поддерживается DRM_CLIENT_CAP_ATOMIC
│   ├───Поддерживается DRM_CLIENT_CAP_ASPECT_RATIO
│   ├───Поддерживается DRM_CLIENT_CAP_WRITEBACK_CONNECTORS
│   ├───DRM_CAP_DUMB_BUFFER = 1
│   ├───DRM_CAP_VBLANK_HIGH_CRTC = 1
│   ├───DRM_CAP_DUMB_PREFERRED_DEPTH = 0
│   ├───DRM_CAP_DUMB_PREFER_SHADOW = 0
│   ├───DRM_CAP_PRIME = 3
│   ├───DRM_CAP_TIMESTAMP_MONOTONIC = 1
│   ├───DRM_CAP_ASYNC_PAGE_FLIP = 0
│   ├───DRM_CAP_CURSOR_WIDTH = 64
│   ├───DRM_CAP_CURSOR_HEIGHT = 64
│   ├───DRM_CAP_ADDFB2_MODIFIERS = 1
│   ├───DRM_CAP_PAGE_FLIP_TARGET = 0
│   ├───DRM_CAP_CRTC_IN_VBLANK_EVENT = 1
│   ├───DRM_CAP_SYNCOBJ = 0
│   └───DRM_CAP_SYNCOBJ_TIMELINE = 0
├───Устройство: платформа st,stm32-ltdc
│   └───Доступные узлы: primary
├───Размер кадра
│   ├───Ширина: [0, 2048]
│   └───Высота: [0, 2048]
├───Разъемы
│   └───Разъем 0
│       ├───ID объекта: 32
│       ├───Тип: HDMI-A
│       ├───Статус: подключен
│       ├───Физический размер: 1210x680 мм
│       ├───Подпиксель: неизвестно
│       ├───Кодировщики: {0}
│       ├───Режимы
│       │   ├───[email protected] драйвер phsync pvsync 16:9 
│       │   ├───[email protected] драйвер phsync pvsync 16:9 
│       │   ├───[email protected] драйвер phsync pvsync 16:9 
│       │   ├───[email protected] драйвер phsync pvsync 
│       │   ├───[email protected] драйвер phsync pvsync 16:9 
│       │   ├───[email protected] драйвер phsync pvsync 16:9 
│       │   ├───[email protected] драйвер nhsync nvsync 16:9 
│       │   ├───[email protected] драйвер nhsync nvsync 4:3 
│       │   ├───[email protected] драйвер nhsync nvsync 16:9 
│       │   └───[email protected] драйвер nhsync nvsync 4:3 
│       └───Свойства
│           ├───"EDID" (неизменяемый): blob = 44
│           ├───"DPMS": enum {Включено, Режим ожидания, Приостановлено, Выключено} = Включено
│           ├───"состояние-соединения": enum {Хорошо, Плохо} = Хорошо
│           ├───"неклассический" (неизменяемый): диапазон [0, 1] = 0
│           ├───"ПЛИТКА" (неизменяемый): blob = 0
│           ├───"CRTC_ID" (атомарный): объект CRTC = 0
│           └───"дизеринг": enum {Выключено, Включено} = Выключено
├───Кодировщики
│   └───Кодировщик 0
│       ├───ID объекта: 31
│       ├───Тип: DPI
│       ├───CRTCS: {0}
│       └───Клоны: {0}
├───CRTCs
│   └───CRTC 0
│       ├───ID объекта: 38
│       ├───Легендарная информация
│       │   └───Размер гаммы: 256
│       └───Свойства
│           ├───"ACTIVE" (атомарный): диапазон [0, 1] = 0
│           ├───"MODE_ID" (атомарный): blob = 0
│           ├───"OUT_FENCE_PTR" (атомарный): диапазон [0, UINT64_MAX] = 0
│           ├───"VRR_ENABLED": диапазон [0, 1] = 0
│           ├───"GAMMA_LUT": blob = 0
│           └───"GAMMA_LUT_SIZE" (неизменяемый): диапазон [0, UINT32_MAX] = 256
└───Плоскости
    ├───Плоскость 0
    │   ├───ID объекта: 34
    │   ├───CRTCS: {0}
    │   ├───Легендарная информация
    │   │   ├───ID FB: 0
    │   │   └───Форматы:
    │   │       ├───ARGB8888 (0x34325241)
    │   │       ├───XRGB8888 (0x34325258)
    │   │       ├───RGB888 (0x34324752)
    │   │       ├───RGB565 (0x36314752)
    │   │       ├───ARGB1555 (0x35315241)
    │   │       ├───XRGB1555 (0x35315258)
    │   │       ├───ARGB4444 (0x32315241)
    │   │       ├───XRGB4444 (0x32315258)
    │   │       └───C8 (0x20203843)
    │   └───Свойства
    │       ├───"тип" (неизменяемый): enum {Накладка, Основной, Курсор} = Основной
    │       ├───"FB_ID" (атомарный): объект framebuffer = 0
    │       ├───"IN_FENCE_FD" (атомарный): srange [-1, INT32_MAX] = -1
    │       ├───"CRTC_ID" (атомарный): объект CRTC = 0
    │       ├───"CRTC_X" (атомарный): srange [INT32_MIN, INT32_MAX] = 0
    │       ├───"CRTC_Y" (атомарный): srange [INT32_MIN, INT32_MAX] = 0
    │       ├───"CRTC_W" (атомарный): диапазон [0, INT32_MAX] = 0
    │       ├───"CRTC_H" (атомарный): диапазон [0, INT32_MAX] = 0
    │       ├───"SRC_X" (атомарный): диапазон [0, UINT32_MAX] = 0
    │       ├───"SRC_Y" (атомарный): диапазон [0, UINT32_MAX] = 0
    │       ├───"SRC_W" (атомарный): диапазон [0, UINT32_MAX] = 0
    │       ├───"SRC_H" (атомарный): диапазон [0, UINT32_MAX] = 0
    │       ├───"IN_FORMATS" (неизменяемый): blob = 35
    │       │   └───DRM_FORMAT_MOD_LINEAR (0x0)
    │       │       ├───ARGB8888 (0x34325241)
    │       │       ├───XRGB8888 (0x34325258)
    │       │       ├───RGB888 (0x34324752)
    │       │       ├───RGB565 (0x36314752)
    │       │       ├───ARGB1555 (0x35315241)
    │       │       ├───XRGB1555 (0x35315258)
    │       │       ├───ARGB4444 (0x32315241)
    │       │       ├───XRGB4444 (0x32315258)
    │       │       └───C8 (0x20203843)
    │       ├───"alpha": диапазон [0, UINT16_MAX] = 65535
    │       └───"zpos" (неизменяемый): диапазон [0, 0] = 0
    └───Плоскость 1
        ├───ID объекта: 39
        ├───CRTCS: {0}
        ├───Легендарная информация
        │   ├───ID FB: 0
        │   └───Форматы:
        │       ├───ARGB8888 (0x34325241)
        │       ├───RGB888 (0x34324752)
        │       ├───RGB565 (0x36314752)
        │       ├───ARGB1555 (0x35315241)
        │       ├───ARGB4444 (0x32315241)
        │       └───C8 (0x20203843)
        └───Свойства
            ├───"тип" (неизменяемый): enum {Накладка, Основной, Курсор} = Накладка
            ├───"FB_ID" (атомарный): объект framebuffer = 0
            ├───"IN_FENCE_FD" (атомарный): srange [-1, INT32_MAX] = -1
            ├───"CRTC_ID" (атомарный): объект CRTC = 0
            ├───"CRTC_X" (атомарный): srange [INT32_MIN, INT32_MAX] = 0
            ├───"CRTC_Y" (атомарный): srange [INT32_MIN, INT32_MAX] = 0
            ├───"CRTC_W" (атомарный): диапазон [0, INT32_MAX] = 0
            ├───"CRTC_H" (атомарный): диапазон [0, INT32_MAX] = 0
            ├───"SRC_X" (атомарный): диапазон [0, UINT32_MAX] = 0
            ├───"SRC_Y" (атомарный): диапазон [0, UINT32_MAX] = 0
            ├───"SRC_W" (атомарный): диапазон [0, UINT32_MAX] = 0
            ├───"SRC_H" (атомарный): диапазон [0, UINT32_MAX] = 0
            ├───"IN_FORMATS" (неизменяемый): blob = 40
            │   └───DRM_FORMAT_MOD_LINEAR (0x0)
            │       ├───ARGB8888 (0x34325241)
            │       ├───RGB888 (0x34324752)
            │       ├───RGB565 (0x36314752)
            │       ├───ARGB1555 (0x35315241)
            │       ├───ARGB4444 (0x32315241)
            │       └───C8 (0x20203843)
            ├───"alpha": диапазон [0, UINT16_MAX] = 65535
            └───"zpos" (неизменяемый): диапазон [1, 1] = 1
[?2004hroot@stm32-os:~# 

Ответ или решение

Для того чтобы отобразить выходные данные с последовательного порта /dev/ttyS0 на HDMI-порт /dev/dri/card0, требуется несколько шагов. В этом ответе я объясню, как это сделать с использованием утилит Linux.

Шаг 1: Установка необходимых утилит

Для отображения данных с последовательного порта на экран потребуется установить некоторые утилиты. Убедитесь, что у вас установлены socat и fbset (или аналогичные утилиты для взаимодействия с фреймбуфером).

sudo apt update
sudo apt install socat fbset

Шаг 2: Чтение данных с последовательно порта

Мы будем использовать команду socat для считывания данных с порта /dev/ttyS0 и перенаправления их в виртуальный терминал. Предположим, что вы хотите отобразить данные в терминале на HDMI. Для этого создайте новый терминал и выполните следующую команду:

socat -u /dev/ttyS0 STDOUT | fbset -fb /dev/fb0

Однако, в большинстве случаев консольное приложение, работающее с фреймбуфером, не будет выводить текст в должном формате. Поэтому лучше использовать cat и echo.

Шаг 3: Отображение данных на HDMI

Вместо прямого вывода через socat, можно выполнить вывод данных в терминал таким образом:

socat -u /dev/ttyS0 - | while IFS= read -r line; do echo "$line" > /dev/tty1; done

Шаг 4: Создание скрипта для автоматизации

Для автоматизации процесса можно создать bash-скрипт. Создайте файл mirror_serial_to_hdmi.sh:

#!/bin/bash

# Открывает последовательный порт и перенаправляет выходные данные в HDMI
socat -u /dev/ttyS0 - | while IFS= read -r line; do
    echo "$line" > /dev/tty1
done

Сделайте файл исполняемым:

chmod +x mirror_serial_to_hdmi.sh

Шаг 5: Запуск скрипта при запуске системы

Если вы хотите, чтобы этот скрипт автоматически запускался при загрузке системы, вы можете добавить его в автозагрузку. Один из способов сделать это — добавить команду в файл /etc/rc.local, если он модифицируем:

# Включите редактирование rc.local
sudo nano /etc/rc.local

Добавьте строку перед exit 0:

/path/to/mirror_serial_to_hdmi.sh &

Заключение

Таким образом, вы сможете отображать данные, получаемые с последовательного порта /dev/ttyS0, на подключенном устройстве HDMI, представленном как /dev/dri/card0, используя утилиты socat и fbset. Не забудьте протестировать работу и убедиться, что все необходимые параметры последовательного порта (скорость передачи, биты данных и т.д.) настроены корректно.

Оцените материал
Добавить комментарий

Капча загружается...