Jimmy Chen

A Programmer

(原创)Framebuffer测试程序

  上一篇,我们看了Framebuffer驱动的内容,同时framebuffer提供了一些借口,可以让我们比较容易的操作Framebuffer,所以就有了这篇,写一个简单的程序来获取Framebuffer的信息,同时对Framebuffer进行刷写。这个程序适合在Linux系列的系统上测试,例如在Ubuntu 14.04系统上,将代码保存为fb_test.c,然后通过下面的指令编译gcc fb_test.c -o fb_test -std=c99,alt+ctrl+f1到tty1,然后执行fb_test即可看到效果

  测试代码如下:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <string.h>
#include <sys/mman.h>

#define FB0 "/dev/fb0"

int main(void)
{
    int fd = 0;
    char *fd_map = NULL;
    // 固定参数
    struct fb_fix_screeninfo fix_info;
    // 可变参数
    struct fb_var_screeninfo var_info;
    int ret = -1;
    
    memset(&fix_info, 0, sizeof(struct fb_fix_screeninfo));
    memset(&var_info, 0, sizeof(struct fb_var_screeninfo));
    
    // 打开framebuffer节点
    fd = open(FB0, O_RDWR);
    if(fd < 0)
    {
        char *error_msg = strerror(errno);
        printf("Open %s failed, errno:%d, error message:%s\n", 
            FB0, errno, error_msg);
        return -1;
    }

    // 通过IOCTL获取可变参数结构体内容
    ret = ioctl(fd, FBIOGET_VSCREENINFO, &var_info);
    if(ret < 0)
    {
        char *error_msg = strerror(errno);
        printf("Get %s var info error, errno:%d, error message:%s\n", 
            FB0, errno, error_msg);
        return ret;
    }

    // 通过IOCTL获取固定参数结构体内容
    ret = ioctl(fd, FBIOGET_FSCREENINFO, &fix_info);
    if(ret < 0)
    {
        char *error_msg = strerror(errno);
        printf("Get %s fix info error, errno:%d, error message:%s\n", 
            FB0, errno, error_msg);
        return ret;
    }

    printf("%s var info, xres=%d, yres=%d\n", FB0, var_info.xres, var_info.yres);
    printf("%s var info, xres_virtual=%d, yres_virtual=%d\n", 
        FB0, var_info.xres_virtual, var_info.yres_virtual);
    printf("%s var info, bits_per_pixel=%d\n", FB0, var_info.bits_per_pixel);
    printf("%s var info, xoffset=%d, yoffset=%d\n", 
        FB0, var_info.xoffset, var_info.yoffset);

    int screen_size = var_info.xres * var_info.yres * var_info.bits_per_pixel / 8;

    // 将Framebuffer映射到进程的内存空间
    fd_map = (char *)mmap(NULL, screen_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if(fd_map == (char *)-1)
    {
        char *error_msg = strerror(errno);
        printf("Mmap %s failed, errno:%d, error message:%s\n", 
            FB0, errno, error_msg);
        return -1;
    }
    
    // 将内容写到进程内存空间,Framebuffer驱动会同步刷新到显示屏上
    for(unsigned int i = 0; i < var_info.yres / 3; i++)
    {
        unsigned int argb = 0;
        argb = argb | (0xff << 8);
        for(int j = 0; j < var_info.xres; j++)
            *((unsigned int *)(fd_map + j * 4 + i * var_info.xres * 4)) = argb;
    }

    for(unsigned int i = var_info.yres/3; i < 2 * var_info.yres / 3; i++)
    {
        unsigned int argb = 0;
        argb = argb | (0xff);
        for(int j = 0; j < var_info.xres; j++)
            *((unsigned int *)(fd_map + j * 4 + i * var_info.xres * 4)) = argb;
    }

    munmap(fd_map, screen_size);
    close(fd);
    return 0;
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d 博主赞过: