# 6.2-inch_USB_Display_Linux_APP **Repository Path**: rses/6.2-inch_USB_Display_Linux_APP ## Basic Information - **Project Name**: 6.2-inch_USB_Display_Linux_APP - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-24 - **Last Updated**: 2026-07-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # USB Display 这是一个运行在 Linux 设备端的 LVGL 副屏程序。项目通过 DRM 直接驱动一块 `1280 x 452` 的竖屏面板,在空闲状态下显示本地待机页面和背景视频;当主机通过 USB 连接后,程序切换为 USB 外接显示模式,接收 JPEG 帧并实时显示,同时把本机触摸事件转发为 USB HID 多点触控报告。 ## 核心功能 - 基于 `LVGL + DRM` 渲染 UI,主程序入口在 [main.c](/home/ubuntu/桌面/USB_Display/main.c)。 - 通过 FunctionFS 接收 USB 主机发送的压缩视频帧,当前只处理 `type == 3` 的 JPEG 帧。 - USB 断开时显示空闲页,USB 接入后隐藏空闲页并显示 USB 画面。 - 从 `/dev/input/event0` 读取触摸事件: - 空闲页模式下供 LVGL 本地交互使用。 - USB 串流模式下转换成 HID 多点触摸报告并转发给主机。 - 暴露 USB 大容量存储功能,将设备 `userdata` 分区导出给主机。 - 在空闲页中提供设置面板,可控制: - 空闲页隐藏状态 - HID 触摸转发开关 - 亮度值 - 背景视频选择 - 在 `/userdata` 未完成初始化时,空闲页会提示执行初始化流程,并调用外部脚本完成默认资源准备。 - 后台视频播放器基于 FFmpeg 解码本地视频并循环播放,作为空闲页背景。 ## 运行流程 程序主流程位于 [main.c](/home/ubuntu/桌面/USB_Display/main.c): 1. 初始化 LVGL、DRM 显示和 CPU 亲和性。 2. 加载配置文件 `/oem/settings.conf`。 3. 初始化触摸路由器,输入源固定为 `/dev/input/event0`。 4. 创建空闲页 UI。 5. 初始化 `userdata` 状态检查。 6. 启动 USB Gadget 显示服务: - Vendor-specific bulk 通道用于视频帧接收 - HID 接口用于触摸回传 - UMS 接口用于导出 `userdata` 7. 主循环中持续处理: - USB 帧接收与 JPEG 解码显示 - USB 连接状态切换 - 触摸模式切换 - `userdata` 初始化状态同步到 UI - LVGL 定时器驱动 ## 模块说明 ### `main.c` 负责系统初始化、USB 帧显示层创建、配置重载和主循环调度。 ### `usb_display.c` 负责 USB Gadget 侧逻辑: - 配置 `configfs` - 挂载 `FunctionFS` - 创建设备描述符和 HID 描述符 - 接收主机发送的帧数据 - 提供最新一帧的无锁近似消费接口 - 管理 `userdata` 的 UMS 导出状态 代码里写死了 gadget 名称 `rk_udisp`,并使用 `/sys/kernel/config/usb_gadget/...`、`/dev/ffs-udisp/...` 等系统路径。 ### `touch_router.c` 负责从 Linux input 子系统读取触摸数据,并在两种模式间切换: - `LVGL` 本地输入模式 - `USB HID` 转发模式 触摸坐标会从面板坐标系 `452 x 1280` 映射到主机坐标系 `1280 x 452`,包含旋转关系。 ### `idle_page.c` 负责待机界面、设置页和媒体选择逻辑,包括: - 背景视频显示 - USB 未连接状态提示 - 设置按钮和设置面板 - 背景视频扫描与缩略图生成 - `userdata` 初始化提示与进度展示 - MiSans 字体加载 相关固定资源路径: - 字体优先路径:`/usr/share/lvgl-usb-display/MiSans-Normal.ttf` - 本地回退路径:`/home/ubuntu/桌面/lvgl_car/MiSans-Normal.ttf` - 默认背景视频:`/userdata/idle.mp4` ### `video_player.c` 使用 FFmpeg 解码本地视频并转换为 LVGL 原生 `BGRA` 像素格式,采用 3 槽环形缓冲,解码和显示分线程执行。 ### `settings.c` 负责配置读写和默认值管理。当前默认值如下: - `page_hidden=false` - `hid_enabled=true` - `brightness=200` - `background_video=/userdata/idle.mp4` ### `userdata_init.c` 负责检测 `userdata` 是否完成工厂初始化,并在用户触发时执行: - 检查挂载点 `/userdata` - 检查标记文件 `/userdata/.factory_initialized` - 检查默认视频 `/userdata/idle.mp4` - 执行外部脚本 `/usr/bin/init-userdata.sh` - 从 `/run/userdata-init.progress` 和 `/run/userdata-init.status` 读取进度和状态文本 ## 依赖 从 [Makefile](/home/ubuntu/桌面/USB_Display/Makefile) 可以确认该项目依赖以下组件: - 交叉编译工具链:`arm-buildroot-linux-gnueabihf` - `LVGL` - `lv_drivers` - `libdrm` - `librga` - `libturbojpeg` - `FFmpeg`: - `libavformat` - `libavcodec` - `libavutil` - `libswscale` - `pthread` - 目标内核需要支持: - DRM 显示 - Linux input - USB Gadget `configfs` - FunctionFS ## 构建 项目默认使用交叉编译,`Makefile` 中的默认 SDK 路径如下: ```makefile SDK_ROOT ?= /home/ubuntu/yu-atk-dlrk3506_linux6 HOST_DIR ?= $(SDK_ROOT)/buildroot/output/atk_dlrk3506/host SYSROOT ?= $(HOST_DIR)/arm-buildroot-linux-gnueabihf/sysroot CROSS_COMPILE ?= $(HOST_DIR)/bin/arm-buildroot-linux-gnueabihf- ``` 直接构建: ```bash make ``` 常用命令: ```bash make info make clean ``` 如果 SDK 不在默认位置,可以显式覆盖: ```bash make SDK_ROOT=/path/to/sdk ``` 输出二进制默认名为: ```text lvgl_usb_display ``` ## 部署与启动 仓库提供了 SysV 风格启动脚本 [deploy/S99lvgl-usb-display](/home/ubuntu/桌面/USB_Display/deploy/S99lvgl-usb-display)。 脚本行为: - 启动 `/usr/bin/lvgl_usb_display` - 记录 PID 到 `/var/run/lvgl-usb-display.pid` - 输出日志到 `/var/log/lvgl-usb-display.log` - 停止时主动解绑 USB Gadget 的 `UDC` 典型部署时还需要准备: - `/usr/bin/lvgl_usb_display` - `/usr/share/lvgl-usb-display/MiSans-Normal.ttf` - `/usr/share/lvgl-usb-display/defaults` - `/usr/bin/init-userdata.sh` ## 配置文件 程序启动时通过下面的调用加载配置: ```c settings_init("/oem/settings.conf", NULL); ``` 因此当前有效配置文件只有: ```text /oem/settings.conf ``` 支持的键值如下: ```ini page_hidden=0 hid_enabled=1 brightness=200 background_video=/userdata/idle.mp4 ``` 字段含义: - `page_hidden`:是否隐藏空闲页主内容 - `hid_enabled`:USB 模式下是否启用触摸 HID 转发 - `brightness`:亮度值,范围 `0-255` - `background_video`:空闲页背景视频路径 程序会在配置变化时回写该文件;如果主配置不可写,则仅保留内存中的值。 ## 设备侧固定路径与约束 这个项目不是完全参数化的,代码中包含较多板级固定路径和假设,迁移前需要重点检查: - 显示分辨率固定为 `1280 x 452` - 触摸输入设备固定为 `/dev/input/event0` - `userdata` 挂载点固定为 `/userdata` - 配置文件固定为 `/oem/settings.conf` - USB Gadget 依赖 `/sys/kernel/config/usb_gadget` - FunctionFS 挂载点固定为 `/dev/ffs-udisp` - 字体和默认资源路径为 `/usr/share/lvgl-usb-display/...` - `userdata` 初始化脚本固定为 `/usr/bin/init-userdata.sh` 如果目标板不是同一套系统布局,通常至少要调整这些路径和设备名。 ## USB 协议侧观察 从当前实现可以确认以下事实: - 帧头长度固定为 `16` 字节。 - 最大单帧限制为 `2 MiB`。 - 当前图像解码路径只接受尺寸严格等于 `1280 x 452` 的 JPEG。 - 当 `1500 ms` 内没有收到新帧时,连接状态可能被判定为失活。 - USB HID 报告支持最多 `5` 个触点。 如果主机侧协议发生变化,优先检查 [usb_display.c](/home/ubuntu/桌面/USB_Display/usb_display.c) 与 [touch_router.c](/home/ubuntu/桌面/USB_Display/touch_router.c)。 ## 目录概览 ```text . ├── main.c 主程序入口 ├── usb_display.c/.h USB Gadget 显示与 UMS ├── touch_router.c/.h 触摸输入与 HID 转发 ├── idle_page.c/.h 空闲页和设置页 ├── video_player.c/.h 背景视频播放 ├── settings.c/.h 配置管理 ├── userdata_init.c/.h userdata 初始化状态机 ├── cpu_affinity.c/.h 线程 CPU 亲和性 ├── deploy/ 部署脚本 ├── tools/ 字体裁剪工具 ├── lvgl/ 第三方 LVGL └── lv_drivers/ 第三方 LVGL 驱动 ``` ## 适用场景 这个项目更适合以下用途: - 车载/中控类副屏 - Linux 设备作为 USB 扩展显示器