1、framebuffer
linux内核用struct fb_info来描述一个framebuffer,定义在linux/include/fb.h
struct fb_info {
int node;
int flags;
struct mutex lock; /* Lock for open/release/ioctl funcs */
struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */
struct fb_var_screeninfo var; /* Current var */
struct fb_fix_screeninfo fix; /* Current fix */
struct fb_monspecs monspecs; /* Current Monitor specs */
struct work_struct queue; /* Framebuffer event queue */
struct fb_pixmap pixmap; /* Image hardware mapper */
struct fb_pixmap sprite; /* Cursor hardware mapper */
struct fb_cmap cmap; /* Current cmap */
struct list_head modelist; /* mode list */
struct fb_videomode *mode; /* current mode */
#ifdef CONFIG_FB_BACKLIGHT
/* assigned backlight device */
/* set before framebuffer registration,
remove after unregister */
struct backlight_device *bl_dev;
/* Backlight level curve */
struct mutex bl_curve_mutex;
u8 bl_curve[FB_BACKLIGHT_LEVELS];
#endif
#ifdef CONFIG_FB_DEFERRED_IO
struct delayed_work deferred_work;
struct fb_deferred_io *fbdefio;
#endif
struct fb_ops *fbops;
struct device *device; /* This is the parent */
struct device *dev; /* This is this fb device */
int class_flag; /* private sysfs flags */
#ifdef CONFIG_FB_TILEBLITTING
struct fb_tile_ops *tileops; /* Tile Blitting */
#endif
char __iomem *screen_base; /* Virtual address */
unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */
void *pseudo_palette; /* Fake palette of 16 colors */
#define FBINFO_STATE_RUNNING 0
#define FBINFO_STATE_SUSPENDED 1
u32 state; /* Hardware state i.e suspend */
void *fbcon_par; /* fbcon use-only private area */
/* From here on everything is device dependent */
void *par;
/* we need the PCI or similiar aperture base/size not
smem_start/size as smem_start may just be an object
allocated inside the aperture so may not actually overlap */
struct apertures_struct {
unsigned int count;
struct aperture {
resource_size_t base;
resource_size_t size;
} ranges[0];
} *apertures;
};
struct fb_fix_screeninfo {
char id[16]; /* identification string eg "TT Builtin" */
unsigned long smem_start; /* Start of frame buffer mem */
/* (physical address) */
__u32 smem_len; /* Length of frame buffer mem */
__u32 type; /* see FB_TYPE_* */
__u32 type_aux; /* Interleave for interleaved Planes */
__u32 visual; /* see FB_VISUAL_* */
__u16 xpanstep; /* zero if no hardware panning */
__u16 ypanstep; /* zero if no hardware panning */
__u16 ywrapstep; /* zero if no hardware ywrap */
__u32 line_length; /* length of a line in bytes */
unsigned long mmio_start; /* Start of Memory Mapped I/O */
/* (physical address) */
__u32 mmio_len; /* Length of Memory Mapped I/O */
__u32 accel; /* Indicate to driver which */
/* specific chip/card we have */
__u16 reserved[3]; /* Reserved for future compatibility */
};
其中struct fb_var_screeninfo var; 记录了用户可以改变的显示参数,包括显示器的分辨率等等
struct fb_var_screeninfo {
__u32 xres; /* visible resolution */
__u32 yres;
__u32 xres_virtual; /* virtual resolution */
__u32 yres_virtual;
__u32 xoffset; /* offset from virtual to visible */
__u32 yoffset; /* resolution */
__u32 bits_per_pixel; /* guess what */
__u32 grayscale; /* != 0 Graylevels instead of colors */
struct fb_bitfield red; /* bitfield in fb mem if true color, */
struct fb_bitfield green; /* else only length is significant */
struct fb_bitfield blue;
struct fb_bitfield transp; /* transparency */
__u32 nonstd; /* != 0 Non standard pixel format */
__u32 activate; /* see FB_ACTIVATE_* */
__u32 height; /* height of picture in mm */
__u32 width; /* width of picture in mm */
__u32 accel_flags; /* (OBSOLETE) see fb_info.flags */
/* Timing: All values in pixclocks, except pixclock (of course) */
__u32 pixclock; /* pixel clock in ps (pico seconds) */
__u32 left_margin; /* time from sync to picture */
__u32 right_margin; /* time from picture to sync */
__u32 upper_margin; /* time from sync to picture */
__u32 lower_margin;
__u32 hsync_len; /* length of horizontal sync */
__u32 vsync_len; /* length of vertical sync */
__u32 sync; /* see FB_SYNC_* */
__u32 vmode; /* see FB_VMODE_* */
__u32 rotate; /* angle we rotate counter clockwise */
__u32 reserved[5]; /* Reserved for future compatibility */
};
struct fb_ops {
/* open/release and usage marking */
struct module *owner;
int (*fb_open)(struct fb_info *info, int user);
int (*fb_release)(struct fb_info *info, int user);
/* For framebuffers with strange non linear layouts or that do not
* work with normal memory mapped access
*/
ssize_t (*fb_read)(struct fb_info *info, char __user *buf,
size_t count, loff_t *ppos);
ssize_t (*fb_write)(struct fb_info *info, const char __user *buf,
size_t count, loff_t *ppos);
/* checks var and eventually tweaks it to something supported,
* DO NOT MODIFY PAR */
int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
/* set the video mode according to info->var */
int (*fb_set_par)(struct fb_info *info);
/* set color register */
int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp, struct fb_info *info);
/* set color registers in batch */
int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
/* blank display */
int (*fb_blank)(int blank, struct fb_info *info);
/* pan display */
int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
/* Draws a rectangle */
void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
/* Copy data from area to another */
void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
/* Draws a image to the display */
void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
/* Draws cursor */
int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
/* Rotates the display */
void (*fb_rotate)(struct fb_info *info, int angle);
/* wait for blit idle, optional */
int (*fb_sync)(struct fb_info *info);
/* perform fb specific ioctl (optional) */
int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
unsigned long arg);
/* Handle 32bit compat ioctl (optional) */
int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd,
unsigned long arg);
/* perform fb specific mmap */
int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
/* get capability given var */
void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,
struct fb_var_screeninfo *var);
/* teardown any resources to do with this framebuffer */
void (*fb_destroy)(struct fb_info *info);
/* called at KDB enter and leave time to prepare the console */
int (*fb_debug_enter)(struct fb_info *info);
int (*fb_debug_leave)(struct fb_info *info);
};
对LCD的操作分为三个步骤
1、打开后用ioctl获得当前屏幕设备的参数,根据屏幕的大小计算缓冲区的大小、
2、用mmap将屏幕的缓冲区映射到用户空间
3、以后直接写入内存相当于写入缓冲区
测试代码
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#define FB_DEVICE_NAME "/dev/fb0"
#define RED_COLOR565 0X0F100
#define GREEN_COLOR565 0X007E0
#define BLUE_COLOR565 0X0001F
typedef struct fb_dev {
int fd; /* 帧缓冲设备硬件描述符 */
void *pfb; /* 指向帧缓冲映射到用户空间的首地址 */
int xres; /* 一帧图像的宽度 */
int yres; /* 一帧图像的高度 */
int size; /* 一帧图像的大小 */
int bits_per_pixel; /* 每个像素的大小 */
} fb_dev_t;
int fb_open(fb_dev_t *fbd, char *fbn)
{
struct fb_var_screeninfo vinfo;
if((fbd->fd = open(fbn, O_RDWR)) == -1) {
printf("Error: Cannot open framebuffer device.\n");
_exit(EXIT_FAILURE);
}
/* 获取LCD 的可变参数 */
ioctl(fbd->fd, FBIOGET_VSCREENINFO, &vinfo);
fbd->xres = vinfo.xres;
fbd->yres = vinfo.yres;
fbd->bits_per_pixel = vinfo.bits_per_pixel;
/* 计算一帧图像的大小 */
fbd->size = fbd->xres * fbd->yres * fbd->bits_per_pixel / 8;
printf("%d * %d,%d bits_per_pixel,screensize = %d.\n",fbd->xres,fbd->yres,fbd->bits_per_pixel,fbd->size);
/* 将帧映射到内存 */
/* mmap的应用 */
/* mmap可以把文件内容映射到一段内存中,准确说是虚拟内存,通过对这段内存的读取和修改,实现对文件的读取和修改。 */
/* addr:指定映射的起始地址,通常为NULL,由系统指定 */
/* length:将文件的多大长度映射到内存 */
/* prot:映射区的保护方式,可以是可被执行(PROT_EXEC),可被写入(PROT_WRITE),可被读取(PROT_READ),映射区不能存取(PROT_NONE) */
/* flags:映射区的特性,对映射区的写入数据会复制回文件,且允许其他映射文件的进城共享(MAP_SHARED),对映射区的写入操作会产生一个映射的复制,对此区域所做的修改不会写会源文件(MAP_PRIVATE) */
/* fd:由open返回的文件描述符,代表要映射的文件 */
/* offset:以文件开始出的偏移,必须是分页大小的整数倍,通常为0,表示从头开始映射 */
/* 注意:在修改映射文件时,只能在原长度上修改,不能增加文件长度,因为内存是已经分配好的 */
fbd->pfb = mmap(NULL, fbd->size, PROT_READ | PROT_WRITE, MAP_SHARED, fbd->fd, 0);
if((int)fbd->pfb == -1) {
printf("Error: Failed to map frambuffer device to memory!\n");
_exit(EXIT_FAILURE);
}
return 0;
}
int fb_close(fb_dev_t *fbd)
{
/* 解除映射 */
munmap(fbd->pfb,fbd->size);
/* 关闭设备文件 */
close(fbd->fd);
}
int fb_drawrect(fb_dev_t *fbd, int x0, int y0, int w, int h, int color)
{
int x,y;
for(y=y0; y<y0+h; y++) {
for(x=x0; x<x0+w; x++) {
*((short *)(fbd->pfb) + y*fbd->xres +x) = color;
}
}
return 0;
}
int main(int argc, char **argv)
{
fb_dev_t *fbd;
fbd = (fb_dev_t *)malloc(sizeof(fb_dev_t));
fb_open(fbd, FB_DEVICE_NAME);
if(fbd->bits_per_pixel == 16) {
printf("Red/Green/Blue Screen!");
fb_drawrect(fbd, 0, 0, fbd->xres, fbd->yres/3, RED_COLOR565);
fb_drawrect(fbd, 0, fbd->yres/3, fbd->xres, fbd->yres/3, GREEN_COLOR565);
fb_drawrect(fbd, 0, fbd->yres*2/3, fbd->xres, fbd->yres/3, BLUE_COLOR565);
}
else
printf("16 bits only!");
fb_close(fbd);
return 0;
}
成功后可以看到屏幕上显示三种颜色条、