[lvgl]如何优雅地向lv_port_linux中添加tslib支持

原始仓库地址:lvgl/lv_port_linux: LVGL configured to work with a standard Linux framebuffer

直接上改完后的CMakeLists.txt:

C 复制代码
cmake_minimum_required(VERSION 3.11)
project(lvgl)

option(WERROR "Treat warnings as errors for LVGL targets" OFF)

# Set policy to allow to run the target_link_libraries cmd on targets that are build
# in another directory.
# Currently, the linking is not handled by env_support/cmake/os.cmakel
# This means that if a driver is enabled and it requires linking an external library
# it needs to be handled in the top-level project.

cmake_policy(SET CMP0079 NEW)

# Uncomment if the program needs debugging
#set(CMAKE_BUILD_TYPE Debug)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

set(CMAKE_C_STANDARD 99) # LVGL officially supports C99 and above
set(CMAKE_CXX_STANDARD 17) #C17
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic")

option(CONFIG "Config to use leave empty for `lv_conf.defaults`" "default")

set(LV_CONF_DEFAULTS_PATH "${CMAKE_SOURCE_DIR}/lv_conf.defaults")
set(LV_CONF_DEFAULTS_OLD_PATH "${CMAKE_SOURCE_DIR}/lv_conf.defaults.old")

# If CONFIG is not default, copy the selected config to lv_conf.defaults
if(NOT CONFIG STREQUAL "default")
    set(CONFIG_FILE "${CMAKE_SOURCE_DIR}/configs/${CONFIG}.defaults")
    
    # Verify the config file exists
    if(NOT EXISTS "${CONFIG_FILE}")
        message(FATAL_ERROR "Config file not found: ${CONFIG_FILE}")
    endif()
    
    # Backup the current lv_conf.defaults to lv_conf.defaults.old
    if(EXISTS "${LV_CONF_DEFAULTS_PATH}")
        file(RENAME "${LV_CONF_DEFAULTS_PATH}" "${LV_CONF_DEFAULTS_OLD_PATH}")
        message(STATUS "Backed up lv_conf.defaults to lv_conf.defaults.old")
    endif()
    
    # Copy the config file to lv_conf.defaults
    configure_file("${CONFIG_FILE}" "${LV_CONF_DEFAULTS_PATH}" COPYONLY)
    message(STATUS "Copied configs/${CONFIG}.defaults to ${LV_CONF_DEFAULTS_PATH}")
    message(STATUS "Using config: configs/${CONFIG}.defaults")
else()
    if(NOT EXISTS "${LV_CONF_DEFAULTS_PATH}")
        message(FATAL_ERROR "Config file not found: ${LV_CONF_DEFAULTS_PATH}")
    endif()
    message(STATUS "Using default lv_conf.defaults")
    message(STATUS "Using config: ${LV_CONF_DEFAULTS_PATH}")
endif()


set(LV_BUILD_SET_CONFIG_OPTS ON CACHE BOOL
    "create CMAKE variables from lv_conf_internal.h" FORCE)

set(LV_BUILD_CONF_PATH
    "${CMAKE_BINARY_DIR}/lv_conf.h"
    CACHE PATH "path to lv_conf.h" FORCE)

set(LVGL_TEMPLATE_PATH "${CMAKE_SOURCE_DIR}/lvgl/lv_conf_template.h")
set(GENERATE_SCRIPT_PATH "${CMAKE_SOURCE_DIR}/lvgl/scripts/generate_lv_conf.py")

configure_file(${LVGL_TEMPLATE_PATH} ${CMAKE_BINARY_DIR}/lv_conf_template.h
               COPYONLY)
configure_file(${LV_CONF_DEFAULTS_PATH} ${CMAKE_BINARY_DIR}/lv_conf.defaults
               COPYONLY)
configure_file(${GENERATE_SCRIPT_PATH} ${CMAKE_BINARY_DIR}/generate_lv_conf.py
               COPYONLY)

execute_process(
  COMMAND
    ${Python3_EXECUTABLE} ${GENERATE_SCRIPT_PATH} --template
    ${LVGL_TEMPLATE_PATH} --defaults ${LV_CONF_DEFAULTS_PATH} --config
    ${LV_BUILD_CONF_PATH}
  RESULT_VARIABLE config_result
  OUTPUT_VARIABLE config_output
  ERROR_VARIABLE config_output)

if(NOT config_result EQUAL 0)
  message(FATAL_ERROR "Failed to generate lv_conf.h: ${config_output}")
endif()

message(STATUS "${LV_BUILD_CONF_PATH} generated successfully")

add_subdirectory(lvgl)

//添加交叉编译选项
option(CROSS_BUILD "Enable cross-compiling mode" OFF)

if (CONFIG_LV_USE_EVDEV)
    message("Including EVDEV support")

//对evdev使用交叉编译条件判断
    if(CROSS_BUILD)
        message(STATUS "Detected cross-compilation environment")
        
        //交叉编译环境下用到的库与头文件目录
        set(EVDEV_LIBRARIES ${STAGING_DIR}/usr/lib/libevdev.so)
        set(EVDEV_INCLUDE_DIRS ${STAGING_DIR}/usr/include)

        list(APPEND PKG_CONFIG_LIB ${EVDEV_LIBRARIES})
        list(APPEND PKG_CONFIG_INC ${EVDEV_INCLUDE_DIRS})
    else()
        message(STATUS "Native build (using host pkg-config)")

        find_package(PkgConfig REQUIRED)
        pkg_check_modules(EVDEV REQUIRED libevdev)

        list(APPEND PKG_CONFIG_LIB ${EVDEV_LIBRARIES})
        list(APPEND PKG_CONFIG_INC ${EVDEV_INCLUDE_DIRS})
    endif()

    list(APPEND LV_LINUX_BACKEND_SRC src/lib/indev_backends/evdev.c)

endif()

//在此处添加TSLIB支持
if (CONFIG_LV_USE_TSLIB)

    message("Including TSLIB support")

    //必须使用交叉编译条件
    if(CROSS_BUILD)
        message(STATUS "Detected cross-compilation environment")
        
        //交叉编译环境下用到的库与头文件目录
        set(TSLIB_LIBRARIES ${STAGING_DIR}/usr/lib/libts.so)
        set(TSLIB_INCLUDE_DIRS ${STAGING_DIR}/usr/include)

        list(APPEND PKG_CONFIG_LIB ${TSLIB_LIBRARIES})
        list(APPEND PKG_CONFIG_INC ${TSLIB_INCLUDE_DIRS})
    endif()

    //添加源文件到编译列表
    list(APPEND LV_LINUX_BACKEND_SRC src/lib/indev_backends/tslib.c)

endif()


if (CONFIG_LV_USE_LINUX_DRM)

    message("Including DRM support")
    find_package(PkgConfig REQUIRED)
    pkg_check_modules(LIBDRM REQUIRED libdrm)

    list(APPEND PKG_CONFIG_LIB ${LIBDRM_LIBRARIES})
    list(APPEND PKG_CONFIG_INC ${LIBDRM_INCLUDE_DIRS})
    list(APPEND LV_LINUX_BACKEND_SRC src/lib/display_backends/drm.c)

endif()

if (CONFIG_LV_USE_LINUX_DRM_GBM_BUFFERS OR CONFIG_LV_LINUX_DRM_USE_EGL)

    message("Including GBM support")

    find_package(PkgConfig REQUIRED)
    pkg_check_modules(LIBGBM REQUIRED gbm)

    list(APPEND PKG_CONFIG_LIB ${LIBGBM_LIBRARIES})
    list(APPEND PKG_CONFIG_INC ${LIBGBM_INCLUDE_DIRS})

endif()

if (CONFIG_LV_USE_LIBINPUT)
    message("Including libinput support")

    find_package(PkgConfig REQUIRED)
    pkg_check_modules(LIBINPUT REQUIRED libinput)

    list(APPEND PKG_CONFIG_LIB ${LIBINPUT_LIBRARIES})
    list(APPEND PKG_CONFIG_INC ${LIBINPUT_INCLUDE_DIRS})

endif()

if (CONFIG_LV_USE_FREETYPE)
    message("Including Freetype support")

    find_package(PkgConfig REQUIRED)
    pkg_check_modules(LIBFREETYPE REQUIRED freetype2)

    list(APPEND PKG_CONFIG_LIB ${LIBFREETYPE_LIBRARIES})
    list(APPEND PKG_CONFIG_INC ${LIBFREETYPE_INCLUDE_DIRS})

endif()

if (CONFIG_LV_USE_SDL OR CONFIG_LV_USE_DRAW_SDL)

    message("Including SDL2 support")
    find_package(PkgConfig REQUIRED)
    pkg_check_modules(SDL2 REQUIRED sdl2)
    pkg_check_modules(SDL2_IMAGE REQUIRED SDL2_image)

    list(APPEND PKG_CONFIG_LIB ${SDL2_LIBRARIES} ${SDL2_IMAGE_LIBRARIES})
    list(APPEND PKG_CONFIG_INC ${SDL2_INCLUDE_DIRS} ${SDL2_IMAGE_INCLUDE_DIRS})

    list(APPEND LV_LINUX_BACKEND_SRC src/lib/display_backends/sdl.c)
endif()


if (CONFIG_LV_USE_WAYLAND)

    message("Including Wayland support")

    find_package(PkgConfig REQUIRED)
    pkg_check_modules(WAYLAND_CLIENT REQUIRED wayland-client)
    pkg_check_modules(WAYLAND_CURSOR REQUIRED wayland-cursor)
    pkg_check_modules(XKBCOMMON REQUIRED xkbcommon)

    list(APPEND PKG_CONFIG_LIB ${WAYLAND_CLIENT_LIBRARIES})
    list(APPEND PKG_CONFIG_LIB ${WAYLAND_CURSOR_LIBRARIES})
    list(APPEND PKG_CONFIG_LIB ${XKBCOMMON_LIBRARIES})

    # Wayland protocols
    pkg_check_modules(WAYLAND_PROTOCOLS REQUIRED wayland-protocols>=1.25)
    pkg_get_variable(WAYLAND_PROTOCOLS_BASE wayland-protocols pkgdatadir)

    if(DEFINED ENV{SDKTARGETSYSROOT} AND DEFINED ENV{SYSROOT})
        message(FATAL_ERROR "Both SDKTARGETSYSROOT and SYSROOT are set. Please set only one.")
    endif()
    
    if(DEFINED ENV{SDKTARGETSYSROOT})
        set(PROTOCOL_ROOT "$ENV{SDKTARGETSYSROOT}/usr/share/wayland-protocols")
    elseif(DEFINED ENV{SYSROOT})
        set(PROTOCOL_ROOT "$ENV{SYSROOT}/usr/share/wayland-protocols")
    else()
        set(PROTOCOL_ROOT "/usr/share/wayland-protocols")
    endif()
    
    if(NOT EXISTS ${PROTOCOL_ROOT})
        message(FATAL_ERROR "Wayland protocols not found at ${PROTOCOL_ROOT}")
    endif()
    
    set(PROTOCOLS_DIR "${CMAKE_CURRENT_BINARY_DIR}/protocols")
    file(MAKE_DIRECTORY ${PROTOCOLS_DIR})
    
    set(WAYLAND_PROTOCOLS_SRC "")
    
    # Generate xdg-shell protocol (always)
    set(XDG_SHELL_XML "${PROTOCOL_ROOT}/stable/xdg-shell/xdg-shell.xml")
    set(XDG_SHELL_HEADER "${PROTOCOLS_DIR}/wayland_xdg_shell.h")
    set(XDG_SHELL_SOURCE "${PROTOCOLS_DIR}/wayland_xdg_shell.c")
    
    if(NOT EXISTS ${XDG_SHELL_HEADER} OR NOT EXISTS ${XDG_SHELL_SOURCE})
        execute_process(COMMAND wayland-scanner client-header ${XDG_SHELL_XML} ${XDG_SHELL_HEADER})
        execute_process(COMMAND wayland-scanner private-code ${XDG_SHELL_XML} ${XDG_SHELL_SOURCE})
    endif()
    list(APPEND WAYLAND_PROTOCOLS_SRC ${XDG_SHELL_SOURCE})
    
    # Generate dmabuf protocol (if config is set)
    if(CONFIG_LV_WAYLAND_USE_DMABUF)
        set(DMABUF_XML "${PROTOCOL_ROOT}/stable/linux-dmabuf/linux-dmabuf-v1.xml")
        set(DMABUF_HEADER "${PROTOCOLS_DIR}/wayland_linux_dmabuf.h")
        set(DMABUF_SOURCE "${PROTOCOLS_DIR}/wayland_linux_dmabuf.c")
        
        if(NOT EXISTS ${DMABUF_HEADER} OR NOT EXISTS ${DMABUF_SOURCE})
            execute_process(COMMAND wayland-scanner client-header ${DMABUF_XML} ${DMABUF_HEADER})
            execute_process(COMMAND wayland-scanner private-code ${DMABUF_XML} ${DMABUF_SOURCE})
        endif()
        list(APPEND WAYLAND_PROTOCOLS_SRC ${DMABUF_SOURCE})
    endif()
    
    list(APPEND PKG_CONFIG_INC ${PROTOCOLS_DIR})
    list(APPEND LV_LINUX_BACKEND_SRC src/lib/display_backends/wayland.c ${WAYLAND_PROTOCOLS_SRC})

endif()

if (CONFIG_LV_USE_X11)

    find_package(PkgConfig REQUIRED)
    pkg_check_modules(X11 REQUIRED x11)

    message("Including X11 support")

    list(APPEND PKG_CONFIG_INC ${X11_INCLUDE_DIRS})
    list(APPEND PKG_CONFIG_LIB ${X11_LIBRARIES})
    list(APPEND LV_LINUX_BACKEND_SRC src/lib/display_backends/x11.c)

endif()

if (CONFIG_LV_USE_LINUX_FBDEV)

    # FBDEV has no dependencies
    message("Including FBDEV support")
    list(APPEND LV_LINUX_BACKEND_SRC src/lib/display_backends/fbdev.c)

endif()

if (CONFIG_LV_USE_GLFW)

    message("Including GLFW support")
    find_package(PkgConfig REQUIRED)
    pkg_check_modules(GLFW3 REQUIRED glfw3)
    pkg_check_modules(GLEW REQUIRED glew)

    list(APPEND PKG_CONFIG_LIB ${GLFW3_LIBRARIES})
    list(APPEND PKG_CONFIG_LIB ${GLEW_LIBRARIES})
    list(APPEND LV_LINUX_BACKEND_SRC src/lib/display_backends/glfw3.c)

endif()

if (CONFIG_LV_USE_DRAW_G2D)
    message("Including G2D support")
    find_library(G2D_LIBRARY NAMES g2d)
    list(APPEND PKG_CONFIG_LIB ${G2D_LIBRARY})
endif()

if (CONFIG_LV_USE_GLTF)
    message(STATUS "Including with GLTF support")
    include(FetchContent)
  
    FetchContent_Declare(
      fastgltf
      GIT_REPOSITORY https://github.com/spnda/fastgltf
      GIT_TAG 4e2261350888bae7c35a1f39991f6233d57795f5)
  
    set(FASTGLTF_ENABLE_DEPRECATED_EXT
        ON
        CACHE BOOL "" FORCE)
  
    set(FASTGLTF_DIFFUSE_TRANSMISSION_SUPPORT
        ON
        CACHE BOOL "" FORCE)
  
    FetchContent_MakeAvailable(fastgltf)
  
    set(WEBP_BUILD_ANIM_UTILS
        OFF
        CACHE BOOL "" FORCE)
    set(WEBP_BUILD_CWEBP
        OFF
        CACHE BOOL "" FORCE)
    set(WEBP_BUILD_DWEBP
        OFF
        CACHE BOOL "" FORCE)
    set(WEBP_BUILD_GIF2WEBP
        OFF
        CACHE BOOL "" FORCE)
    set(WEBP_BUILD_IMG2WEBP
        OFF
        CACHE BOOL "" FORCE)
    set(WEBP_BUILD_VWEBP
        OFF
        CACHE BOOL "" FORCE)
    set(WEBP_BUILD_WEBPINFO
        OFF
        CACHE BOOL "" FORCE)
    set(WEBP_BUILD_WEBPMUX
        OFF
        CACHE BOOL "" FORCE)
    set(WEBP_BUILD_EXTRAS
        OFF
        CACHE BOOL "" FORCE)
  
    FetchContent_Declare(
      webp
      GIT_REPOSITORY https://github.com/webmproject/libwebp
      GIT_TAG fa6f56496a442eed59b103250021e4b14ebf1427)
  
    FetchContent_MakeAvailable(webp)
  
    list(APPEND PKG_CONFIG_LIB fastgltf webp)
endif()

if (CONFIG_LV_USE_GSTREAMER)

    message("Including GSTREAMER support")
    find_package(PkgConfig REQUIRED)

    pkg_check_modules(GSTREAMER REQUIRED gstreamer-1.0)
    pkg_check_modules(GSTREAMER_VIDEO REQUIRED gstreamer-video-1.0)
    pkg_check_modules(GSTREAMER_APP REQUIRED gstreamer-app-1.0)

    list(APPEND PKG_CONFIG_LIB ${GSTREAMER_VIDEO_LIBRARIES} ${GSTREAMER_APP_LIBRARIES})
    list(APPEND PKG_CONFIG_INC ${GSTREAMER_VIDEO_INCLUDE_DIRS} ${GSTREAMER_APP_INCLUDE_DIRS})
endif()

# Check for external demos
if(CONFIG_LV_USE_DEMO_FLEX_LAYOUT
   OR CONFIG_LV_USE_DEMO_MULTILANG
   OR CONFIG_LV_USE_DEMO_TRANSFORM
   OR CONFIG_LV_USE_DEMO_SCROLL
   OR CONFIG_LV_USE_DEMO_EBIKE
   OR CONFIG_LV_USE_DEMO_HIGH_RES
   OR CONFIG_LV_USE_DEMO_SMARTWATCH)

    set(USE_EXTERNAL_DEMOS ON)
else()
    set(USE_EXTERNAL_DEMOS OFF)
endif()

if(USE_EXTERNAL_DEMOS)
    message("Including external demos")
    include(FetchContent)
    FetchContent_Declare(lv_demos_ext GIT_REPOSITORY https://github.com/lvgl/lv_demos)
    FetchContent_MakeAvailable(lv_demos_ext)
    list(APPEND PKG_CONFIG_LIB lv_demos_ext)
endif()


file(GLOB LV_LINUX_SRC src/lib/*.c)
set(LV_LINUX_INC src/lib)

target_include_directories(lvgl PUBLIC ${PKG_CONFIG_INC})

add_library(lvgl_linux STATIC ${LV_LINUX_SRC} ${LV_LINUX_BACKEND_SRC})
target_include_directories(lvgl_linux PUBLIC ${PKG_CONFIG_INC})

# If LVGL is configured to use LV_CONF_PATH or Kconfig
# Set the exactly the same definitions on the lvgl_linux target
set_target_properties(lvgl_linux PROPERTIES COMPILE_DEFINITIONS "${LVGL_COMPILER_DEFINES}")
target_include_directories(lvgl_linux PUBLIC
    ${LV_LINUX_INC} ${CMAKE_CURRENT_SOURCE_DIR}
    ${PROJECT_SOURCE_DIR}/src/lib ${LVGL_CONF_INC_DIR})

# Link LVGL with external dependencies - Modern CMake/CMP0079 allows this
target_link_libraries(lvgl PUBLIC ${PKG_CONFIG_LIB} m pthread)

add_executable(lvglsim src/main.c ${LV_LINUX_SRC} ${LV_LINUX_BACKEND_SRC})
target_link_libraries(lvglsim lvgl_linux lvgl)

if(WERROR)
    target_compile_options(lvglsim PRIVATE -Werror)
    target_compile_options(lvgl PRIVATE -Werror)
    target_compile_options(lvgl_linux PRIVATE -Werror)
endif()


# Install the lvgl_linux library and its headers
install(DIRECTORY src/lib/
    DESTINATION include/lvgl
    FILES_MATCHING
    PATTERN "backends*" EXCLUDE
    PATTERN "*.h")

install(TARGETS lvgl_linux
    ARCHIVE DESTINATION lib
)

add_custom_target(run COMMAND ${EXECUTABLE_OUTPUT_PATH}/lvglsim DEPENDS lvglsim)

修改configs/fbdev.default:

C 复制代码
LV_COLOR_DEPTH	    24

LV_USE_LINUX_FBDEV      1
LV_LINUX_FBDEV_RENDER_MODE   LV_DISPLAY_RENDER_MODE_DIRECT
LV_LINUX_FBDEV_BUFFER_COUNT  2

# Input support
LV_USE_EVDEV    0
LV_USE_LIBINPUT 0
LV_USE_TSLIB    1                      #添加该字段,启用tslib支持

# Examples
LV_BUILD_EXAMPLES 1

# Demos
LV_BUILD_DEMOS 1
LV_USE_DEMO_WIDGETS         1
LV_USE_DEMO_KEYPAD_AND_ENCODER 0
LV_USE_DEMO_BENCHMARK       0
LV_USE_DEMO_RENDER          0
LV_USE_DEMO_STRESS          0
LV_USE_DEMO_MUSIC           0

......

为了使得LV_USE_TSLIB能够生成CONFIG_LV_USE_TSLIB,需要修改lvgl/lv_conf_template.h:

C 复制代码
......

/** Interface for Lovyan_GFX */
#define LV_USE_LOVYAN_GFX         0

#if LV_USE_LOVYAN_GFX
    #define LV_LGFX_USER_INCLUDE "lv_lgfx_user.hpp"

#endif /*LV_USE_LOVYAN_GFX*/

/** Driver for tslib input devices */
#define LV_USE_TSLIB    0                    //添加该字段

/** Driver for evdev input devices */
#define LV_USE_EVDEV    0

/** Driver for libinput input devices */
#define LV_USE_LIBINPUT    0

......

使用交叉编译环境时,cmake命令还需搭配文件user_cross_compile_setup.cmake

bash 复制代码
# Usage:
# cmake -DCMAKE_TOOLCHAIN_FILE=./user_cross_compile_setup.cmake -B build -S .
# make  -C build -j

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(CROSS_COMPILE /home/ender/sunxi/buildroot/buildroot-2025.02.7/output/host/bin/arm-buildroot-linux-gnueabi-)
set(CMAKE_C_COMPILER ${CROSS_COMPILE}gcc)
set(CMAKE_CXX_COMPILER ${CROSS_COMPILE}g++)

# If necessary, set STAGING_DIR
# if not work, please try(in shell command): export STAGING_DIR=/home/ubuntu/Your_SDK/out/xxx/openwrt/staging_dir/target
set(STAGING_DIR "/home/ender/sunxi/buildroot/buildroot-2025.02.7/output/staging")

STAGING_DIR指向自己的staging rootfs即可。 添加文件src/lib/indev_backends/tslib.c,添加tslib触摸驱动注册接口:

C 复制代码
/**
 *
 * @file evdev.c
 *
 * The lib evdev driver
 *
 * Based on the original file from the repository
 *
 * - Move the driver to a separate file to avoid excessive conditional
 *   compilation
 *   Author: EDGEMTech Ltd, Erik Tagirov (erik.tagirov@edgemtech.ch)
 *
 * Copyright (c) 2025 EDGEMTech Ltd.
 *
 */

/*********************
 *      INCLUDES
 *********************/
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

#include "lvgl/lvgl.h"
#if LV_USE_TSLIB
#include "lvgl/src/core/lv_global.h"
#include "../backends.h"
#include "tslib.h"

/*********************
 *      DEFINES
 *********************/

/**********************
 *      TYPEDEFS
 **********************/

/**********************
 *  STATIC PROTOTYPES
 **********************/

static lv_indev_t *init_pointer_tslib(lv_display_t *display);

/**********************
 *  STATIC VARIABLES
 **********************/

static char *backend_name = "TSLIB";
static struct tsdev *ts = NULL;

/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
 **********************/

/*
 * Initialize the tslib driver
 *
 * @param backend the backend descriptor
 */
int backend_init_tslib(backend_t *backend)
{
    LV_ASSERT_NULL(backend);
    backend->handle->indev = malloc(sizeof(indev_backend_t));
    LV_ASSERT_NULL(backend->handle->indev);

    backend->handle->indev->init_indev = init_pointer_tslib;

    backend->name = backend_name;
    backend->type = BACKEND_INDEV;
    return 0;
}


/**********************
 *   STATIC FUNCTIONS
 **********************/

static lv_coord_t last_x = 0;
static lv_coord_t last_y = 0;
static lv_indev_state_t last_state = LV_INDEV_STATE_RELEASED;

static void tslib_read_cb(lv_indev_t *indev, lv_indev_data_t *data)
{
    struct ts_sample samp;

    if(!ts) {
        data->state = LV_INDEV_STATE_RELEASED;
        data->point.x = 0;
        data->point.y = 0;
        data->continue_reading = false;
        return;
    }

    /* 读取队列中所有事件,最后一个点作为当前状态 */
    while(ts_read(ts, &samp, 1) > 0) {
        last_x = samp.x;
        last_y = samp.y;
        last_state = (samp.pressure > 0) ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
    }

    data->point.x = last_x;
    data->point.y = last_y;
    data->state   = last_state;
    data->continue_reading = false;

    /* 限幅到屏幕分辨率 */
    lv_disp_t *disp = lv_indev_get_display(indev);
    lv_coord_t hor_res = lv_disp_get_hor_res(disp);
    lv_coord_t ver_res = lv_disp_get_ver_res(disp);

    if(data->point.x < 0) data->point.x = 0;
    if(data->point.y < 0) data->point.y = 0;
    if(data->point.x >= hor_res) data->point.x = hor_res - 1;
    if(data->point.y >= ver_res) data->point.y = ver_res - 1;
}

static lv_indev_t *init_pointer_tslib(lv_display_t *display)
{
    const char *input_device = getenv("TSLIB_TSDEVICE");
    if(!input_device) 
    {
        input_device = "/dev/input/event0";   
        LV_LOG_USER("Using default input device %s\r\n", input_device);
    }

    ts = ts_setup(input_device, O_RDONLY | O_NONBLOCK);
    if(!ts) {
        LV_LOG_ERROR("ts_setup failed");
        return NULL;
    }
    
    lv_indev_t * indev = lv_indev_create();
    lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
    lv_indev_set_read_cb(indev, tslib_read_cb);
    lv_indev_set_display(indev, display);

    return indev;
}
#endif /*#if LV_USE_TSLIB*/

记得在src/lib/driver_backends.c里的available_backends数组中添加一项新的backends

C 复制代码
/* The default backend is the one that will end up at index 0
 * To add support for a new driver backend add the declaration
 * and append an entry to the available_backends array
 */
backend_init_t available_backends[] = {

#if LV_USE_LINUX_FBDEV
    backend_init_fbdev,
#endif

#if LV_USE_LINUX_DRM
    backend_init_drm,
#endif

#if LV_USE_SDL
    backend_init_sdl,
#endif

#if LV_USE_WAYLAND
    backend_init_wayland,
#endif

#if LV_USE_X11
    backend_init_x11,
#endif

#if LV_USE_GLFW
    backend_init_glfw3,
#endif

#if LV_USE_EVDEV
    backend_init_evdev,
#endif

#if LV_USE_TSLIB
    backend_init_tslib,
#endif

    NULL    /* Sentinel */
};

最后别忘了src/main.c里要手动去初始化

C 复制代码
/**
 * @brief entry point
 * @description start a demo
 * @param argc the count of arguments in argv
 * @param argv The arguments
 */
int main(int argc, char **argv)
{

    configure_simulator(argc, argv);

    /* Initialize LVGL. */
    lv_init();

    /* Initialize the configured backend */
    if (driver_backends_init_backend(selected_backend) == -1) {
        die("Failed to initialize display backend");
    }

    /* Enable for EVDEV support */
#if LV_USE_EVDEV
    if (driver_backends_init_backend("EVDEV") == -1) {
        die("Failed to initialize evdev");
    }
#endif

    /* Enable for TSLIB support */
#if LV_USE_TSLIB
    if (driver_backends_init_backend("TSLIB") == -1) {
        die("Failed to initialize tslib");
    }
#endif

    /*Create a Demo*/
    lv_demo_widgets();
    //lv_demo_widgets_start_slideshow();

    /* Enter the run loop of the selected backend */
    driver_backends_run_loop();

    return 0;
}

都完成后执行

sh 复制代码
cmake CMakeLists.txt -DCMAKE_TOOLCHAIN_FILE=./user_cross_compile_setup.cmake -B build -DCONFIG=fbdev -DCROSS_BUILD=ON

即可完成,这样改动的优点是保持lvgl原有的构建架构,同时tslib作为可选模块被添加到了构建系统中,避免了硬编码,保证了未来更新的兼容性。

相关推荐
自由的好好干活2 小时前
使用Qoder编写ztdaq的C#跨平台示例总结
linux·windows·c#·qoder
赖small强2 小时前
【Linux 网络基础】libwebsockets HTTPS 服务端实现机制详解
linux·网络·https·tls·libwebsockets
optimistic_chen2 小时前
【Redis 系列】Redis详解
linux·数据库·redis·缓存·xsheel
低客的黑调3 小时前
了解JVM 结构和运行机制,从小白编程Java 大佬
java·linux·开发语言
想唱rap3 小时前
C++ map和set
linux·运维·服务器·开发语言·c++·算法
CodeByV3 小时前
【Linux】Ext 系列文件系统深度解析:从磁盘到软硬链接
linux·服务器
运维-大白同学3 小时前
2025最全面开源devops运维平台功能介绍
linux·运维·kubernetes·开源·运维开发·devops
梦在深巷、4 小时前
linux系统防火墙之iptables
linux·运维·服务器
放学有种别跑、5 小时前
GIT使用指南
大数据·linux·git·elasticsearch