`
jgsj
  • 浏览: 961521 次
文章分类
社区版块
存档分类
最新评论

FrameBuffer驱动程序分析

 
阅读更多

FrameBuffer通常作为LCD控制器或者其他显示设备的驱动,FrameBuffer驱动是一个字符设备,设备节点是/dev/fbX,主设备号为29,次设备号递增,用户可以将Framebuffer看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。这种操作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等具体细节。这些都是由Framebuffer设备驱动来完成的。Framebuffer设备为上层应用程序提供系统调用,也为下一层的特定硬件驱动提供接口;那些底层硬件驱动需要用到这儿的接口来向系统内核注册它们自己。

Linux中的PCI设备可以将其控制寄存器映射到物理内存空间,而后,对这些控制寄存器的访问变成了对理内存的访问,因此,这些寄存器又被称为"memio"。一旦被映射到物理内存,Linux的普通进程就可以通过mmap将这些内存I/O映射到进程地址空间,这样就可以直接访问这些寄存器了。

FrameBuffer设备属于字符设备,采用了文件层—驱动层的接口方式,Linux为帧缓冲设备定义了驱动层的接口fb_info结构,在文件层上,用户调用file_operations的函数操作,间接调用fb_info中的fb_ops函数集来操作硬件。

Framebuffer数据结构

kernel\include\linux\fb.h

fb_info是Linux为帧缓冲设备定义的驱动层接口。它不仅包含了底层函数,而且还有记录设备状态的数据。每个帧缓冲设备都与一个fb_info结构相对应。

struct fb_info {
	atomic_t count;
	int node;  /*一个FrameBuffer设备的次设备号*/
	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
	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 */
	void *par;
	struct apertures_struct {
		unsigned int count;
		struct aperture {
			resource_size_t base;
			resource_size_t size;
		} ranges[0];
	} *apertures;
};

fb_var_screeninfo:用于记录用户可修改的显示控制器参数,包括屏幕分辨率、每个像素点的比特数等

struct fb_var_screeninfo {
	__u32 xres;			/* 行可见像素*/
	__u32 yres;         /* 列可见像素*/
	__u32 xres_virtual;	/* 行虚拟像素*/
	__u32 yres_virtual; /* 列虚拟像素*/
	__u32 xoffset;		/* 水平偏移量*/
	__u32 yoffset;		/* 垂直偏移量*/
	__u32 bits_per_pixel;/*每个像素所占bit位数*/
	__u32 grayscale;	/* 灰色刻度*/
	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;			/* 图像高度*/
	__u32 width;			/* 图像宽度*/
	__u32 accel_flags;		/* (OBSOLETE) see fb_info.flags */
	__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 */
};

fb_fix_screeninfo:记录了用户不能修改的显示控制器的参数,这些参数是在驱动初始化时设置的

struct fb_fix_screeninfo {
	char id[16];			/* identification string eg "TT Builtin" */
	unsigned long smem_start;/* Start of frame buffer mem */
	__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   */
	__u32 mmio_len;			/* Length of Memory Mapped I/O  */
	__u32 accel;			/* Indicate to driver which	*/
	__u16 reserved[3];		/* Reserved for future compatibility */
};

fb_ops是提供给底层设备驱动的一个接口。当我们编写一个FrameBuffer的时候,就要依照Linux FrameBuffer编程的套路,填写fb_ops结构体。

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);
};

Framebuffer模块初始化过程

FrameBuffer驱动是以模块的形式注册到系统中,在模块初始化时,创建FrameBuffer对应的设备文件及proc文件,并注册FrameBuffer设备操作接口函数。
kernel\drivers\video\Fbmem.c

module_init(fbmem_init);
static int __init fbmem_init(void)
{
  //在proc文件系统中创建/proc/fb文件,并注册proc接口函数
	proc_create("fb", 0, NULL, &fb_proc_fops);
  //注册字符设备fb,并注册fb设备文件的操作接口函数,主设备号为29,
  //#define FB_MAJOR		29 	
  if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
		printk("unable to get major %d for fb devs\n", FB_MAJOR);
	//创建sys/class/graphics目录
	fb_class = class_create(THIS_MODULE, "graphics");
	if (IS_ERR(fb_class)) {
		printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));
		fb_class = NULL;
	}
	return 0;
}

首先在proc文件系统中创建fb文件,同时注册操作该文件的接口函数:

static const struct file_operations fb_proc_fops = {
	.owner		= THIS_MODULE,
	.open		= proc_fb_open,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= seq_release,
};

因此可以对/proc/fb文件进行打开,读写操作。然后注册一个主设备号为29的字符设备,fbmem_init函数中注册了字符设备的文件操作接口函数fb_fops,定义如下:

static const struct file_operations fb_fops = {
	.owner =THIS_MODULE,
	.read =	fb_read,
	.write = fb_write,
	.unlocked_ioctl = fb_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl = fb_compat_ioctl,
#endif
	.mmap =	fb_mmap,
	.open =	fb_open,
	.release =fb_release,
#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
	.get_unmapped_area = get_fb_unmapped_area,
#endif
#ifdef CONFIG_FB_DEFERRED_IO
	.fsync =fb_deferred_io_fsync,
#endif
	.llseek =default_llseek,
};

Framebuffer驱动注册过程

变量定义:

//保存注册的所有Framebuffer驱动
extern struct fb_info *registered_fb[FB_MAX];
//已注册的Framebuffer驱动的个数
extern int num_registered_fb;

任何一个特定硬件Framebuffer驱动在初始化时都必须向fbmem.c注册,FrameBuffer模块提供了驱动注册接口函数register_framebuffer:

int register_framebuffer(struct fb_info *fb_info)
{
	int ret;
	mutex_lock(®istration_lock);
	ret = do_register_framebuffer(fb_info);
	mutex_unlock(®istration_lock);
	return ret;
}

参数fb_info描述特定硬件的FrameBuffer驱动信息

static int do_register_framebuffer(struct fb_info *fb_info)
{
	int i;
	struct fb_event event;
	struct fb_videomode mode;
	if (fb_check_foreignness(fb_info))
		return -ENOSYS;
	//根据当前注册的fb_info的apertures属性从FrameBuffer驱动数组registered_fb中查询是否存在冲突
	do_remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id,
					 fb_is_primary_device(fb_info));
	//判断已注册的驱动是否超过32个FrameBuffer驱动
	if (num_registered_fb == FB_MAX)
		return -ENXIO;
	//增加已注册的驱动个数
	num_registered_fb++;
	//从数组registered_fb中查找空闲元素,用于存储当前注册的fb_info
	for (i = 0 ; i < FB_MAX; i++)
		if (!registered_fb[i])
			break;
	//将当前注册的fb_info在数组registered_fb中的索引位置保存到fb_info->node
	fb_info->node = i;
	//初始化当前注册的fb_info的成员信息
	atomic_set(&fb_info->count, 1);
	mutex_init(&fb_info->lock);
	mutex_init(&fb_info->mm_lock);
    //在/dev目录下创建一个fbx的设备文件,次设备号就是该fb_info在数组registered_fb中的索引
	fb_info->dev = device_create(fb_class, fb_info->device,MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
	if (IS_ERR(fb_info->dev)) {
		printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
		fb_info->dev = NULL;
	} else
		//初始化fb_info
		fb_init_device(fb_info);
	if (fb_info->pixmap.addr == NULL) {
		fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
		if (fb_info->pixmap.addr) {
			fb_info->pixmap.size = FBPIXMAPSIZE;
			fb_info->pixmap.buf_align = 1;
			fb_info->pixmap.scan_align = 1;
			fb_info->pixmap.access_align = 32;
			fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;
		}
	}	
	fb_info->pixmap.offset = 0;
	if (!fb_info->pixmap.blit_x)
		fb_info->pixmap.blit_x = ~(u32)0;
	if (!fb_info->pixmap.blit_y)
		fb_info->pixmap.blit_y = ~(u32)0;
	if (!fb_info->modelist.prev || !fb_info->modelist.next)
		INIT_LIST_HEAD(&fb_info->modelist);
	fb_var_to_videomode(&mode, &fb_info->var);
	fb_add_videomode(&mode, &fb_info->modelist);
	//将特定硬件对应的fb_info注册到registered_fb数组中
	registered_fb[i] = fb_info;
	event.info = fb_info;
	if (!lock_fb_info(fb_info))
		return -ENODEV;
	//使用Linux事件通知机制发送一个FrameBuffer注册事件FB_EVENT_FB_REGISTERED
	fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
	unlock_fb_info(fb_info);
	return 0;
}

注册过程就是将指定的设备驱动信息fb_info存放到registered_fb数组中。因此在注册具体的fb_info时,首先要构造一个fb_info数据结构,并初始化该数据结构,该结构用于描述一个特定的FrameBuffer驱动。

fbX设备文件的打开过程

open("/dev/fb0")打开设备文件fb0对应的操作过程如下:

static int fb_open(struct inode *inode, struct file *file)
__acquires(&info->lock)
__releases(&info->lock)
{
	//从文件节点中取得次设备号
	int fbidx = iminor(inode);
	struct fb_info *info;
	int res = 0;
	//根据次设备号从registered_fb数组中取出对应的fb_info
	info = get_fb_info(fbidx);
	if (!info) {
		request_module("fb%d", fbidx);
		info = get_fb_info(fbidx);
		if (!info)
			return -ENODEV;
	}
	if (IS_ERR(info))
		return PTR_ERR(info);
	mutex_lock(&info->lock);
	if (!try_module_get(info->fbops->owner)) {
		res = -ENODEV;
		goto out;
	}
	//将当前的fb_info保存到/dev/fbx设备文件的private_data成员中
	file->private_data = info;
	if (info->fbops->fb_open) {
		//调用当前fb_info的fb_open函数打开当前FrameBuffer设备
		res = info->fbops->fb_open(info,1);
		if (res)
			module_put(info->fbops->owner);
	}
#ifdef CONFIG_FB_DEFERRED_IO
	if (info->fbdefio)
		fb_deferred_io_open(info, inode, file);
#endif
out:
	mutex_unlock(&info->lock);
	if (res)
		put_fb_info(info);
	return res;
}
打开过程很简单,首先从文件节点中取出要打开FrameBuffer的fb_info数据信息,并保存到设备文件file的private_data变量中,然后调用当前fb_info中的fb_open函数完成设备打开过程。该函数在构造具体的fb_info并注册FrameBuffer时,就已注册了对应的打开操作函数指针。


fbX设备文件的映射过程

static int fb_mmap(struct file *file, struct vm_area_struct * vma)
{
	//从文件节点中取出fb_info,并且判断是否和private_data变量中的fb_info相同
	struct fb_info *info = file_fb_info(file);
	struct fb_ops *fb;
	unsigned long off;
	unsigned long start;
	u32 len;
	if (!info)
		return -ENODEV;
	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
		return -EINVAL;
	off = vma->vm_pgoff << PAGE_SHIFT;
	fb = info->fbops;
	if (!fb)
		return -ENODEV;
	mutex_lock(&info->mm_lock);
	//如果fb_info中注册了fb_mmap函数,则调用fb_info中的fb_mmap来完成地址空间映射
	if (fb->fb_mmap) {
		int res;
		res = fb->fb_mmap(info, vma);
		mutex_unlock(&info->mm_lock);
		return res;
	}
	//如果具体的fb_info没有实现fb_mmap
	start = info->fix.smem_start;
	len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
	if (off >= len) {
		/* memory mapped io */
		off -= len;
		if (info->var.accel_flags) {
			mutex_unlock(&info->mm_lock);
			return -EINVAL;
		}
		start = info->fix.mmio_start;
		len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
	}
	mutex_unlock(&info->mm_lock);
	start &= PAGE_MASK;
	if ((vma->vm_end - vma->vm_start + off) > len)
		return -EINVAL;
	off += start;
	vma->vm_pgoff = off >> PAGE_SHIFT;
	/* This is an IO map - tell maydump to skip this VMA */
	vma->vm_flags |= VM_IO | VM_RESERVED;
	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
	fb_pgprotect(file, vma, off);
	if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
			     vma->vm_end - vma->vm_start, vma->vm_page_prot))
		return -EAGAIN;
	return 0;
}
这里和fb打开过程类似,仍然是调用具体的fb_info的映射函数来完成地址空间映射过程,但是也有区别,就是在具体的fb_info没有实现地址空间映射时,就在FrameBuffer这一层完成映射过程。

fbX设备文件的命令控制过程


static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,unsigned long arg)
{
	struct fb_ops *fb;
	struct fb_var_screeninfo var;
	struct fb_fix_screeninfo fix;
	struct fb_con2fbmap con2fb;
	struct fb_cmap cmap_from;
	struct fb_cmap_user cmap;
	struct fb_event event;
	void __user *argp = (void __user *)arg;
	long ret = 0;
	switch (cmd) {
	case FBIOGET_VSCREENINFO:
		if (!lock_fb_info(info))
			return -ENODEV;
		var = info->var;
		unlock_fb_info(info);

		ret = copy_to_user(argp, &var, sizeof(var)) ? -EFAULT : 0;
		break;
	case FBIOPUT_VSCREENINFO:
		if (copy_from_user(&var, argp, sizeof(var)))
			return -EFAULT;
		if (!lock_fb_info(info))
			return -ENODEV;
		console_lock();
		info->flags |= FBINFO_MISC_USEREVENT;
		ret = fb_set_var(info, &var);
		info->flags &= ~FBINFO_MISC_USEREVENT;
		console_unlock();
		unlock_fb_info(info);
		if (!ret && copy_to_user(argp, &var, sizeof(var)))
			ret = -EFAULT;
		break;
	case FBIOGET_FSCREENINFO:
		if (!lock_fb_info(info))
			return -ENODEV;
		fix = info->fix;
		unlock_fb_info(info);

		ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0;
		break;
	case FBIOPUTCMAP:
		if (copy_from_user(&cmap, argp, sizeof(cmap)))
			return -EFAULT;
		ret = fb_set_user_cmap(&cmap, info);
		break;
	case FBIOGETCMAP:
		if (copy_from_user(&cmap, argp, sizeof(cmap)))
			return -EFAULT;
		if (!lock_fb_info(info))
			return -ENODEV;
		cmap_from = info->cmap;
		unlock_fb_info(info);
		ret = fb_cmap_to_user(&cmap_from, &cmap);
		break;
	case FBIOPAN_DISPLAY:
		if (copy_from_user(&var, argp, sizeof(var)))
			return -EFAULT;
		if (!lock_fb_info(info))
			return -ENODEV;
		console_lock();
		ret = fb_pan_display(info, &var);
		console_unlock();
		unlock_fb_info(info);
		if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
			return -EFAULT;
		break;
	case FBIO_CURSOR:
		ret = -EINVAL;
		break;
	case FBIOGET_CON2FBMAP:
		if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
			return -EFAULT;
		if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
			return -EINVAL;
		con2fb.framebuffer = -1;
		event.data = &con2fb;
		if (!lock_fb_info(info))
			return -ENODEV;
		event.info = info;
		fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event);
		unlock_fb_info(info);
		ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0;
		break;
	case FBIOPUT_CON2FBMAP:
		if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
			return -EFAULT;
		if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
			return -EINVAL;
		if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
			return -EINVAL;
		if (!registered_fb[con2fb.framebuffer])
			request_module("fb%d", con2fb.framebuffer);
		if (!registered_fb[con2fb.framebuffer]) {
			ret = -EINVAL;
			break;
		}
		event.data = &con2fb;
		if (!lock_fb_info(info))
			return -ENODEV;
		event.info = info;
		ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event);
		unlock_fb_info(info);
		break;
	case FBIOBLANK:
		if (!lock_fb_info(info))
			return -ENODEV;
		console_lock();
		info->flags |= FBINFO_MISC_USEREVENT;
		ret = fb_blank(info, arg);
		info->flags &= ~FBINFO_MISC_USEREVENT;
		console_unlock();
		unlock_fb_info(info);
		break;
	default:
		if (!lock_fb_info(info))
			return -ENODEV;
		fb = info->fbops;
		if (fb->fb_ioctl)
			ret = fb->fb_ioctl(info, cmd, arg);
		else
			ret = -ENOTTY;
		unlock_fb_info(info);
	}
	return ret;
}
FrameBuffer驱动的框架就介绍到这来,总结一下:
1)构建一个fb_info数据结构,用来描述帧缓冲设备;
2)调用FrameBuffer驱动模块提供的接口函数register_framebuffer来注册帧缓冲设备;
3)对FrameBuffer设备文件的操作过程是,首先执行FrameBuffer驱动函数,然后根据注册的帧缓冲设备的次设备号得到注册的fb_info,最后调用具体的帧缓冲设备的操作函数;

分享到:
评论

相关推荐

    Linux设备驱动之Framebuffer分析

    在Linux内核中,Framebuffer(帖缓冲)驱动...其中Frmaebuffer驱动接口为fbmem.c,此文件提供了LCD驱动的通用文件操作接口,如read 、write、 ioctl等应用程序可能应用到的文件接口,特定平台的LCD驱动程序可以实现自己的

    基于linux2.6.30.4 framebuffer移植LCD驱动到FL2440开发板

    4、 驱动移植相关及应用程序接口相关重要数据结构分析 5、 在linux2.6.30.4内核中添加(移植)LCD驱动; 6、 嵌入式linux应用程序中LCD驱动接口函数的调用及其必要包含头文件和数据结构; 7、 编写一个应用程序在LCD上...

    Android底层开发技术实战详解--内核、移植和驱动.(电子工业.王振丽).part3

    8.3.1 goldfish中的framebuffer驱动程序210 8.3.2 使用gralloc模块的驱动程序214 8.4 msm高通处理器中的显示驱动实现224 8.4.1 msm中的framebuffer驱动程序225 8.4.2 msm中的gralloc驱动程序227 8.5 omap...

    Android底层开发技术实战详解--内核、移植和驱动.(电子工业.王振丽).part1

    8.3.1 goldfish中的framebuffer驱动程序210 8.3.2 使用gralloc模块的驱动程序214 8.4 msm高通处理器中的显示驱动实现224 8.4.1 msm中的framebuffer驱动程序225 8.4.2 msm中的gralloc驱动程序227 8.5 omap...

    Android底层开发技术实战详解--内核、移植和驱动.(电子工业.王振丽).part2

    8.3.1 goldfish中的framebuffer驱动程序210 8.3.2 使用gralloc模块的驱动程序214 8.4 msm高通处理器中的显示驱动实现224 8.4.1 msm中的framebuffer驱动程序225 8.4.2 msm中的gralloc驱动程序227 8.5 omap...

    基于Framebuffer的MCU-LCD驱动设计

    对Framebuffer自身的框架及MCU-LCD的硬件接口进行了分析和研究,根据Framebuffer的架构并结合MCU-LCD自身的特点,在比较了RGB与MCU优劣的基础上,设计了支持Linux帧缓冲的MCU-LCD设备驱动程序结果,实现了内核...

    Android驱动开发权威指南

    15.1.2 Framebuffer驱动 15.2 Android Framebuffer子系统实践 15.2.1硬件基础 15.2.2 CPU侧显示驱动模块 15.2.3 LCM驱动模块 15.3 Android系统对Framebuffer的使用 第16章Input子系统 16.1 Linux Input一般子系统 ...

    嵌入式系统Linux 下液晶显示的实现

    介绍了嵌入式微处理器PXA270的LCD控制器与SHARP公司的液晶屏LQ035Q7DH06,分析了TFT显示器基本原理,结合它们的工作时序设计了LCD的驱动电路,并在嵌入式操作系统Linux下设计了相应的驱动程序,实现了嵌入式设备的TFT...

    基于Linux的人机交互接口设备驱动程序的设计

    文中按照驱动的设计流程为主线给出了各设备驱动程序的控制器设置、GPIO口设置、中断设置等关键部分的详细代码分析。   文中所述的设备驱动已经能够在Unity805plus平台的媒体播放器上稳定运行,并通过了初步...

    嵌入式Linux程序设计案例与实验教程(配套光盘)第一部分

    第4章 嵌入式Linux接口设计与驱动程序53 4.1 驱动程序设计基础53 4.1.1 Linux驱动程序简介53 4.1.2 开发驱动程序的方法53 4.1.3 设备驱动程序的分类53 4.1.4 主设备号和次设备号54 4.1.5 设备文件系统(devfs...

    高清嵌入式系统中的DVI驱动开发

    以飞思卡尔半导体的MX51为系统硬件平台,给出了...分析了framebuffer的实现机制及其在驱动中的应用;详细讲述Linux2.6.28内核下基于framebuffer开发DVI驱动的方法及步骤。该设计应用于高清机顸盒等产品中,效果良好。

    嵌入式Linux程序设计案例与实验教程-实例代码

    第4章 嵌入式Linux接口设计与驱动程序53 4.1 驱动程序设计基础53 4.1.1 Linux驱动程序简介53 4.1.2 开发驱动程序的方法53 4.1.3 设备驱动程序的分类53 4.1.4 主设备号和次设备号54 4.1.5 设备文件系统...

    嵌入式Linux程序设计案例与实验教程(配套光盘)第三部分

    第4章 嵌入式Linux接口设计与驱动程序53 4.1 驱动程序设计基础53 4.1.1 Linux驱动程序简介53 4.1.2 开发驱动程序的方法53 4.1.3 设备驱动程序的分类53 4.1.4 主设备号和次设备号54 4.1.5 设备文件系统(devfs...

    嵌入式Linux程序设计案例与实验教程(配套光盘)第二部分

    第4章 嵌入式Linux接口设计与驱动程序53 4.1 驱动程序设计基础53 4.1.1 Linux驱动程序简介53 4.1.2 开发驱动程序的方法53 4.1.3 设备驱动程序的分类53 4.1.4 主设备号和次设备号54 4.1.5 设备文件系统(devfs...

    Android技术内幕.系统卷 pdf

    5.1.3 framebuffer驱动的实现机制 /190 5.2 视频驱动(v4l和v4l2)/201 5.2.1 v4l2介绍 /201 5.2.2 v4l2的原理和构架 /201 5.2.3 v4l2的实现 /202 5.3 音频驱动(oss和alsa)/208 5.3.1 oss与alsa介绍 /208 ...

    Magic ARM 2410

    6.11 U 盘驱动程序编译与使用实验...........253 6.12 USB 键盘与鼠标应程序实验..............256 6.13 FrameBuffer模块应用实验.................261 6.14 video4linux 模块应用实验...................268 ...

    精通Qt4编程(第二版)源代码

    \1.1.4 第一个Qt程序的代码分析 8 \1.2 使用Qt布局管理器 11 \1.3 关联操作 12 \1.4 小结 13 \第2章 对话框——QDialog 14 \2.1 自定义对话框 14 \2.1.1 建立新类 14 \2.1.2 添加子窗口部件 15 \2.2 加入主...

    精通qt4编程(源代码)

    \1.1.4 第一个Qt程序的代码分析 8 \1.2 使用Qt布局管理器 11 \1.3 关联操作 12 \1.4 小结 13 \第2章 对话框——QDialog 14 \2.1 自定义对话框 14 \2.1.1 建立新类 14 \2.1.2 添加子窗口部件 15 \2.2 加入主程序 22 \...

Global site tag (gtag.js) - Google Analytics