tslib中对linux fb操作接口的封装

嵌入式调试显示屏,可能用过tslib,其中有些代码拿出来就是对linux fb不错的封装。

例如如下程序,就是tslib中的部分代码,大家可以直接使用,或者再加工修改:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <fcntl.h>

#include <linux/vt.h>
#include <linux/kd.h>
#include <linux/fb.h>


/*****************************************************************************
 *
 * Macro definition
 *
 *****************************************************************************/
// 
#define VTNAME_LEN                      (128)


/*****************************************************************************
 *
 * Structure/Class Definition
 *
 *****************************************************************************/
union multiptr {
    uint8_t     *p8;
    uint16_t    *p16;
    uint32_t    *p32;
};


/*****************************************************************************
 *
 * Data definition
 *
 *****************************************************************************/
static int32_t con_fd = -1;
static int32_t last_vt = -1;

static struct fb_fix_screeninfo fix;
static struct fb_var_screeninfo var;

static unsigned char *fbuffer = NULL;
static unsigned char **line_addr = NULL;

static int32_t fb_fd;
static int32_t bytes_per_pixel;
static uint32_t transp_mask;

uint32_t xres, yres;
uint32_t xres_orig, yres_orig;
int8_t rotation;
// 0 ... no rotation; 0 degree (default)
// 1 ... clockwise orientation; 90 degrees
// 2 ... upside down orientation; 180 degrees
// 3 ... counterclockwise orientation; 270 degrees

static const char *defaultfbdevice = "/dev/fb0";
//static char *defaultconsoledevice = "/dev/tty";
static const char *fbdevice;
static const char *consoledevice;


/*****************************************************************************
 *
 * Function Entity
 *
 *****************************************************************************/
int FbOpen(const char *fb_dev, const char * console_dev, uint32_t *max_width, uint32_t *max_height)
{
    struct vt_stat vts;
    char vtname[VTNAME_LEN];
    int32_t fd, nr;
    uint32_t y, addr;

    //
    if (NULL == fb_dev)
    {
        fbdevice = defaultfbdevice;
    }
    else
    {
        fbdevice = fb_dev;
    }
    

    //
    if (NULL == console_dev)
    {
        consoledevice = "none";
    }
    else
    {
        consoledevice = console_dev;
    }
    

    if (strcmp(consoledevice, "none") != 0)
    {
        if (strlen(consoledevice) >= VTNAME_LEN)
        {
            return -1;
        }

        sprintf(vtname, "%s%d", consoledevice, 1);
        fd = open(vtname, O_WRONLY);
        if (fd < 0)
        {
            perror("open consoledevice");
            return -1;
        }

        if (ioctl(fd, VT_OPENQRY, &nr) < 0)
        {
            close(fd);
            perror("ioctl VT_OPENQRY");
            return -1;
        }
        close(fd);

        sprintf(vtname, "%s%d", consoledevice, nr);

        con_fd = open(vtname, O_RDWR | O_NDELAY);
        if (con_fd < 0)
        {
            perror("open tty");
            return -1;
        }

        if (ioctl(con_fd, VT_GETSTATE, &vts) == 0)
            last_vt = vts.v_active;

        if (ioctl(con_fd, VT_ACTIVATE, nr) < 0)
        {
            perror("VT_ACTIVATE");
            close(con_fd);
            return -1;
        }

#ifndef TSLIB_NO_VT_WAITACTIVE
        if (ioctl(con_fd, VT_WAITACTIVE, nr) < 0)
        {
            perror("VT_WAITACTIVE");
            close(con_fd);
            return -1;
        }
#endif

        if (ioctl(con_fd, KDSETMODE, KD_GRAPHICS) < 0)
        {
            perror("KDSETMODE");
            close(con_fd);
            return -1;
        }
    }

    fb_fd = open(fbdevice, O_RDWR);
    if (fb_fd == -1)
    {
        perror("open fbdevice");
        return -1;
    }

    if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fix) < 0)
    {
        perror("ioctl FBIOGET_FSCREENINFO");
        close(fb_fd);
        return -1;
    }

    if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &var) < 0)
    {
        perror("ioctl FBIOGET_VSCREENINFO");
        close(fb_fd);
        return -1;
    }

    xres_orig = var.xres;
    yres_orig = var.yres;

    if (rotation & 1)
    {
        /* 1 or 3 */
        y = var.yres;
        yres = var.xres;
        xres = y;
    }
    else
    {
        /* 0 or 2 */
        xres = var.xres;
        yres = var.yres;
    }

    fbuffer = mmap(NULL,
                   fix.smem_len,
                   PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED,
                   fb_fd,
                   0);


    if (fbuffer == (unsigned char *)-1)
    {
        printf("%s - smem_len = %d, fb = %d\n\r", __func__, fix.smem_len, fb_fd);
        perror("mmap framebuffer");
        close(fb_fd);
        return -1;
    }
    memset(fbuffer, 0, fix.smem_len);

    bytes_per_pixel = (var.bits_per_pixel + 7) / 8;
    transp_mask = ((1 << var.transp.length) - 1) << var.transp.offset; // transp.length unlikely > 32
    line_addr = malloc(sizeof(*line_addr) * var.yres_virtual);
    addr = 0;
    for (y = 0; y < var.yres_virtual; y++, addr += fix.line_length)
    {
        line_addr[y] = fbuffer + addr;
    }


    if (max_width != NULL && max_height != NULL)
    {
        *max_width = xres;
        *max_height = yres;
    }


    return 0;
}


void FbClose(void)
{
    memset(fbuffer, 0, fix.smem_len);
    munmap(fbuffer, fix.smem_len);
    close(fb_fd);

    if (strcmp(consoledevice, "none") != 0)
    {
        if (ioctl(con_fd, KDSETMODE, KD_TEXT) < 0)
        {
            perror("KDSETMODE");
        }

        if (last_vt >= 0)
        {
            if (ioctl(con_fd, VT_ACTIVATE, last_vt))
            {
                perror("VT_ACTIVATE");
            }
        }

        close(con_fd);
    }

    free(line_addr);

    xres = 0;
    yres = 0;
    rotation = 0;

    fbuffer = NULL;
    line_addr = NULL;
}

static void __PixelLocate(int32_t x, int32_t y, union multiptr *loc)
{
    if (NULL == line_addr)
    {
        loc->p8 = NULL;
        return;
    }

    switch (rotation)
    {
    case 0:
    default:
        loc->p8 = line_addr[y] + x * bytes_per_pixel;
        break;
    case 1:
        loc->p8 = line_addr[x] + (yres - y - 1) * bytes_per_pixel;
        break;
    case 2:
        loc->p8 = line_addr[yres - y - 1] + (xres - x - 1) * bytes_per_pixel;
        break;
    case 3:
        loc->p8 = line_addr[xres - x - 1] + y * bytes_per_pixel;
        break;
    }
}



static inline void __SetPixel(union multiptr loc, uint32_t xormode, uint32_t color)
{
    if (NULL == loc.p8)
    {
        return;
    }


    switch (bytes_per_pixel)
    {
    case 1:
    default:
        if (xormode)
            *loc.p8 ^= color;
        else
            *loc.p8 = color;
        break;
    case 2:
        if (xormode)
            *loc.p16 ^= color;
        else
            *loc.p16 = color;
        break;
    case 3:
        if (xormode)
        {
            *loc.p8++ ^= (color >> 16) & 0xff;
            *loc.p8++ ^= (color >> 8) & 0xff;
            *loc.p8 ^= color & 0xff;
        }
        else
        {
            *loc.p8++ = (color >> 16) & 0xff;
            *loc.p8++ = (color >> 8) & 0xff;
            *loc.p8 = color & 0xff;
        }
        break;
    case 4:
        if (xormode)
            *loc.p32 ^= color;
        else
            *loc.p32 = color;
        break;
    }
}


// 绘制一个像素点
void FbDrawPixel(int32_t x, int32_t y, uint32_t color)
{
    uint32_t xormode;
    union multiptr loc;

    if ((x < 0) || ((uint32_t)x >= xres) || (y < 0) || ((uint32_t)y >= yres))
    {
        return;
    }

    xormode = 0;

    __PixelLocate(x, y, &loc);
    __SetPixel(loc, xormode, color);
}


// 绘制一条直线,任何2点之间的直线
void FbDrawBeeLine(int32_t x_start, int32_t y_start, int32_t x_end, int32_t y_end, uint32_t color)
{
    int32_t tmp;
    int32_t distance_x = x_end - x_start;
    int32_t distance_y = y_end - y_start;

    if (abs(distance_x) < abs(distance_y))
    {
        if (y_start > y_end)
        {
            tmp = x_start;
            x_start = x_end;
            x_end = tmp;
            tmp = y_start;
            y_start = y_end;
            y_end = tmp;
            distance_x = -distance_x;
            distance_y = -distance_y;
        }
        x_start <<= 16;
        // distance_y is apriori > 0 
        distance_x = (distance_x << 16) / distance_y;
        while (y_start <= y_end)
        {
            FbDrawPixel(x_start >> 16, y_start, color);
            x_start += distance_x;
            y_start++;
        }
    }
    else
    {
        if (x_start > x_end)
        {
            tmp = x_start;
            x_start = x_end;
            x_end = tmp;
            tmp = y_start;
            y_start = y_end;
            y_end = tmp;
            distance_x = -distance_x;
            distance_y = -distance_y;
        }
        y_start <<= 16;
        distance_y = distance_x ? (distance_y << 16) / distance_x : 0;
        while (x_start <= x_end)
        {
            FbDrawPixel(x_start, y_start >> 16, color);
            y_start += distance_y;
            x_start ++;
        }
    }
}


// 绘制一个矩形框
void FbDrawRectLine(int32_t x_start, int32_t y_start, int32_t x_end, int32_t y_end, uint32_t color)
{
    FbDrawBeeLine(x_start, y_start,     x_end,   y_start,     color);
    FbDrawBeeLine(x_end,   y_start + 1, x_end,   y_end - 1,   color);
    FbDrawBeeLine(x_end,   y_end,       x_start, y_end,       color);
    FbDrawBeeLine(x_start, y_end - 1,   x_start, y_start + 1, color);
}



void CoordinateChk(int32_t *x_start, int32_t *y_start, int32_t *x_end, int32_t *y_end)
{
    int32_t x_loc;
    int32_t y_loc;

    // Clipping and sanity checking 
    if (*x_start > *x_end)
    {
        x_loc = *x_start;
        *x_start = *x_end;
        *x_end = x_loc;
    }
    if (*y_start > *y_end)
    {
        y_loc = *y_start;
        *y_start = *y_end;
        *y_end = y_loc;
    }

    if (*x_start < 0)
    {
        *x_start = 0;
    }
    if ((uint32_t)(*x_start) >= xres)
    {
        *x_start = xres - 1;
    }

    if (*x_end < 0)
    {
        *x_end = 0;
    }
    if ((uint32_t)(*x_end) >= xres)
    {
        *x_end = xres - 1;
    }

    if (*y_start < 0)
    {
        *y_start = 0;
    }
    if ((uint32_t)(*y_start) >= yres)
    {
        *y_start = yres - 1;
    }

    if (*y_end < 0)
    {
        *y_end = 0;
    }
    if ((uint32_t)(*y_end) >= yres)
    {
        *y_end = yres - 1;
    }
}



// 绘制一个实心矩形
void FbFillRect(int32_t x_start, int32_t y_start, int32_t x_end, int32_t y_end, uint32_t color)
{
    int32_t x_loc;
    int32_t y_loc;
    uint32_t xormode = 0;
    union multiptr loc;

    // Clipping and sanity checking 
    CoordinateChk(&x_start, &y_start, &x_end, &y_end);

    if ((x_start > x_end) || (y_start > y_end))
    {
        return;
    }


    // 
    for (y_loc = y_start; y_loc <= y_end; ++y_loc)
    {
        for (x_loc = x_start; x_loc <= x_end; ++x_loc)
        {
            __PixelLocate(x_loc, y_loc, &loc);
            __SetPixel(loc, xormode, color);
            //loc.p8 += bytes_per_pixel;
        }
    }
}



// 根据输入的图像,绘制一个矩形图案,图案为ARGB
void FbFillRectPicture(int32_t x_start, int32_t y_start, int32_t x_end, int32_t y_end, uint32_t *pic_color)
{
    int32_t x_loc;
    int32_t y_loc;
    int32_t height;
    int32_t width;
    uint32_t xormode = 0;
    union multiptr loc;


    // Clipping and sanity checking 
    CoordinateChk(&x_start, &y_start, &x_end, &y_end);

    if ((x_start > x_end) || (y_start > y_end))
    {
        return;
    }


    //
    height = y_end - y_start + 1;
    width  = x_end - x_start + 1;


    // 
    for (y_loc = y_start; y_loc <= y_end; ++y_loc)
    {
        for (x_loc = x_start; x_loc <= x_end; ++x_loc)
        {
            __PixelLocate(x_loc, y_loc, &loc);
            __SetPixel(loc, xormode, pic_color[x_loc - x_start]);
        }

        pic_color += width;
    }
}

// 绘制一个单色矩形图案,将输入的8bit像素值,拷贝到RGB
void FbFillRectPictureByYUV400(int32_t x_start, int32_t y_start, int32_t x_end, int32_t y_end, uint8_t *pic_color)
{
    int32_t x_loc;
    int32_t y_loc;
    int32_t height;
    int32_t width;
    uint32_t xormode = 0;
    uint32_t color;
    union multiptr loc;


    // Clipping and sanity checking 
    CoordinateChk(&x_start, &y_start, &x_end, &y_end);

    if ((x_start > x_end) || (y_start > y_end))
    {
        return;
    }


    //
    height = y_end - y_start + 1;
    width  = x_end - x_start + 1;

    //printf("%s - x_start = %d, x_end = %d, width = %d\n\r", __func__, x_start, x_end, width);
    //printf("%s - y_start = %d, y_end = %d, width = %d\n\r", __func__, y_start, y_end, height);


    // 
    for (y_loc = y_start; y_loc <= y_end; ++y_loc)
    {
        for (x_loc = x_start; x_loc <= x_end; ++x_loc)
        {
            color = 0xff000000 | (pic_color[x_loc - x_start] << 16) | (pic_color[x_loc - x_start] << 8) | (pic_color[x_loc - x_start]);
            __PixelLocate(x_loc, y_loc, &loc);
            __SetPixel(loc, xormode, color);
        }

        pic_color += width;
    }
}

引用:D:\Linux-4.9.88.tar\Linux-4.9.88\include\uapi\linux input.h 。 引用:cp -d lib/*so* /home/book/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/ (2)板子上测试编译 。 引用:1,上网搞个源码库,如果你可爱到不会用百度,没关系,戳我下载( http://download.csdn.net/detail/vincent040/9662825 )。 2,将源代码丢到Ubuntu,并通过以下命令解压到Ubuntu的家目录下: tar xjvf tslib-1.4.tar.bz2 -C ~ 3,进入源码顶层目录,依次执行如下命令: mkdir ~/tslib ./configure --prefix=/home/xxx/tslib --host=arm-none-linux-gnueabi make make install A) --prefix= 后面的路径就是你要安装 tslib 库的路径,墙裂建议设置为家目录下的空目录(比如~/tslib),因为如果设置系统其它目录的话,后期 make install 的时候会让你解决权限的问题,当你自作聪明地使用sudo的时候,系统却又可能会抱怨找不到工具链,因此除非你是 Ubuntu科学家,对系统环境变量了如指掌,否则不要用小白的身份去作死,乖乖将 --prefix 指定为 ~/tslib 即可。 根据提供的引用内容,可以看出tslib是一个Linux上的触摸屏输入子系统库。它提供了在嵌入式系统处理触摸屏输入的功能和接口。要安装tslib库,可以按照以下步骤进行操作:首先,下载源码库并将源代码解压到Ubuntu的家目录下;接着进入源码顶层目录,创建一个空目录(比如~/tslib)作为安装路径,并执行configure命令来配置安装参数;然后使用make命令编译源代码;最后使用make install命令安装tslib库到指定的安装路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值