#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <asm/page.h> #include "fbtools.h" #define TRUE 1 #define FALSE 0 #define MAX(x,y) ((x)>(y)?(x):(y)) #define MIN(x,y) ((x)<(y)?(x):(y)) /* open & init a frame buffer */ int fb_open(PFBDEV pFbdev) { pFbdev->fb = open(pFbdev->dev, O_RDWR); if(pFbdev->fb < 0) { printf("Error opening %s: %m. Check kernel config/n", pFbdev->dev); return FALSE; } if (-1 == ioctl(pFbdev->fb,FBIOGET_VSCREENINFO,&(pFbdev->fb_var))) { printf("ioctl FBIOGET_VSCREENINFO/n"); return FALSE; } if (-1 == ioctl(pFbdev->fb,FBIOGET_FSCREENINFO,&(pFbdev->fb_fix))) { printf("ioctl FBIOGET_FSCREENINFO/n"); return FALSE; } /*map physics address to virtual address */ /*PROT_READ and PROT_WRITE,flags MAP_SHARED*/ pFbdev->fb_mem_offset = (unsigned long)(pFbdev->fb_fix.smem_start) & (~PAGE_MASK); pFbdev->fb_mem = (unsigned long int)mmap(NULL, pFbdev->fb_fix.smem_len + pFbdev->fb_mem_offset, PROT_READ | PROT_WRITE, MAP_SHARED, pFbdev->fb, 0); if (-1L == (long) pFbdev->fb_mem) { printf("mmap error! mem:%d offset:%d/n", pFbdev->fb_mem, pFbdev->fb_mem_offset); return FALSE; } return TRUE; } /* close frame buffer */ int fb_close(PFBDEV pFbdev) { close(pFbdev->fb); pFbdev->fb=-1; } /* get display depth */ int get_display_depth(PFBDEV pFbdev); { if(pFbdev->fb<=0) { printf("fb device not open, open it first/n"); return FALSE; } return pFbdev->fb_var.bits_per_pixel; } /* full screen clear */ void fb_memset (void *addr, int c, size_t len) { memset(addr, c, len); } /* use by test */ #define DEBUG #ifdef DEBUG main() { FBDEV fbdev; memset(&fbdev, 0, sizeof(FBDEV)); strcpy(fbdev.dev, "/dev/fb0"); if(fb_open(&fbdev)==FALSE) { printf("open frame buffer error/n"); return; } fb_memset(fbdev.fb_mem + fbdev.fb_mem_offset, 0, fbdev.fb_fix.smem_len); fb_close(&fbdev); }
帧缓冲(framebuffer)是 Linux 为显示设备提供的一个接口,把显存抽象后的一种设备,他允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。这种操作是抽象的,统一的。用户不必 关心物理显存的位置、换页机制等等具体细节。这些都是由Framebuffer 设备驱动来完成的,所以可知其具有良好的移植性。 帧缓冲设备对应的设备文件为/dev/fb*,如果系统有多个显示卡,Linux 下还可支持多个帧缓冲设备,最多可达32 个,分别为/dev/fb0 到/dev/fb31,当前缺省的帧缓冲设备通常指向/dev/fb0。当然在嵌入式系统中支持一个显示设备就够了。帧缓冲设备为标准字符设备,主设备号 为29,次设备号则从0到31。分别对应/dev/fb0-/dev/fb31。在MID上,设备信息是/dev/graphics/fb0,在PC机上 有显卡的原因是找不到fb的。 通过/dev/fb,应用程序的操作主要有这几种: 1.读/写(read /write)/dev/fb:相当于读/写屏幕缓冲区。在MID上,采用的方式是cat /dev/graphics/fb0 tmp和cat tmp > /dev/graphics/fb0可以实现屏幕内存存储和重现,但是本人试了没有效果(原因不知)。 2.映射(map)操作:由于 Linux 工作在保护模式,每个应用程序都有自己的虚拟地址空间,在应用程序中是不能直接访问物理缓冲区地址的。为此,Linux 在文件操作 file_operations 结构中提供了 mmap 函数,可将文件的内容映射到用户空间。对于帧缓冲设备,则可通过映射操作,可将屏幕缓冲区的物理地址映射到用户空间的一段虚拟地址中,之后用户就可以通过 读写这段虚拟地址访问屏幕缓冲区,在屏幕上绘图了。
mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。 munmap执行相反的操作,删除特定地址区域的对象映射。成功执行时,mmap()返回被映射区的指针,munmap()返回0。 基于文件的映射,在mmap和munmap执行过程的任何时刻,被映射文件的st_atime可能被更新。如果st_atime字段在前述的情况下没有得 到更新,用PROT_WRITE 和 MAP_SHARED标志建立起来的文件映射,其st_ctime 和 st_mtime在对映射区写入之后,在msync()通过MS_SYNC 和 MS_ASYNC两个标志调用之前会被更新。
logo.h
#ifndef _FBTOOLS_H_ #define _FBTOOLS_H_ #include <linux/fb.h> /* a framebuffer device structure */ typedef struct fbdev{ int fb; unsigned long fb_mem_offset; unsigned long fb_mem; struct fb_fix_screeninfo fb_fix; struct fb_var_screeninfo fb_var; char dev[20]; } FBDEV, *PFBDEV; /* open & init a frame buffer */ /* to use this function, you must set FBDEV.dev="/dev/fb0" or "/dev/fbX" */ /* it's your frame buffer. */ int fb_open(PFBDEV pFbdev); /*close a frame buffer*/ int fb_close(PFBDEV pFbdev); /*get display depth*/ int get_display_depth(PFBDEV pFbdev); /*full screen clear */ void fb_memset(void *addr, int c, size_t len); #endif
logo.c