📄 关于frambuffer - ~ 悠悠风信子 ~ - csdnblog.htm
字号:
<P>#i nclude <linux/fb.h></P>
<P>//a framebuffer device structure;</P>
<P>typedef struct fbdev{</P>
<P> int fb;</P>
<P> unsigned long
fb_mem_offset;</P>
<P> unsigned long fb_mem;</P>
<P> struct fb_fix_screeninfo
fb_fix;</P>
<P> struct fb_var_screeninfo
fb_var;</P>
<P> char dev[20];</P>
<P>} FBDEV, *PFBDEV;</P>
<P>//open & init a frame buffer</P>
<P>//to use this function,</P>
<P>//you must set FBDEV.dev="/dev/fb0"</P>
<P>//or "/dev/fbX"</P>
<P>//it's your frame buffer.</P>
<P>int fb_open(PFBDEV pFbdev);</P>
<P>//close a frame buffer</P>
<P>int fb_close(PFBDEV pFbdev);</P>
<P>//get display depth</P>
<P>int get_display_depth(PFBDEV pFbdev);</P>
<P>//full screen clear</P>
<P>void fb_memset(void *addr, int c, size_t len);</P>
<P>#endif</P>
<P><!--[if !supportEmptyParas]--> <!--[endif]--></P>
<P>/******************</P>
<P>File name : fbtools.c</P>
<P>*/</P>
<P>#i nclude <stdio.h></P>
<P>#i nclude <stdlib.h></P>
<P>#i nclude <fcntl.h></P>
<P>#i nclude <unistd.h></P>
<P>#i nclude <string.h></P>
<P>#i nclude <sys/ioctl.h></P>
<P>#i nclude <sys/mman.h></P>
<P>#i nclude <asm/page.h></P>
<P>#i nclude "fbtools.h"</P>
<P>#define TRUE 1</P>
<P>#define FALSE 0</P>
<P>#define MAX(x,y)
((x)>(y)?(x)y))</P>
<P>#define MIN(x,y)
((x)<(y)?(x)y))</P>
<P>//open & init a frame buffer</P>
<P>int fb_open(PFBDEV pFbdev)</P>
<P>{</P>
<P> pFbdev->fb =
open(pFbdev->dev, O_RDWR);</P>
<P> if(pFbdev->fb < 0)</P>
<P> {</P>
<P>
printf("Error opening %s: %m. Check kernel config\n",
pFbdev->dev);</P>
<P>
return FALSE;</P>
<P> }</P>
<P> if (-1 ==
ioctl(pFbdev->fb,FBIOGET_VSCREENINFO,&(pFbdev->fb_var)))</P>
<P> {</P>
<P>
printf("ioctl FBIOGET_VSCREENINFO\n");</P>
<P>
return FALSE;</P>
<P> }</P>
<P> if (-1 ==
ioctl(pFbdev->fb,FBIOGET_FSCREENINFO,&(pFbdev->fb_fix)))</P>
<P> {</P>
<P>
printf("ioctl FBIOGET_FSCREENINFO\n");</P>
<P>
return FALSE;</P>
<P> }</P>
<P> //map physics address to
virtual address</P>
<P> pFbdev->fb_mem_offset =
(unsigned long)(pFbdev->fb_fix.smem_start) &
(~PAGE_MASK);</P>
<P> pFbdev->fb_mem =
(unsigned long int)mmap(NULL, pFbdev->fb_fix.smem_len +
pFbdev->fb_mem_offset,
PROT_READ | PROT_WRITE, MAP_SHARED, pFbdev->fb, 0);</P>
<P> if (-1L == (long)
pFbdev->fb_mem) </P>
<P> {</P>
<P>
printf("mmap error! mem:%d offset:%d\n", pFbdev->fb_mem,
pFbdev->fb_mem_offset);</P>
<P>
return FALSE;</P>
<P> }</P>
<P> return TRUE;</P>
<P>}</P>
<P>//close frame buffer</P>
<P>int fb_close(PFBDEV pFbdev)</P>
<P>{</P>
<P> close(pFbdev->fb);</P>
<P> pFbdev->fb=-1;</P>
<P>}</P>
<P>//get display depth</P>
<P>int get_display_depth(PFBDEV pFbdev);</P>
<P>{</P>
<P> if(pFbdev->fb<=0)</P>
<P> {</P>
<P>
printf("fb device not open, open it first\n");</P>
<P>
return FALSE;</P>
<P> }</P>
<P> return
pFbdev->fb_var.bits_per_pixel;</P>
<P>}</P>
<P>//full screen clear</P>
<P>void fb_memset (void *addr, int c, size_t len)</P>
<P>{</P>
<P> memset(addr, c, len);</P>
<P>}</P>
<P>//use by test</P>
<P>#define DEBUG</P>
<P>#ifdef DEBUG</P>
<P>main()</P>
<P>{</P>
<P> FBDEV fbdev;</P>
<P> memset(&fbdev, 0,
sizeof(FBDEV));</P>
<P> strcpy(fbdev.dev,
"/dev/fb0");</P>
<P>
if(fb_open(&fbdev)==FALSE)</P>
<P> {</P>
<P>
printf("open frame buffer error\n");</P>
<P>
return;</P>
<P> }</P>
<P> fb_memset(fbdev.fb_mem +
fbdev.fb_mem_offset, 0, fbdev.fb_fix.smem_len);</P>
<P>
fb_close(&fbdev);</P>
<P>}</P>
<P>(二)基于Linux核心的汉字显示的尝试</P>
<P>我们以一个简单的例子来说明字符显示的过程。我们假设是在虚拟终端1(/dev/tty1)下运行一个如下的简单程序。</P>
<P>main ( )</P>
<P>{</P>
<P>puts("hello, world.\n");</P>
<P>}</P>
<P>puts
函数向缺省输出文件(/dev/tty1)发出写的系统调用write(2)。系统调用到linux核心里面对应的核心函数是console.c中的
con_write(),con_write()最终会调用do_con_write( )。在do_con_write(
)中负责把"hello, world.\n"这个字符串放到tty1对应的缓冲区中去。</P>
<P>do_con_write( )还负责处理控制字符和光标的位置。让我们来看一下do_con_write()这个函数的声明。</P>
<P>static int do_con_write(struct tty_struct * tty, int from_user,
const unsigned char *buf, int count) </P>
<P>其中tty是指向tty_struct结构的指针,这个结构里面存放着关于这个tty的所有信息(请参照
linux/include/linux/tty.h)。Tty_struct结构中定义了通用(或高层)tty的属性(例如宽度和高度等)。在do_con_write(
)函数中用到了tty_struct结构中的driver_data变量。driver_data是一个vt_struct指针。在vt_struct结构中包含这个tty的序列号(我们正使用tty1,所以这个序号为1)。Vt_struct结构中有一个vc结构的数组vc_cons,这个数组就是各虚拟终端的私有数据。</P>
<P>static int do_con_write(struct tty_struct * tty, int
from_user,const unsigned char *buf, int count)</P>
<P>{</P>
<P>struct vt_struct *vt = (struct vt_struct
*)tty->driver_data;//我们用到了driver_data变量</P>
<P>. . . . .</P>
<P>currcons = vt->vc_num; file://我们在这里的vc_nums就是1</P>
<P>. . . . .</P>
<P>}</P>
<P>要访问虚拟终端的私有数据,需使用vc_cons〔currcons〕.d指针。这个指针指向的结构含有当前虚拟终端上光标的位置、缓冲区的起始地址、缓冲区大小等等。</P>
<P>"hello, world.\n"中的每一个字符都要经过conv_uni_to_pc(
)这个函数转换成8位的显示字符。这要做的主要目的是使不同语言的国家能把16位的UniCode码映射到8位的显示字符集上,目前还是主要针对欧洲国家的语言,映射结果为8位,不包含对双字节(double
byte)的范围。</P>
<P>这种UNICODE到显示字符的映射关系可以由用户自行定义。在缺省的映射表上,会把中文的字符映射到其他的字符上,这是我们不希望看到也是不需要的。所以我们有两个选择∶</P>
<P>1不进行conv_uni_to_pc( )的转换。</P>
<P>2加载符合双字节处理的映射关系,即对非控制字符进行1对1的不变映射。我们自己定制的符合这种映射关系的UNICODE码表是direct.uni。要想查看/装载当前系统的unicode映射表,可使外部命令loadunimap。</P>
<P>经过conv_uni_to_pc( )转换之后,"hello,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -