所用操作系統概述: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 <linux/fb.h> //struct fb_fix_screeninfo和struct fb_var_screeninfo的頭文件
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;`
測試的C代碼如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#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;
}
}
``` ----- 大白