📄 关于framebuffer的一些文章_ - 我的文章 - t_t.htm
字号:
values */<BR>__u16 *green;<BR>__u16 *blue;<BR>__u16 *transp; /*
transparency, can be NULL */<BR>};<O:P></O:P></SPAN></P>
<P style="LINE-HEIGHT: 14pt"><SPAN lang=EN-US
style="FONT-SIZE: 10.5pt">4)
fb_info<BR>定义当显卡的当前状态;fb_info结构仅在内核中可见,在这个结构中有一个fb_ops指针,
指向驱动设备工作所需的函数集。<O:P></O:P></SPAN></P>
<P style="LINE-HEIGHT: 14pt"><SPAN lang=EN-US
style="FONT-SIZE: 10.5pt">struct fb_info {<BR>char modename[40]; /*
default video mode */<BR>kdev_t node;<BR>int flags;<BR>int open; /*
Has this been open already ? */<BR>#define FBINFO_FLAG_MODULE 1 /*
Low-level driver is a module */<BR>struct fb_var_screeninfo var; /*
Current var */<BR>struct fb_fix_screeninfo fix; /* Current fix
*/<BR>struct fb_monspecs monspecs; /* Current Monitor specs
*/<BR>struct fb_cmap cmap; /* Current cmap */<BR>struct fb_ops
*fbops;<BR>char *screen_base; /* Virtual address */<BR>struct
display *disp; /* initial display variable */<BR>struct vc_data
*display_fg; /* Console visible on this display */<BR>char
fontname[40]; /* default font name */<BR>devfs_handle_t
devfs_handle; /* Devfs handle for new name */<BR>devfs_handle_t
devfs_lhandle; /* Devfs handle for compat. symlink */<BR>int
(*changevar)(int); /* tell console var has changed */<BR>int
(*switch_con)(int, struct fb_info*);<BR>/* tell fb to switch
consoles */<BR>int (*updatevar)(int, struct fb_info*);<BR>/* tell fb
to update the vars */<BR>void (*blank)(int, struct fb_info*); /*
tell fb to (un)blank the screen */<BR>/* arg = 0: unblank */<BR>/*
arg > 0: VESA level (arg-1) */<BR>void *pseudo_palette; /* Fake
palette of 16 colors and<BR>the cursor's color for non<BR>palette
mode */<BR>/* From here on everything is device dependent */<BR>void
*par;<BR>};<O:P></O:P></SPAN></P>
<P style="LINE-HEIGHT: 14pt"><SPAN lang=EN-US
style="FONT-SIZE: 10.5pt">5) struct
fb_ops<BR>用户应用可以使用ioctl()系统调用来操作设备,这个结构就是用一支持ioctl()的这些操作的。<O:P></O:P></SPAN></P>
<P style="LINE-HEIGHT: 14pt"><SPAN lang=EN-US
style="FONT-SIZE: 10.5pt">struct fb_ops {<BR>/* open/release and
usage marking */<BR>struct module *owner;<BR>int (*fb_open)(struct
fb_info *info, int user);<BR>int (*fb_release)(struct fb_info *info,
int user);<BR>/* get non settable parameters */<BR>int
(*fb_get_fix)(struct fb_fix_screeninfo *fix, int con,<BR>struct
fb_info *info);<BR>/* get settable parameters */<BR>int
(*fb_get_var)(struct fb_var_screeninfo *var, int con,<BR>struct
fb_info *info);<BR>/* set settable parameters */<BR>int
(*fb_set_var)(struct fb_var_screeninfo *var, int con,<BR>struct
fb_info *info);<BR>/* get colormap */<BR>int (*fb_get_cmap)(struct
fb_cmap *cmap, int kspc, int con,<BR>struct fb_info *info);<BR>/*
set colormap */<BR>int (*fb_set_cmap)(struct fb_cmap *cmap, int
kspc, int con,<BR>struct fb_info *info);<BR>/* pan display
(optional) */<BR>int (*fb_pan_display)(struct fb_var_screeninfo
*var, int con,<BR>struct fb_info *info);<BR>/* perform fb specific
ioctl (optional) */<BR>int (*fb_ioctl)(struct inode *inode, struct
file *file, unsigned int cmd,<BR>unsigned long arg, int con, struct
fb_info *info);<BR>/* perform fb specific mmap */<BR>int
(*fb_mmap)(struct fb_info *info, struct file *file, struct
vm_area_struct *vma);<BR>/* switch to/from raster image mode
*/<BR>int (*fb_rasterimg)(struct fb_info *info, int
start);<BR>};<O:P></O:P></SPAN></P>
<P style="LINE-HEIGHT: 14pt"><SPAN lang=EN-US
style="FONT-SIZE: 10.5pt">6) structure map<BR>struct fb_info_gen |
struct fb_info | fb_var_screeninfo<BR>| | fb_fix_screeninfo<BR>| |
fb_cmap<BR>| | modename[40]<BR>| | fb_ops ---|--->ops on var<BR>|
| ... | fb_open<BR>| | | fb_release<BR>| | | fb_ioctl<BR>| | |
fb_mmap<BR>| struct fbgen_hwswitch -|-> detect<BR>| |
encode_fix<BR>| | encode_var<BR>| | decode_fix<BR>| |
decode_var<BR>| | get_var<BR>| | set_var<BR>| | getcolreg<BR>| |
setcolreg<BR>| | pan_display<BR>| | blank<BR>| |
set_disp<O:P></O:P></SPAN></P>
<P style="LINE-HEIGHT: 14pt"><SPAN lang=EN-US
style="FONT-SIZE: 10.5pt">[编排有点困难,第一行的第一条竖线和下面的第一列竖线对齐,第一行的第二条竖线和下面的第二列竖线对齐就可以了]<BR>这个结构
fbgen_hwswitch抽象了硬件的操作.虽然它不是必需的,但有时候很有用.<O:P></O:P></SPAN></P>
<P style="LINE-HEIGHT: 14pt"><SPAN lang=EN-US
style="FONT-SIZE: 10.5pt">2、 fbmem.c<BR>fbmem.c
处于Framebuffer设备驱动技术的中心位置.它为上层应用程序提供系统调用也为下一层的特定硬件驱动提供接口;那些底层硬件驱动需要用到这儿的接口来向系统内核注册它们自己.
fbmem.c 为所有支持FrameBuffer的设备驱动提供了通用的接口,避免重复工作.<O:P></O:P></SPAN></P>
<P style="LINE-HEIGHT: 14pt"><SPAN lang=EN-US
style="FONT-SIZE: 10.5pt">1) 全局变量<O:P></O:P></SPAN></P>
<P style="LINE-HEIGHT: 14pt"><SPAN lang=EN-US
style="FONT-SIZE: 10.5pt">struct fb_info
*registered_fb[FB_MAX];<BR>int
num_registered_fb;<O:P></O:P></SPAN></P>
<P style="LINE-HEIGHT: 14pt"><SPAN lang=EN-US
style="FONT-SIZE: 10.5pt"><BR>这两变量记录了所有fb_info 结构的实例,fb_info
结构描述显卡的当前状态,所有设备对应的fb_info
结构都保存在这个数组中,当一个FrameBuffer设备驱动向系统注册自己时,其对应的fb_info
结构就会添加到这个结构中,同时num_registered_fb 为自动加1.<O:P></O:P></SPAN></P>
<P style="LINE-HEIGHT: 14pt"><SPAN lang=EN-US
style="FONT-SIZE: 10.5pt">static struct {<BR>const char
*name;<BR>int (*init)(void);<BR>int (*setup)(void);<BR>}
fb_drivers[] __initdata= { ....};<O:P></O:P></SPAN></P>
<P style="LINE-HEIGHT: 14pt"><SPAN style="FONT-SIZE: 10.5pt">如果<SPAN
lang=EN-US>FrameBuffer设备被静态链接到内核,其对应的入口就会添加到这个表中;如果是动态加载的,即使用insmod/rmmod,就不需要关心这个表。<O:P></O:P></SPAN></SPAN></P>
<P style="LINE-HEIGHT: 14pt"><SPAN lang=EN-US
style="FONT-SIZE: 10.5pt">static struct file_operations fb_ops
={<BR>owner: THIS_MODULE,<BR>read: fb_read,<BR>write:
fb_write,<BR>ioctl: fb_ioctl,<BR>mmap: fb_mmap,<BR>open:
fb_open,<BR>release:
fb_release<BR>};<BR>这是一个提供给应用程序的接口.<O:P></O:P></SPAN></P>
<P style="LINE-HEIGHT: 14pt"><SPAN lang=EN-US
style="FONT-SIZE: 10.5pt">2)fbmem.c 实现了如下函数.<O:P></O:P></SPAN></P>
<P style="LINE-HEIGHT: 14pt"><SPAN lang=EN-US
style="FONT-SIZE: 10.5pt">register_framebuffer(struct fb_info
*fb_info);<BR>unregister_framebuffer(struct fb_info
*fb_info);<O:P></O:P></SPAN></P>
<P style="LINE-HEIGHT: 14pt"><SPAN
style="FONT-SIZE: 10.5pt">这两个是提供给下层<SPAN
lang=EN-US>FrameBuffer设备驱动的接口,设备驱动通过这两函数向系统注册或注销自己。几乎底层设备驱动所要做的所有事情就是填充fb_info结构然后向系统注册或注销它。<O:P></O:P></SPAN></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">(二)一个</SPAN><SPAN
lang=EN-US>LCD</SPAN><SPAN
style="FONT-FAMILY: 宋体">显示芯片的驱动实例</SPAN></P>
<P>以<SPAN lang=EN-US>Skeleton LCD
控制器驱动为例,在LINUX中存有一个/fb/skeleton.c的skeleton的Framebuffer驱动程序,很简单,仅仅是填充了
fb_info结构,并且注册/注销自己。设备驱动是向用户程序提供系统调用接口,所以我们需要实现底层硬件操作并且定义file_operations
结构来向系统提供系统调用接口,从而实现更有效的LCD控制器驱动程序。</SPAN></P>
<P><SPAN lang=EN-US>1)在系统内存中分配显存<BR>在fbmem.c文件中可以看到, file_operations
结构中的open()和release()操作不需底层支持,但read()、write()和
mmap()操作需要函数fb_get_fix()的支持.因此需要重新实现函数fb_get_fix()。另外还需要在系统内存中分配显存空间,大多数的LCD控制器都没有自己的显存空间,被分配的地址空间的起始地址与长度将会被填充到fb_fix_screeninfo
结构的smem_start 和smem_len 的两个变量中.被分配的空间必须是物理连续的。</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>2</SPAN><SPAN
style="FONT-FAMILY: 宋体">)实现</SPAN><SPAN lang=EN-US> fb_ops
</SPAN><SPAN style="FONT-FAMILY: 宋体">中的函数</SPAN><SPAN
lang=EN-US><BR></SPAN><SPAN
style="FONT-FAMILY: 宋体">用户应用程序通过</SPAN><SPAN
lang=EN-US>ioctl()</SPAN><SPAN
style="FONT-FAMILY: 宋体">系统调用操作硬件,</SPAN><SPAN lang=EN-US>fb_ops
</SPAN><SPAN style="FONT-FAMILY: 宋体">中的函数就用于支持这些操作。(注:</SPAN><SPAN
lang=EN-US> fb_ops</SPAN><SPAN
style="FONT-FAMILY: 宋体">结构与</SPAN><SPAN lang=EN-US>file_operations
</SPAN><SPAN style="FONT-FAMILY: 宋体">结构不同,</SPAN><SPAN
lang=EN-US>fb_ops</SPAN><SPAN
style="FONT-FAMILY: 宋体">是底层操作的抽象</SPAN><SPAN
lang=EN-US>,</SPAN><SPAN style="FONT-FAMILY: 宋体">而</SPAN><SPAN
lang=EN-US>file_operations</SPAN><SPAN
style="FONT-FAMILY: 宋体">是提供给上层系统调用的接口,可以直接调用</SPAN><SPAN
lang=EN-US>.<BR><SPAN> </SPAN>ioctl()</SPAN><SPAN
style="FONT-FAMILY: 宋体">系统调用在文件</SPAN><SPAN
lang=EN-US>fbmem.c</SPAN><SPAN
style="FONT-FAMILY: 宋体">中实现,通过观察可以发现</SPAN><SPAN
lang=EN-US>ioctl()</SPAN><SPAN
style="FONT-FAMILY: 宋体">命令与</SPAN><SPAN lang=EN-US>fb_ops’s
</SPAN><SPAN style="FONT-FAMILY: 宋体">中函数的关系</SPAN><SPAN
lang=EN-US>:<BR>FBIOGET_VSCREENINFO
fb_get_var<BR>FBIOPUT_VSCREENINFO fb_set_var<BR>FBIOGET_FSCREENINFO
fb_get_fix<BR>FBIOPUTCMAP fb_set_cmap<BR>FBIOGETCMAP
fb_get_cmap<BR>FBIOPAN_DISPLAY fb_pan_display</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><BR></SPAN><SPAN
style="FONT-FAMILY: 宋体">如果我们定义了</SPAN><SPAN lang=EN-US>fb_XXX_XXX
</SPAN><SPAN style="FONT-FAMILY: 宋体">方法,用户程序就可以使用</SPAN><SPAN
lang=EN-US>FBIOXXXX</SPAN><SPAN
style="FONT-FAMILY: 宋体">宏的</SPAN><SPAN
lang=EN-US>ioctl()</SPAN><SPAN
style="FONT-FAMILY: 宋体">操作来操作硬件。</SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">文件</SPAN><SPAN
lang=EN-US>linux/drivers/video/fbgen.c</SPAN><SPAN
style="FONT-FAMILY: 宋体">或者</SPAN><SPAN
lang=EN-US>linux/drivers/video</SPAN><SPAN
style="FONT-FAMILY: 宋体">目录下的其它设备驱动是比较好的参考资料。在所有的这些函数中</SPAN><SPAN
lang=EN-US>fb_set_var()</SPAN><SPAN
style="FONT-FAMILY: 宋体">是最重要的,它用于设定显示卡的模式和其它属性,下面是函数</SPAN><SPAN
lang=EN-US>fb_set_var()</SPAN><SPAN
style="FONT-FAMILY: 宋体">的执行步骤:</SPAN> </P>
<P class=MsoNormal><SPAN lang=EN-US>1)</SPAN><SPAN
style="FONT-FAMILY: 宋体">检测是否必须设定模式</SPAN><SPAN
lang=EN-US><BR>2)</SPAN><SPAN
style="FONT-FAMILY: 宋体">设定模式</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>3)</SPAN><SPAN
style="FONT-FAMILY: 宋体">设定颜色映射</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>4) </SPAN><SPAN
style="FONT-FAMILY: 宋体">根据以前的设定重新设置</SPAN><SPAN
lang=EN-US>LCD</SPAN><SPAN
style="FONT-FAMILY: 宋体">控制器的各寄存器。</SPAN></P>
<P class=MsoNormal><SPAN
style="FONT-FAMILY: 宋体">第四步表明了底层操作到底放置在何处。在系统内存中分配显存后,显存的起始地址及长度将被设定到</SPAN><SPAN
lang=EN-US>LCD</SPAN><SPAN
style="FONT-FAMILY: 宋体">控制器的各寄存器中(一般通过</SPAN><SPAN
lang=EN-US>fb_set_var() </SPAN><SPAN
style="FONT-FAMILY: 宋体">函数),显存中的内容将自动被</SPAN><SPAN
lang=EN-US>LCD</SPAN><SPAN
style="FONT-FAMILY: 宋体">控制器输出到屏幕上。另一方面,用户程序通过函数</SPAN><SPAN
lang=EN-US>mmap()</SPAN><SPAN
style="FONT-FAMILY: 宋体">将显存映射到用户进程地址空间中,然后用户进程向映射空间发送的所有数据都将会被显示到</SPAN><SPAN
lang=EN-US>LCD</SPAN><SPAN style="FONT-FAMILY: 宋体">显示器上。</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><!--[if
!supportEmptyParas]--> <!--[endif]--><O:P></O:P></SPAN></P>
<P class=MsoNormal
style="MARGIN-LEFT: 21pt; TEXT-INDENT: -21pt"><!--[if
!supportLists]--><SPAN lang=EN-US
style="FONT-FAMILY: 宋体">三、</SPAN><!--[endif]--><SPAN
lang=EN-US>FrameBuffer</SPAN><SPAN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -