所用操作系统概述:linux3.2.0内核,64位的Ubuntu12.04虚拟机
关于linux下操作fb0的介绍网上已经有很多资料了,大家可以随便搜索一下就能找到大量的比较详细的原理性的东西的介绍,我也是根据网上的资料自己写了一个小的测试程序,拿出来跟大家分享。必要说明的一点是直接操作fb0只能在除了tty7图形界面的其它终端才有效,具体原因我也不是很清楚,感觉像是图形界面下看不到真正的tty终端,所以没办法显示吧,具体原因有大神也可以给解答一下。
我测试的时候是用的tty1字符终端(在图形界面下,同时按Ctrl+Alt+F1就可以进入tty1字符终端界面),实际效果如图,源码见附件。但是在安卓下测试这个程序也不能正常工作,除非是在机器启动时,系统在进入linux系统但还没运行安卓应用之前测试的时候是可以直接写的,但是感觉跟Ubuntu下现象还是不一致,显示的不是很正常。谁了解怎么在安卓下直接操作/dev/graphics/fb0也可以留言。
测试的效果图如下,代码包连接如下https://download.csdn.net/download/jxhln/10925387,
2019-01-18 13:52 修正
下面的代码我又用另外版本的虚拟机测试了一下,发现不正常工作,虽然也能显示自己写进去的东西,但是与实际图片相差甚远,后来发现同一个Windows主机上安装的虚拟机得到fb中line_length还不一样,由于这个原因导致在填充显示器的实际行时一个每一行需填充8192字节的像素,而另一个每一行只需填充3200字节的像素,故导致其中一个虚拟机显示正常,另外一个虚拟即显示不正常,故需根据这个line_length改变自己程序中实际填充的字节数才能得到想要的图片(对照下面的程序,虚拟机line_length为8192的fb_width为8193/4=2048,line_length为3200的fb_width=3200/4=8,除以4是因为下面的bits_per_pixel为32位,故每4字节代表一个实际像素点)。
调用ioctl(fbFd, FBIOGET_FSCREENINFO, &finfo)和ioctl(fbFd, FBIOGET_VSCREENINFO, &vinfo) 可以得到fb下列fixed和variable配置信息,其中fbFd为fb0的设备描述符,finfo和vinfo为保存fb配置信息的结构,定义如下
#include //struct fb_fix_screeninfo和struct fb_var_screeninfo的头文件
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;`
测试的C代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#define PIC_DAT 1
#define PIC_DAT2 2
#define DM16A_1 3
#define DM16A_3 4
#define PIC_SELECT 1
#if (PIC_SELECT == PIC_DAT)
#include "pic_data.h"
#elif (PIC_SELECT == DM16A_3)
#include "dm16a_3.h"
#elif (PIC_SELECT == DM16A_1)
#include "dm16a_1_dealed.h"
#elif (PIC_SELECT == PIC_DAT2)
#include "pic_data2.h"
#endif
#define FB_DEV "/dev/fb0"
//#define FB_DEV "/dev/graphics/fb0"
/***************** function declaration ******************/
void usage(char *msg);
int fb_open(char *fb_device);
int fb_close(int fd);
int fb_stat(int fd, int *width, int *height, int *depth);
void *fb_mmap(int fd, unsigned int screensize);
int fb_munmap(void *start, size_t length);
void deal_pic_data2show_buffer(unsigned char * des,const unsigned char * src,unsigned int len);
/************ function implementation ********************/
int main(int argc, char *argv[])
{
/*
* declaration for framebuffer device
*/
int fbdev;
char *fb_device;
unsigned char *fbmem;
unsigned int screensize;
unsigned int fb_width;
unsigned int fb_height;
unsigned int fb_depth;
unsigned int x;
unsigned int y;
unsigned int show_width;
unsigned int show_height;
unsigned char * show_buffer;
unsigned int data_len;
unsigned int len;
unsigned char bytes_per_pix;
/*
* open framebuffer device
*/
if(PIC_SELECT != PIC_DAT || PIC_SELECT != PIC_DAT2
|| PIC_SELECT != DM16A_1 || PIC_SELECT != DM16A_3)
if ((fb_device = getenv("FRAMEbuffer")) == NULL)
fb_device = FB_DEV;
fbdev = fb_open(fb_device);
/*
* get status of framebuffer device
*/
fb_stat(fbdev, &fb_width, &fb_height, &fb_depth);
/*
* map framebuffer device to shared memory
*/
bytes_per_pix = fb_depth / 8;
screensize = fb_width * fb_height * bytes_per_pix;
fbmem = fb_mmap(fbdev, screensize);
#if 0
show_width = fb_width;
show_height = fb_height;
#endif
show_width = pic_width;
show_height = pic_height;
data_len = show_width * show_height * 4;
show_buffer = malloc(data_len);
if(show_buffer == NULL)
return -1;
#if (PIC_SELECT == PIC_DAT)
memset(show_buffer,0xff,data_len);
memcpy(show_buffer,pic_buf,sizeof(pic_buf));
#else
len = sizeof(pic_buf);
deal_pic_data2show_buffer(show_buffer,pic_buf,len);
#endif
while(1){
for(x = 0;x < show_height;x ++)
for(y = 0;y < show_width * bytes_per_pix;y ++)
fbmem[x * fb_width * bytes_per_pix + y] =
show_buffer[x * show_width * bytes_per_pix + y];
//memset(fbmem,0xff,fb_height * fb_width * 4);
}
fb_munmap(fbmem, screensize);
/*
* close framebuffer device
*/
fb_close(fbdev);
return (0);
}
/*
* open framebuffer device.
* return positive file descriptor if success,
* else return -1.
*/
int fb_open(char *fb_device)
{
int fd;
if ((fd = open(fb_device, O_RDWR)) < 0) {
perror(__func__);
return (-1);
}
return (fd);
}
/*
* get framebuffer's width,height,and depth.
* return 0 if success, else return -1.
*/
int fb_stat(int fd, int *width, int *height, int *depth)
{
struct fb_fix_screeninfo fb_finfo;
struct fb_var_screeninfo fb_vinfo;
if (ioctl(fd, FBIOGET_FSCREENINFO, &fb_finfo)) {
perror(__func__);
return (-1);
}
if (ioctl(fd, FBIOGET_VSCREENINFO, &fb_vinfo)) {
perror(__func__);
return (-1);
}
*width = fb_vinfo.xres;
*height = fb_vinfo.yres;
*depth = fb_vinfo.bits_per_pixel;
return (0);
}
/*
* map shared memory to framebuffer device.
* return maped memory if success,
* else return -1, as mmap dose.
*/
void * fb_mmap(int fd, unsigned int screensize)
{
caddr_t fbmem;
if ((fbmem = mmap(0, screensize, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0)) == MAP_FAILED) {
perror(__func__);
return (void *) (-1);
}
return (fbmem);
}
/*
* unmap map memory for framebuffer device.
*/
int fb_munmap(void *start, size_t length)
{
return (munmap(start, length));
}
/*
* close framebuffer device
*/
int fb_close(int fd)
{
return (close(fd));
}
void deal_pic_data2show_buffer(unsigned char * des,const unsigned char * src,unsigned int len){
int i = 0;
unsigned char show_data;
unsigned short tmp_data;
for(i = 0;i < (len / 2);i ++){
tmp_data = (src[i * 2] << 8 | src[i * 2 + 1]);
show_data = (tmp_data >> 6);
des[i * 4] = show_data;
des[i * 4 + 1] = show_data;
des[i * 4 + 2] = show_data;
des[i * 4 + 3] = 0xff;
}
}
``` ----- 大白