display mode cannot bfile mode changedd (800x600 16bit ),该怎么整能正常玩儿游戏呢

judejie82 日志(3) - 笨杰的个人空间 - 51Testing软件测试网 51Testing软件测试网-中国软件测试人的精神家园
1.保存下面文件hello.desktop& 在QPEDIR/apps/applications
[Desktop Entry]Comment=A Simply Application ProgramExec=helloIcon=TodayAppType=ApplicationName=Hello World
2.把写好的应用程序hello.放在& QPEDIR/bin下面
在运行qvfb&
qpe后,将会看到自己刚写好的 hello程序在PDA中有显示.
arm-linux学习笔记之minigui移植minigui-1.6.10在s3c2410平台的移植
开发板:atmel9263CPU:at9263linux-2.6.26fs:nfsLCD:TFT320 X 240
PC:ubuntu 8.10
(一)准备工作下载软件包&libminigui-1.6.10.tar.gz&mg-samples-1.6.10.tar.gz&minigui-res-1.6.10.tar.gz&mg-samples-str-1.6.2.tar.gz在/home/arm/创建一个minigui的目录,然后把这些载在的软件包放在该目录下,在分别解压缩。再在/home/arm/minigui下创建一个miniguitmp的目录,用于安装编译以后的库文件。(二 )编译 libminigui首先修改configure文件,在文件的开头加入交叉编译的路径CC=arm-9tdmi-linux-gnu-gccCPP=arm-9tdmi-linux-gnu-cppLD=arm-9tdmi-linux-gnu-ldAR=arm-9tdmi-linux-gnu-arRANLIB=arm-9tdmi-linux-gnu-ranlibSTRIP=arm-9tdmi-linux-gnu-strip然后执行[root@localhost libminigui-1.6.10]# ./configure --prefix=/home/arm/minigui/miniguitmp/ \--build=x86_64-linux \--host=arm-unknown-linux \--target=arm-unknown-linux[root@localhost libminigui-1.6.10]# make[root@localhost libminigui-1.6.10]# make install这个过程基本上不会有什么错误的执行make install的时候会把编译以后的资源安装到/home/arm/minigui/miniguitmp中,在这之下会有etc& include& lib& usr几个目录产生。¥#%#¥%说明:由于这是之后作的记录所以这一步产生的目录是include& lib& usr这三个还是四个忘记了,网上一堆说明然后进入/home/arm/minigui/miniguitmp/lib,执行[root@localhost lib]# ldconfiglibminigui的交叉编译工作就算完成了。
(三)安装minigui-res比较简单进入/home/arm/minigui/minigui-res-1.6.10目录修改config.liux文件的第11行TOPDIR=/home/arm/minigui/miniguitmp保存然后[root@localhost minigui-res-1.6.10]# make install资源文件被安装到/home/arm/minigui/miniguitmp/usr/local/lib/minigui/res下面有这几个东西bmp& cursor& font& icon& imetab(四)修改/home/arm/minigui/miniguitmp/etc/MiniGUI.cfg文件[system]&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& # GAL engine and default options&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& gal_engine=fbcon&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& defaultmode=320x240-16bpp&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& # IAL engine&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& #ial_engine=qvfb&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& #mdev=/dev/input/mice&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ial_engine=console&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& mdev=/dev/mouse&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& mtype=IMPS2&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& [fbcon]&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& defaultmode=320x240-16bpp&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& [qvfb]&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& defaultmode=320x240-16bpp&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& display=0&&&&&&&&&&&&
一般就上面几个地方要修改然后把MiniGUI.cfg下载到开发板的/etc/目录下(五)下载minigui的运行库
&&& 把PC上/home/arm/minigui/miniguitmp/lib中所有的运行库下载到开发板上的/usr/lib目录下;在把PC上/home/arm/minigui/miniguitmp/usr/local/lib下的minigui目录整个下载到开发板的/usr/lib下面,到现在开发板上应该有这些东西了在开发板的/usr/lib下面有lib.tar.bz2&&&&&&&&&&&&&& libminigui-1.6.so.10&&&&& libvcongui-1.6.so.10.0.0libmgext-1.6.so.10&&&&&&& libminigui-1.6.so.10.0.0& libvcongui.alibmgext-1.6.so.10.0.0&&& libminigui.a&&&&&&&&&&&&& libvcongui.lalibmgext.a&&&&&&&&&&&&&&& libminigui.la&&&&&&&&&&&& libvcongui.solibmgext.la&&&&&&&&&&&&&& libminigui.so&&&&&&&&&&&& miniguilibmgext.so&&&&&&&&&&&&&& libvcongui-1.6.so.10其中minigui是目录在开发板的/etc下面应该有MiniGUI.cfg文件存在。现在准备工作已经已经完成,下面应该移植一些演示程序。(六)编译mg-samples-1.6.10或者mg-samples-str-1.6.2这两个东西编译的时候比较不好整,偶太菜,费劲半天才编译通过,事后作的记录可能遗漏。1、进入/home/arm/minigui/mg-samples-1.6.10修改configure.in第30行,这一步有没有用说不清楚,改成下面的样子AC_CHECK_HEADERS($prefix/include/minigui/common.h, have_libminigui=no, foo="bar")2、修改configure文件在文件的最前面加上交叉编译的工具CC=arm-9tdmi-linux-gnu-gccCPP=arm-9tdmi-linux-gnu-cppLD=arm-9tdmi-linux-gnu-ldAR=arm-9tdmi-linux-gnu-arRANLIB=arm-9tdmi-linux-gnu-ranlibSTRIP=arm-9tdmi-linux-gnu-strip3、运行configure进行配置[root@localhost mg-samples-1.6.10]# ./configure --prefix=/home/arm/minigui/miniguitmp/ \& --build=x86_64-linux \& --host=arm-unknown-linux \& --target=arm-unknown-linux…………最后还是有configure: WARNING:&&&&&&& MiniGUI is not properly installed on the system. You need&&&&&&& MiniGUI Ver 2.0.0 or later for building this package.&&&&&&& Please configure and install MiniGUI Ver 2.0.0 first.
这个提示,不管他。4、修改src/Makefile文件找到CC = arm-9tdmi-linux-gnu-gcc改成CC = arm-9tdmi-linux-gnu-gcc -I/home/arm/minigui/miniguitmp/include -L/home/arm/minigui/miniguitmp/lib
CFLAGS = -g -O2 -`Wall -Wstrict-prototypes -pipe改成CFLAGS =-O2
LIBOBJS =& 改成LIBOBJS = -lminigui -lmgext -lm& -lpthread
LIBS =& -lminigui改成LIBS =& -lminigui -lmgext -lm& -lpthread
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \&&& $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)改成COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \&&& $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -lminigui -lmgext -lm& -lpthread
(上面的有一步无用)¥%¥#……%¥……%丫的。
这样基本上可以了,mginit.c文件里面有地方修改后也可以编译完成的,但是有./configure生成的Makefile,已经把这个地方注销掉了。象这样,省得动手修改。am__EXEEXT_2 =#am__EXEEXT_3 = scrnsaver$(EXEEXT) mginit$(EXEEXT)如果想要一起编译这个断,需要修改mginit.c源文件,暂时不说5、进入/home/arm/minigui/mg-samples-1.6.10/src运行make…………然后在res目录下会有很多可执行文件。
(七)下载演示程序吧/home/arm/minigui/mg-samples-1.6.10/src下的所有文件和目录打包成一个mg.tar.bz2的文件下载到开发板的/usr/local/mg下面没有这个目录自己“贱”一个。然后解压缩在开发板上解压缩tar -xvzf mg.tar.bz2然后删除*.c和Makefile文件rm *.c现在可以运行minigui的演示程序了。
(八)问题1、可能会有这个问题:GAL: Init GAL engine failure: fbcon. GDI: Can not initialize graphics engine!我也出现了,解决方法忘记了,网上查的,不是禁止newgal,就是修改源代码,还得上网查。
2、tty0的问题保证tty0有效不行的话就自己创建一个tty0节点:crw-r--r--&&& 1 root&&&& root&&&&&& 4,&& 0 Jan& 1 00:02 tty0
3、鼠标的问题我的是usb鼠标。3.1要支持鼠标首先要在内核中加入驱动支持:## USB Input Devices#CONFIG_USB_HID=yCONFIG_USB_HIDINPUT_POWERBOOK=yCONFIG_HID_FF=yCONFIG_HID_PID=yCONFIG_LOGITECH_FF=yCONFIG_PANTHERLORD_FF=yCONFIG_THRUSTMASTER_FF=yCONFIG_ZEROPLUS_FF=yCONFIG_USB_HIDDEV=yCONFIG_USB_SUPPORT=yCONFIG_USB_ARCH_HAS_HCD=yCONFIG_USB_ARCH_HAS_OHCI=y# CONFIG_USB_ARCH_HAS_EHCI is not setCONFIG_USB=y# CONFIG_USB_DEBUG is not set# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set大概这个样子
3.2 然后创建节点查看/proc/bus/input/devices文件#cat /proc/bus/input/devicesI: Bus="0003" Vendor="15d9" Product="0a33" Version="0110"N: Name="USB Mouse"P: Phys="usb-s3c24xx-1/input0"S: Sysfs="/class/input/input0"U: Uniq=H: Handlers="mouse0" B: EV="17"B: KEY="7 0 0 0 0 0 0B: REL="103"B: MSC="10"确定已经鼠标已经连接上了然后查看/proc/bus/input/handler# cat /proc/bus/input/handlerN: Number="0" Name="kbd"N: Number="1" Name="mousedev" Minor="32"看到Number=1 Name="mousedev" Minor="32这个东西了"
# cat /proc/devicesCharacter devices:&10 misc&13 input&29 fb
到/dev下创建#mknod /dev/input/mouse c 13 32
crw-r--r--&&& 1 root&&&& root&&&&& 13,& 32 Jan& 1 00:25 input/mouse其中13是设备号的高位 32低位上面的Minor=32和13 input定的,不小的是不是这么会事情,反正鼠标可以工作了.可以用下面的命令测试一下:# cat /dev/input/mouse??(?(?(?(8??8??8??8??8??8??8??8??(这一堆乱码就是移动鼠标的时候输出的东西,说明鼠标可以工作了。创建一个符号连接:ln -s /dev/input/mouse& /dev/mouse
修改权限chmod go+r /dev/mousechmod go+r /dev/input/mouse.
这下运行minigui的时候有鼠标了。
还有遇到的问题:
如果鼠标无法使用。 可以修改如下&25 [system]&26 # GAL engine and default options&27 gal_engine=fbcon&28 defaultmode=240x320-16bpp&29 &30 # IAL engine&31 ial_engine=console&32 mdev=/dev/mouse0&33 mtype=IMPS2这个配置一定可用. 还要注意库的使用
文章出处:DIY部落()
硬件环境:
软件环境:
VMware虚拟机下的redhat linux 9.0(完全安装)
2.准备以下源码包(下载)&
开发库:libminigui-1.6.0.tar.gz
资源文件:minigui-res-1.6.10.tar.gz
示例程序:mg-samples-str-1.6.2.tar.gz
FramBuffer:qvfb-1.1.tar.gz
3.编译安装
(1) 准备工作
在redhat linux 9.0下新建工作目录
[root@localhost /]# mkdir /minigui&&&&&&&&&&&&&&工作目录&
[root@localhost /]# mkdir /minigui/compressed /minigui/source
[root@localhost /]# cd /minigui/compressed&&&&& &&进入工作目录
说明:把第2步下载的源码包放到该目录中,即/minigui/compressed
(2)编译安装minigui-res-1.6.0.tar.gz
说明:minigui 所使用的资源,包括基本字体、图标、位图和鼠标光标。
[root@localhost compressed]# tar xzvf minigui-res-1.6.10.tar.gz –C ../source
[root@localhost compressed]# cd ../source/minigui-res-1.6.10
[root@localhost minigui-res-1.6.10]# make install
(3)编译安装libminigui-1.6.0.tar.gz
说明:minigui函数库源代码。
[root@localhost minigui-res-1.6.10]# cd /minigui/compressed
[root@localhost compressed]# tar xzvf libminigui-1.6.0.tar.gz –C ../source
[root@localhost compressed]# cd ../source/libminigui-1.6.0
[root@localhost libminigui-1.6.0]# ./configure
[root@localhost libminigui-1.6.0]# make
[root@localhost libminigui-1.6.0]# make install
(4)编译 mg-samples-str-1.6.2.tar.gz
同上原理:
[………]# ./configure
[………]# make
(5)编译安装qvfb-1.1.tar.gz
同上原理:
[………]# ./configure
[………]# make
[………]# make install
第一处:修改/boot/grub/grub.conf文件
用编辑器打开,在“kernel …………”行的后面加入如下内容:
vga=0x0317
第二处:修改/etc/ld.so.conf文件
用编辑器打开,在后面加入如下内容:
/usr/local/lib
接着为了使刚加入的内容生效,在超级终端运行下列命令:
[………]# ldconfig
第三处:修改/usr/local/etc/MiniGUI.cfg文件,打开文件之后,注意如下内容:
与上述内容不一致的,请比较后,修改。
在超级终端运行qvfb,命令如下:
[………]# qvfb &
这说明在后台运行,接着再开一终端,或按“ctrl+c”退出,然后进入示例程序目录下,运行helloworld程序:
[………]# cd /minigui/source/ mg-samples-str-1.6.2/src
[………]# ./helloworld
运行之后的效果如下图4-1所示:
图4-1& 测试minigui示例程序效果
首先你的redhat必须是安装在vm虚拟机中的那种。启动了redhat后,插上u盘,选择虚拟机的usb接口,一般默认是有2个usb1和usb2,你必须选择一个,虚拟机会自动卸载另外一个,如此你的usb接口才能在虚拟机中真正发挥作用。接下来运行fdisk -l ,系统会查找出来你的u盘,一般情况下你的虚拟机都使用的scsi硬盘(不会是ide),那么你的u盘基本上可以确定是/dev/sdb,或者是/dev/sdb1、/dev/sdb2等等。使用dmesg | more命令可以更清楚地研究配置情况。
第二,你要了解你的u盘是什么文件格式的,如果是fat格式的,那你的问题就简单得多了。只要运行如下命令加载就行了:
mkdir &/mnt/usb
mount& &-t& vfat&& /dev/sdb& /mnt/usb
如果不幸你的u盘是ntfs的,那情况就要麻烦一些了。高手可以去编译linux的内核,一般就要找支持ntfs的驱动了。先查找你的linux版本,可以使用的命令有很多,如下:
rpm& -qi& kernel
cat&& /proc/version
我的kernel版本是2.4.20-8,然后你就到google去找kernel-ntfs-2.4.20-8.***.rpm,参考,***代表不同的版本的细微差别,如果安装不上就要换版本。我的试了好几次,最后的文件是kernel-ntfs-2.4.20-8.athlon.rpm。运行如下命令安装好驱动:
rpm -ivh& kernel-ntfs-2.4.20-8.athlon.rpm
成功了没有?接下来就是简单的mount了
mount &-t&& ntfs&& /dev/sdb&& /mnt/usb
终于在xwindow桌面看到了usb的图标,好激动啊。看看u盘里面的资料,拷贝出来。呵呵。再拷一个文件到u盘。啊,mygod 磁盘写保护,怎么会这样??这样我怎么带资料出去啊,痛苦,谁来救救我。
下面是我从网上转来的一篇文章,没有试验过,大家自己参考。
Linux/Windows双系统下实现Linux对NTFS的可靠的写操作
随着windows 2000/XP的普及,越来越多的Linux爱好者面临Linux读写NTFS文件系统的困难。由于NTFS系统的复杂性和隐秘性,Open Source 对 NTFS 的reverse engineering 迄今只限于可靠的读取功能。
Captive Project 使用合法的windows XP NTFS 系统文件 作了 类似wine 的仿真,实现了linux 对NTFS 文件系统的写操作。下面是一些简单的步骤:
1. 下载 rpm package captive-static-1.1.5-0.i386.rpm
http://www.jankratochvil.net/project/captive/dist/captive-static-1.1.5-0.i386.rpm
# rpm -ivh captive-static-1.1.5-0.i386.rpm
2. 验证一下你的linux 有kernel source pakage:
# rpm -qa |grep kernel-source
如果没有的话, 先安装kernel-source, 例如
# rpm -ivh kernel-source-2.4.20-8.i386.rpm
如果你有更新kernel, 请用相应的kernel source包
3. 设置 windows system files
拷贝windows NTFS 文件: ntfs.sys 和 ntoskrnl.exe 到某linux 目录下
运行 命令:
# /usr/sbin/captive-install-acquire
该命令会搜索linux目录下的NTFS 文件,如果你没有windows NTFS 文件:
ntfs.sys 和 ntoskrnl.exe,该命令会请求是否从microsoft网站自动下载
你也可以直接拷贝两个文件到 /var/lib/captive,
注意 要使用windowsXP 的文件,win2000 的NTFS 文件不支持。
4. 运行 命令 以产生 lufs module
# /usr/share/lufs/prepmod
5. 运行命令 安装 NTFS格式 例如: C 盘
# mkdir /mnt/dosc
# mount -t captive-ntfs /dev/hda1 /mnt/dosc
captive 1.1.5 会自动寻找 NTFS 分区 并且修改/etc/fstab 文件,你可以按你所愿重新更改/etc/fstab 文件
6. 运行命令 看/mnt/dosc 是否已挂上
要使用windowsXP 的文件,win2000 的NTFS 文件不支持。
在Linux下使用sync, 及umount/mount NTFS分区 可以避免Linux重起动后NTFS分区文件丢失的问题。
测试过程中务必做好windowXP/2000的备份工作,以防不测
./helloerror:/hello: error while loading shared libraries: libqte.so.2: cannot open shared object file: No such file or directorytry to run sister hello here# /tmp/helloerror:Cannot find font definition file /home/qte/qt-embedded-free-3.3.4/lib/fonts/fontdir - is Qt installed correctly?but there is truly no direcotory named /home/qte/.... on arm now, strange!then i#mount mp3 on /petertheni export LD_LIBRARY_PATH=/path/to/my/libthen#./hellostill same error:lib not found.then iusr/qt/lib # mv libqte.so.2* /peter/mhel/ql/error:mv: cannot create symlink `/peter/mhel/ql/libqte.so.2': Operation not permittedmv: cannot create symlink `/peter/mhel/ql/libqte.so.2.3': Operation not permittedmv: unable to preserve ownership of `/peter/mhel/ql/libqte.so.2.3.1': Operationnot permittedso finally the sis lib itself is on mp3, but the two symbol links are still there on armthe lib's name become capitalized when i open it again in windows. that means i can not copy it back to arm directly now!!!that is bad, since linux is case sensitive. ok anyway,now reboot the sis-hello runs as before, so i know the /usr/qt/lib is not in use.it is the /lib/libqte that matters.so now *************************/ # ./hello./hello: error while loading shared libraries: libqte.so.2: cannot open shared object file: No such file or directory#cd lib#ln -s libqte.so.3 libqte.so.2#cd / # ./hello./hello: error while loading shared libraries: libstdc++.so.5: cannot open shared object file: No such file or directory &# cd& lib//lib # ln -s libstdc++.so.6 libstdc++.so.5#cd /&# ./hello./hello: /lib/libstdc++.so.5: version `GLIBCPP_3.2' not found (required by ./hello)later, i find libstdc++.so.5 is in /usr/local/arm/3.3.2/libpeople on net say libstdc++.so.5 and .6 are incompatiable, that's bad.**lib # ln -s libstdc\+\+-3-libc6.1-2-2.10.0.so& libstdc++.so.5peter: i make a symbol linux to a symbol link before, and it does not work,this time i think i am right,because& error message is different, and part of it is what shows up when i try to run sis_hello/hello: /lib/libstdc++.so.5: no version information available (required by /hello)Cannot find font definition file /home/qte/qt-embedded-free-3.3.4/lib/fonts/fontdir - is Qt installed correctly?**reboot arm# ./hello./hello: /lib/libstdc++.so.5: no version information available (required by ./hello)QSocket::writeBlock: Socket is not openQSocket::writeBlock: Socket is not openQSocket::writeBlock: Socket is not openNo Qt/Embedded server appears to be running.If you want to run this program as a server,add the "-qws" command-line option.peter: from all above, i believe libqte.so.3 and .2 is compatiable. but the libstdc++6refuse to corperate.********when i copy the right libstdc++from /usr/local/arm/3.3.2/arm-linux/liband make the needed symbol link to itthen#./hellothe "no version information available" error disappersbut the "Qsocket error" remains, reboot, nothing shows up on the screen.now may be the fake lqte.so is responsible!*******************now i will use a fake libstdC++, and a right lqte, wait and see/lib # ln -s libqte~1.7 libqte.so.2/lib # cd ../ # ./hello./hello: /lib/libstdc++.so.5: no version information available (required by ./hello)./hello: relocation error: /lib/libqte.so.2: undefined symbol: __cxa_pure_virtualpeter: it is obvious that the lqte is right now. something wrong is with libstdc++.and one interesting phenomenon can be seen that even the empty screen do not shows up.i think i can understand, it is because qte needs the libc++, now that my hello invokes the fake c++ lib, so the qte fails to run.*********************************since there is not enough space on arm, i need to move libqte.so.3 or libstdc++.so.6 out of arm.once that are moved onto mp3, the name will be changed(caoitalized),can i move it back? now i #mv /lib/libqte.so.3.3.4 /peterpeter/ is mp3then, reboot, no blue screen can be seen.now i will change the name of libqte back,
and copy it backit is done. you just need to be very careful about the name.copy the lib to mp3 will not ruin it. that's good.*******************so finally when there is/lib/libstdc++.so.5(plus its symbol link)/lib/libqte.so.2(symbol link is also needed)my hello runs on arm perfectly.
ubuntu的安去管理很严格,我一直不会用普通帐号在界面中复制粘贴修改关键文件今天发现了一条好命令在终端中输入sudo gnome-open /输入密码后就可以自由修改根目录的文件了~不错吧
我编译aclock时,出现问题如下:[root@localhost aclock]# make g++ -c -pipe -DQWS -fno-exceptions -fno-rtti -Wall -W -O2 -DNO_DEBUG -I/friendly-arm/x86-qtopia/qt/include -o aclock.o aclock.cpp aclock.cpp: In member function `void AnalogClock::drawClock(QPainter*)': aclock.cpp:83: no matching function for call to `QPainter::setWindow(int, int, & int, int)' aclock.cpp:85: no matching function for call to `QPainter::viewport()' aclock.cpp:88: no matching function for call to `QPainter::setViewport(int, & int, int&, int&)' aclock.cpp:94: no matching function for call to `QPainter::rotate(int)' aclock.cpp:100: no matching function for call to `QPainter::rotate(int)' aclock.cpp:107: no matching function for call to `QPainter::rotate(in
参见 qpainter.h (qt-embedded-2.3.7\include)setWindow函数的声明是用#ifndef QT_NO_TRANSFORMATIONS括起来的, 说明你的config里定义了这个宏, 所以这些函数都没编进你的qte
注释这个宏即可.
[root@jude jude_qt]# makeMakefile:119: warning: overriding commands for target `moc_hello.cpp'Makefile:116: warning: ignoring old commands for target `moc_hello.cpp'gcc& -o hello hello.o main.o hello.o moc_hello.o moc_hello.o& -L/usr/x-qtopia/qt-2.3.7/lib -lm -lqtehello.o(.text+0x0): In function `Hello::Hello[not-in-charge](QWidget*, char const*, unsigned)':: multiple definition of `Hello::Hello[not-in-charge](QWidget*, char const*, unsigned)'hello.o(.text+0x0): first defined herehello.o(.text+0x190): In function `Hello::Hello[in-charge](QWidget*, char const*, unsigned)':: multiple definition of `Hello::Hello[in-charge](QWidget*, char const*, unsigned)'hello.o(.text+0x190): first defined herehello.o(.text+0x320): In function `Hello::~Hello [not-in-charge]()':: multiple definition of `Hello::~Hello [not-in-charge]()'hello.o(.text+0x320): first defined herehello.o(.text+0x344): In function `Hello::~Hello [in-charge]()':: multiple definition of `Hello::~Hello [in-charge]()'hello.o(.text+0x344): first defined herehello.o(.text+0x368): In function `Hello::~Hello [in-charge deleting]()':: multiple definition of `Hello::~Hello [in-charge deleting]()'hello.o(.text+0x368): first defined heremoc_hello.o(.text+0xcc): In function `Hello::staticMetaObject()':: multiple definition of `Hello::staticMetaObject()'moc_hello.o(.text+0xcc): first defined heremoc_hello.o(.text+0x0): In function `Hello::className() const':: multiple definition of `Hello::className() const'moc_hello.o(.text+0x0): first defined heremoc_hello.o(.data+0x0): multiple definition of `Hello::metaObj'moc_hello.o(.data+0x0): first defined heremoc_hello.o(.text+0xc): In function `Hello::initMetaObject()':: multiple definition of `Hello::initMetaObject()'moc_hello.o(.text+0xc): first defined heremoc_hello.o(.text+0x74): In function `Hello::tr(char const*)':: multiple definition of `Hello::tr(char const*)'moc_hello.o(.text+0x74): first defined heremoc_hello.o(.text+0xa0): In function `Hello::tr(char const*, char const*)':: multiple definition of `Hello::tr(char const*, char const*)'moc_hello.o(.text+0xa0): first defined here/usr/x-qtopia/qt-2.3.7/lib/libqte.so: undefined reference to `QWizard::staticMetaObject()'collect2: ld returned 1 exit statusmake: *** [hello] Error 1
&.pro文件中的qt改为qtopia
在Qt中编程,利用Signal和Slot进行对象之间的通信是Qt的主要特征。它与Windows中的消息机制非常类似,但是Signal和Slot机制真正实现了一种消息的封装。当对象的状态改变时,发出Signal,通知所有的Slot接受Signal,尽管它不知道哪些函数是Slot,Slot一开始也不知道哪些Signal可以接收。Signal和Slot之间不是一一对应的关系,一个Signal可以发给多个Slot, Slot也可以接收多个Signal。Slot除了可以接收Signal以外,与其它的成员函数没有区别。这种机制比使用回调函数要灵活,但是会减慢程序的运行速度。不过在现在高速CPU的面前,这种损失是无足轻重的,而且它还能保证程序的简明性和灵活性,非常便利。
在Qt的组件中,不仅定义了常用的成员变量和成员函数,还定义了所有与该组件相关的Signal和Slot。
要将组件组合起来,最简单的方法就是使用Qt Designer。首先要启动Qt Designer,在Linux命令模式下,键入以下命令(假设Qt安装在/usr/local下):
cd qt-2.3.2/bin
./designer
这样就可以启动一个与Windows下的Delphi相类似的如图1的界面。
图1 Qt Designer界面
然后新建一个QFrame,将自己需要的组件直接拖拉到这个Frame中,相信很多人都有过这样的经历,此处就不再详细描述了。完成之后存盘时,会将这个新的组件保存为一个扩展名为.ui的文件。假设所存的文件名为test.ui,用vi test.ui来查看这个文件,发现这是一个用xml语言写的一个文本。下面用这个test.ui生成相应的test.h和test.cpp。同样还是在这个目录下,可以看到一个uic的工具,这个是Qt专门用来将ui文件生成.h和.cpp文件的,在终端模式下键入以下命令:
&progen -n hello -o hello.pro./uic -o test.h test.ui &./uic -o test.cpp -impl hello.h& test.uivi main.cpp 然后加些自己需要的代码&progen -n hello -o hello.protmake -o Makefile hello.pro
生成Makefile文件make
生成需要的可执行文件然后 qvrb& ./hello -qws即可观察到程序执行结果&&&
此时就能看到生成了相应test.h和test.cpp,这是一个类。当然这只是一些表面的东西,还需要在这些代码中添加相应的Signal和Slot,完成所需要的操作。值得注意的是,相应版本生成的ui最好用相应版本的uic来生成代码。
./configure -xplatform linux-arm-g++ -qconfig qpe编译的出错情况是这样:echo '#include "kernel/qt.h"' &allmoc.cpparm-linux-g++ -E -DQT_MOC_CPP -I/usr/jin/qteqpe/qt-2.3.7/include -pipe -DQWS -fno-exceptions -fno-rtti -O2 -Wall -W -DNO_DEBUG -fPIC -DQT_NO_IMAGEIO_MNG -DQT_NO_QWS_VOODOO3 -DQT_NO_QWS_MACH64 -DQT_NO_QWS_MATROX -DQT_NO_QWS_VNC -DQT_NO_QWS_VGA_16 -DQT_NO_QWS_DEPTH_4 -DQT_NO_QWS_DEPTH_8 -DQT_NO_QWS_DEPTH_24 -DQT_NO_QWS_DEPTH_32 -DQT_BUILTIN_GIF_READER=0 -DQT_NO_IMAGEIO_JPEG -DQT_NO_IMAGEIO_MNG -DQT_NO_SM_SUPPORT -I/usr/jin/qteqpe/qt-2.3.7/src/3rdparty/zlib -I/usr/jin/qteqpe/qt-2.3.7/src/3rdparty/libpng -I3rdparty/kernel -I3rdparty/tools &allmoc.h allmoc.cpp/bin/sh: line 1: arm-linux-g++: command not foundmake[1]: *** [allmoc.cpp] Error 127make[1]: Leaving directory `/usr/jin/qteqpe/qt-2.3.7/src'make: *** [sub-src] Error 2[root@localhost qt-2.3.7]#
SYSCONF_LINK = arm-linux-gccSYSCONF_LINK_SHLIB = arm-linux-gcc均改为SYSCONF_LINK = arm-linux-g++SYSCONF_LINK_SHLIB = arm-linux-g++
[root@localhost host]#cd qt-x11
[root@localhost qt-x11]#export QTDIR=$PWD
[root@localhost qt-x11]#echo yes|./configure -static -no-xft -no-opengl -no-sm
[root@localhost qt-x11]# make -C src/moc
[root@localhost qt-x11]# cp src/moc/moc bin/
[root@localhost qt-x11]# make -C src
注:此处可能会提示错误信息,那是由于你的系统没有安装X窗口系统环境有问题,错误提示信息如下所示:
kernel/qt_x11.h:65:22: X11/Xlib.h: 没有那个文件或目录
kernel/qt_x11.h:71:23: X11/Xutil.h: 没有那个文件或目录
kernel/qt_x11.h:72:21: X11/Xos.h: 没有那个文件或目录
kernel/qt_x11.h:73:23: X11/Xatom.h: 没有那个文件或目录
kernel/qt_x11.h:84:34: X11/extensions/shape.h: 没有那个文件或目录
kernel/qpsprinter.cpp: In member function `USHORT
QPSPrinterFontTTF::unicode_for_glyph(int)':
kernel/qpsprinter.cpp:3328: warning: `ULONG offset' might be used uninitialized
in this function
kernel/qpsprinter.cpp: In constructor `QPSPrinterFont::QPSPrinterFont(const
QFont&, QPSPrinterPrivate*)':
kernel/qpsprinter.cpp:5195: `XGetFontPath' undeclared (first use this function)
kernel/qpsprinter.cpp:5195: (Each undeclared identifier is reported only once
for each function it appears in.)
kernel/qpsprinter.cpp:5235: `XFreeFontPath' undeclared (first use this
make: *** [kernel/qpsprinter.o] Error 1
解决方法:利用“添加/删除程序”给系统安装X软件开发包
: undefined reference to `operator new(unsigned)'/usr/local/arm/qt_x86/qt/lib/libqte.so: undefined reference to `operator new[](unsigned)'/usr/local/arm/qt_x86/qt/lib/libqte.so: undefined reference to `__cxa_pure_virtual'/usr/local/arm/qt_x86/qt/lib/libqte.so: undefined reference to `operator delete[](void*)'collect2: ld returned 1 exit statusmake: *** [hello] Error 1
【原因】:原因是Makefile 里的LINK 项应该为g++ 而不是gcc , 修改tmake/lib/qws/linux-generic-g++/tmake.conf#vi $TMAKEPATH/tmake.conf将TMAKE_LINK = gcc 和TMAKE_LINK_SHLIB = gcc分别修改成TMAKE_LINK = g++和TMAKE_LINK_SHLIB = g++#tmake –o Makefile hello.pro此时查看Makefile 里的LINK 项应该已经为g++
tar xfz qt-x11-2.3.2.tar.gz cd qt-2.3.2 export QTDIR=$PWD export PATH=$QTDIR/bin:$PATH export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH ./configure -no-opengl 结果又报错: In file included from kernel/qt_x11.h:76, from kernel/qpsprinter.cpp:97: /usr/X11R6/include/X11/Xft/Xft.h:35:31: freetype/freetype.h: 没有那个 文件或目录 In file included from kernel/qt_x11.h:76, from kernel/qpsprinter.cpp:97: /usr/X11R6/include/X11/Xft/Xft.h:52: syntax error before `;' token /usr/X11R6/include/X11/Xft/Xft.h:86: 'FT_UInt' is used as a type, but is not defined as a type. /usr/X11R6/include/X11/Xft/Xft.h:93: 'FT_UInt' is used as a type, but is not defined as a type. /usr/X11R6/include/X11/Xft/Xft.h:190: parse error before `*' token /usr/X11R6/include/X11/Xft/Xft.h:295: parse error before `*' token /usr/X11R6/include/X11/Xft/Xft.h:354: parse error before `*' token /usr/X11R6/include/X11/Xft/Xft.h:393: parse error before `*' token /usr/X11R6/include/X11/Xft/Xft.h:399: parse error before `*' token /usr/X11R6/include/X11/Xft/Xft.h:408: type specifier omitted for parameter ` FT_UInt' /usr/X11R6/include/X11/Xft/Xft.h:408: parse error before `,' token /usr/X11R6/include/X11/Xft/Xft.h:418: parse error before `*' token /usr/X11R6/include/X11/Xft/Xft.h:461: parse error before `*' token make[2]: *** [kernel/qpsprinter.o] Error 1 make[2]: Leaving directory `/opt/qt-2.3.2/src' make[1]: *** [sub-src] Error 2 make[1]: Leaving directory `/opt/qt-2.3.2' make: *** [init] Error 2
先cd /usr/include ln -s freetype2/freetype freetype
然后再回到qt-2.3.2 再make 即可
我的错误信息......global1.cpp:39:23: uuid/uuid.h: No such file or directoryglobal1.cpp: In static member function `static QUuid Global::generateUuid()':global1.cpp:188: `::uuid_generate' undeclared (first use here)make[1]: *** [.obj/linux-generic-g++//global1.o] Error 1make[1]: Leaving directory `/usr/src/qtopia-free-1.7.0/src/libraries/qtopia1'make: *** [libraries/qtopia1] Error 2You have new mail in /var/spool/mail/root
QT编译补遗&&&&&在安装完整版的RedHat9下,按照前面那个傻瓜教程可以一次编译通过qtopia的开发环境,但是…… 在非完整版的Rh9下面就行不通了。经过无数次的尝试,总结如下:问题一: 找不到 uuid.h解决: 下载 ,解压编译,把 e2fsprogs-1.35/lib/uuid 目录拷贝到 qtopia-free-1.7.0/include问题二: 找不到 -luuid把e2fsprogs-1.35/lib/uuid/libuuid.a 文件拷贝到 usr/lib 或者 qtopia-free-1.7.0/lib
安装:1.建立本机QTOPIA虚拟平台
&软件:& tmake-1.11.tar.gz&&&&&&&&& //编译工具,如progen与tmake&&&&& qtopia-free-1.7.0.tar.gz&&&&& //QTE的桌面环境程序&&&&& qt-embedded-2.3.7.tar.gz&& //提供qte的库&&&&& qt-x11-2.3.2.tar.gz&&&&&&&&&&&&&& //为了生成相应的QT工具,如designer和qvfb等)
首先准备软件安装包:tmake工具安装包&& qt-embedded安装包&& qt-x11 安装包 和具有友好人机界面的qtopia-free安装包
把软件包下载到提前建立的x86-qtopia目录下.为防止版本的不同而造成的冲突,选择软件包时需要注意一些基本原则,因为qt-x11安装包的两个工具uic和designer产生的源文件会与qt-embedded库一起被编译链接,本着向前兼容的原则,qt-x11安装包的版本必须比qt-embedded安装包的版本旧..
1,安装tmake&tar xfz tmake-1.11.tar.gz[root@jude x86-qtopia]# export TMAKEDIR=/root/x86-qtopia/tmake-1.11[root@jude x86-qtopia]# export TMAKEPATH=/root/x86-qtopia/tmake-1.11/lib/qws/linux-x86-g++/[root@jude x86-qtopia]# export PATH=$TMAKEDIR/bin:$PATH
2.安装Qt/embedded2.3.7[root@jude x86-qtopia]# tar xfz qtopia-free-1.7.0.tar.gz
[root@jude root]# cd x86-qtopia/[root@jude x86-qtopia]# cd qt-2.3.7/
[root@jude qt-2.3.7]# export QPEDIR="/root/x86-qtopia/qtopia-free-1.7.0"[root@jude qt-2.3.7]# export QTEDIR="/root/x86-qtopia/qt-2.3.7"[root@jude qt-2.3.7]# cp /root/x86-qtopia/qtopia-free-1.7.0/src/qt/qconfig-qpe.h&& src/tools/[root@jude qt-2.3.7]# ./configure -qvfb -depths 4,8,16,32 -qconfig[root@jude qt-2.3.7]# make sub-src&&&& //精简方式编译开发包.[root@jude qt-2.3.7]# cd ..
3.安装qt/x11&& 2.3.2[root@jude x86-qtopia]# tar xfz qt-x11-2.3.2.tar.gz[root@jude x86-qtopia]# cd qt-2.3.2/[root@jude qt-2.3.2]# export QTDIR=$PWD[root@jude qt-2.3.2]# export PATH=/root/x86-qtopia/qt-2.3.2/bin/:$PATH[root@jude qt-2.3.2]# export LD_LIBRARY_PATH=/root/x86-qtopia/qt-2.3.2/lib/:$LD_LIBRARY_PATH[root@jude qt-2.3.2]# ./configure -no-opengl[root@jude qt-2.3.2]# make注意在make 之前& 需要 先先cd /usr/include ln -s freetype2/freetype freetype[root@jude qt-2.3.2]# make -C tools/qvfb[root@jude qt-2.3.2]# mv tools/qvfb/qvfb& bin[root@jude qt-2.3.2]# cp bin/uic /root/x86-qtopia/qt-2.3.7/bin/[root@jude qt-2.3.2]# cd ..
验证:进入/bin&& ./desiger& 弹出QT界面
(点击有大图)
5.安装Qtopia
[root@jude x86-qtopia]# cd qtopia-free-1.7.0[root@jude qtopia-free-1.7.0]# cd qtopia-free-1.7.0[root@jude qtopia-free-1.7.0]# export QTDIR=$QTEDIR[root@jude qtopia-free-1.7.0]#export QPEDIR=$PWD[root@jude qtopia-free-1.7.0]#export PATH=$QPEDIR/bin:$PATH[root@jude qtopia-free-1.7.0]#cd src[root@jude qtopia-free-1.7.0]#./configure&& 如果环境变量没设好,将会出现错误&& global1.cpp:39:23: uuid/uuid.h: 没有那个文件或目录&& global1.cpp: In static member function `static QUuid Global::generateUuid()':&& global1.cpp:188: `::uuid_generate' undeclared (first use here)&& make[1]: *** [.obj/linux-generic-g++//global1.o] Error 1&& make[1]: Leaving directory `/root/x86-qtopia/qtopia-free-1.7.0/src/libraries/qtopia1'&& make: *** [libraries/qtopia1] Error 2
安装 e2fsprogs-1.39cd e2fsprogs-1.39./configure -enable-elf-shlibsmakemake install lib/uuid/问题一: 找不到 uuid.h解决: 下载 e2fsprogs-1.35.tar.gz,解压编译,把 e2fsprogs-1.35/lib/uuid 目录拷贝到 qtopia-free-1.7.0/include
问题二: 找不到 -luuid把e2fsprogs-1.35/lib/uuid/libuuid.a 文件拷贝到 usr/lib 或者 qtopia-free-1.7.0/lib
[root@jude src]# make
[root@jude qtopia-free-1.7.0]#cd ../..
6.安装Qtopia桌面[root@jude qtopia-free-1.7.0]#cd qtopia-free-1.7.0/src[root@jude src]# export QTEDIR=$QTEDIR[root@jude src]#./configure -qtopiadesktop [root@jude src]#make[root@jude src]#mv qtopiadesktop/bin/qtopiadesktop ../bin[root@jude src]#cd ..
7.在PC机上运行QPE& qvfb&& qpe&
8.添加自己的应用程序到QPE中.& (1)新建一个hello.desktop文件,保存在$QPEDIR/apps/applications&&&& [Desktop Entry]&&&& Comment=A Simply Application Program&&&& Exec=hello&&&& Icon=TodayApp&&&& Type=Application&&&& Name=Hello World& (2)把自己通过QT 等一系列的变换后,得到hello 可执行文件&&&& 然后把其保存在$QPEDIR/bin文件夹下
非常好的将framebuffer驱动的文章,看过后受益匪浅
*一、FrameBuffer的原理* &&& FrameBuffer 是出现在 2.2.xx 内核当中的一种驱动程序接口。
Linux是工作在保护模式下,所以用户态进程是无法象DOS那样使用显卡BIOS里提供的中断调用来实现直接写屏,Linux抽象出FrameBuffer这-个设备来供用户态进程实现直接写屏。Framebuffer机制模仿显卡的功能,将显卡硬件结构抽象掉,可以通过Framebuffer的读写直接对显存进行操-作。用户可以将Framebuffer看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。这种操-作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等具体细节。这些都是由Framebuffer设备驱动来完成的。 &&& 但Framebuffer本身不具备任何运算数据的能力,就只好比是一个暂时存放水的水池.CPU将运算后的结果放到这个水池, 水池再将结果流到显示器.中间不会对数据做处理. 应用程序也可以直接读写这个水池的内容.在这种机制下, 尽管Framebuffer需要真正的显卡驱动的支持,但所有显示任务都有CPU完成,因此CPU负担很重. framebuffer的设备文件一般是 /dev/fb0、/dev/fb1 等等。 可以用命令: #dd if=/dev/zero ōf=/dev/fb 清空屏幕. 如果显示模式是
位色,用命令:$ dd if=/dev/zero ōf=/dev/fb0 bs=1024 count=768 清空屏幕; 用命令: #dd if=/dev/fb ōf=fbfile 可以将fb中的内容保存下来; 可以重新写回屏幕: #dd if=fbfile ōf=/dev/fb; 在使用Framebuffer时,Linux是将显卡置于图形模式下的.
&&& 在应用程序中,一般通过将 FrameBuffer 设备映射到进程地址空间的方式使用,比如下面的程序就打开 /dev/fb0 设备,并通过 mmap 系统调用进行地址映射,随后用 memset 将屏幕清空(这里假设显示模式是
位色模式,线性内存模式):
unsigned char* fb_ fb = open ("/dev/fb0", O_RDWR); fb_mem = mmap (NULL, , PROT_READ|PROT_WRITE,MAP_SHARED,fb,0); memset (fb_mem, 0, );
&&& FrameBuffer 设备还提供了若干 ioctl 命令,通过这些命令,可以获得显示设备的一些固定信息(比如显示内存大小)、与显示模式相关的可变信息(比如分辨率、象素结构、每扫描线的字节宽度),以及伪彩-色模式下的调色板信息等等。 &&& 通过 FrameBuffer 设备,还可以获得当前内核所支持的加速显示卡的类型(通过固定信息得到),这种类型通常是和特定显示芯片相关的。比如目前最新的内核(2.4.9)中,就包含有-对 S3、Matrox、nVidia、3Dfx 等等流行显示芯片的加速支持。在获得了加速芯片类型之后,应用程序就可以将 PCI 设备的内存I/O(memio)映射到进程的地址空间。这些 memio 一般是用来控制显示卡的寄存器,通过对这些寄存器的操作,应用程序就可以控制特定显卡的加速功能。 &&& PCI 设备可以将自己的控制寄存器映射到物理内存空间,而后,对这些控制寄存器的访问,给变成了对物理内存的访问。因此,这些寄存器又被称为"memio"。一旦被映-射到物理内存,Linux 的普通进程就可以通过 mmap 将这些内存 I/O 映射到进程地址空间,这样就可以直接访问这些寄存器了。 &&& 当然,因为不同的显示芯片具有不同的加速能力,对memio 的使用和定义也各自不同,这时,就需要针对加速芯片的不同类型来编写实现不同的加速功能。比如大多数芯片都提供了对矩形填充的硬件加速支持,但不同的芯片实现方-式不同,这时,就需要针对不同的芯片类型编写不同的用来完成填充矩形的函数。 &&& FrameBuffer 只是一个提供显示内存和显示芯片寄存器从物理内存映射到进程地址空间中的设备。所以,对于应用程序而言,如果希望在 FrameBuffer 之上进行图形编程,还需要自己动手完成其他许多工作。
*二、FrameBuffer在Linux中的实现和机制 *Framebuffer对应的源文件在linux/drivers/video/目录下。总的抽象设备文件为fbcon.c, 在这个目录下还有与各种显卡驱动相关的源文件。
(一)、分析Framebuffer设备驱动 &&& 需要特别提出的是在INTEL平台上,老式的VESA 1.2卡,如CGA/EGA卡,是不能支持Framebuffer的,因为Framebuffer要求显卡支持线性帧缓冲,即CPU可以访问显缓冲中的每一位,-但是VESA 1.2 卡只能允许CPU一次访问64K的地址空间。 FrameBuffer设备驱动基于如下两个文件: 1) linux/include/linux/fb.h 2) linux/drivers/video/fbmem.c
下面分析这两个文件。 1、fb.h && 几乎主要的结构都是在这个中文件定义的。这些结构包括: 1)fb_var_screeninfo && 这个结构描述了显示卡的特性:
struct fb_var_screeninfo { __u32 /* visible resolution */ __u32 __u32 xres_ /* virtual resolution */ __u32 yres_ __u32 /* offset from virtual to visible resolution */ __u32
__u32 bits_per_ /* guess what */ __u32 /* != 0 Gray levels instead of colors */
struct fb_ /* bitfield in fb mem if true color, */ struct fb_ /* else only length is significant */ struct fb_ struct fb_ /* transparency */
__u32 /* != 0 Non standard pixel format */
__u32 /* see FB_ACTIVATE_* */
__u32 /* height of picture in mm */ __u32 /* width of picture in mm */
__u32 accel_ /* acceleration flags (hints) */
/* Timing: All values in pixclocks, except pixclock (of course) */ __u32 /* pixel clock in ps (pico seconds) */ __u32 left_ /* time from sync to picture */ __u32 right_ /* time from picture to sync */ __u32 upper_ /* time from sync to picture */ __u32 lower_ __u32 hsync_ /* length of horizontal sync */ __u32 vsync_ /* length of vertical sync */ __u32 /* see FB_SYNC_* */ __u32 /* see FB_VMODE_* */ __u32 reserved[6]; /* Reserved for future compatibility */
2) fb_fix_screeninfon 这个结构在显卡被设定模式后创建,它描述显示卡的属性,并且系统运行时不能被修改;比如FrameBuffer内存的起始地址。它依赖于被设定的模式,当一个模-式被设定后,内存信息由显示卡硬件给出,内存的位置等信息就不可以修改。
struct fb_fix_screeninfo { char id[16]; /* identification string eg "TT Builtin" */ unsigned long smem_ /* Start of frame buffer mem */ /* (physical address) */ __u32 smem_ /* Length of frame buffer mem */ __u32 /* see FB_TYPE_* */ __u32 type_ /* Interleave for interleaved Planes */ __u32 /* see FB_VISUAL_* */ __u16 /* zero if no hardware panning */ __u16 /* zero if no hardware panning */ __u16 /* zero if no hardware ywrap */ __u32 line_ /* length of a line in bytes */ unsigned long mmio_ /* Start of Memory Mapped I/O */ /* (physical address) */ __u32 mmio_ /* Length of Memory Mapped I/O */ __u32 /* Type of acceleration available */ __u16 reserved[3]; /* Reserved for future compatibility */
3) fb_cmap 描述设备无关的颜色映射信息。可以通过FBIOGETCMAP 和 FBIOPUTCMAP 对应的ioctl操作设定或获取颜色映射信息.
struct fb_cmap { __u32 /* First entry */ __u32 /* Number of entries */ __u16 * /* Red values */ __u16 * __u16 * __u16 * /* transparency, can be NULL */
4) fb_info 定义当显卡的当前状态;fb_info结构仅在内核中可见,在这个结构中有一个fb_ops指针, 指向驱动设备工作所需的函数集。
struct fb_info { char modename[40]; /* default video mode */ kdev_
/* Has this been open already ? */ #define FBINFO_FLAG_MODULE 1 /* Low-level driver is a module */ struct fb_var_ /* Current var */ struct fb_fix_ /* Current fix */ struct fb_ /* Current Monitor specs */ struct fb_ /* Current cmap */ struct fb_ops * char *screen_ /* Virtual address */ struct display * /* initial display variable */ struct vc_data *display_ /* Console visible on this display */ char fontname[40]; /* default font name */ devfs_handle_t devfs_ /* Devfs handle for new name */ devfs_handle_t devfs_ /* Devfs handle for compat. symlink */ int (*changevar)(int); /* tell console var has changed */ int (*switch_con)(int, struct fb_info*); /* tell fb to switch consoles */ int (*updatevar)(int, struct fb_info*); /* tell fb to update the vars */ void (*blank)(int, struct fb_info*); /* tell fb to (un)blank the screen */ /* arg = 0: unblank */ /* arg & 0: VESA level (arg-1) */ void *pseudo_ /* Fake palette of 16 colors and the cursor's color for non palette mode */ /* From here on everything is device dependent */ void *
5) struct fb_ops 用户应用可以使用ioctl()系统调用来操作设备,这个结构就是用一支持ioctl()的这些操作的。
struct fb_ops { /* open/release and usage marking */ struct module * int (*fb_open)(struct fb_info *info, int user); int (*fb_release)(struct fb_info *info, int user); /* get non settable parameters */ int (*fb_get_fix)(struct fb_fix_screeninfo *fix, int con, struct fb_info *info); /* get settable parameters */ int (*fb_get_var)(struct fb_var_screeninfo *var, int con, struct fb_info *info); /* set settable parameters */ int (*fb_set_var)(struct fb_var_screeninfo *var, int con, struct fb_info *info); /* get colormap */ int (*fb_get_cmap)(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info); /* set colormap */ int (*fb_set_cmap)(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info); /* pan display (optional) */ int (*fb_pan_display)(struct fb_var_screeninfo *var, int con, struct fb_info *info); /* perform fb specific ioctl (optional) */ int (*fb_ioctl)(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, int con, struct fb_info *info); /* perform fb specific mmap */ int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma); /* switch to/from raster image mode */ int (*fb_rasterimg)(struct fb_info *info, int start);
6) structure map struct fb_info_gen | struct fb_info | fb_var_screeninfo | | fb_fix_screeninfo | | fb_cmap | | modename[40] | | fb_ops ---|---&ops on var | | ... | fb_open | | | fb_release | | | fb_ioctl | | | fb_mmap | struct fbgen_hwswitch -|-& detect | | encode_fix | | encode_var | | decode_fix | | decode_var | | get_var | | set_var | | getcolreg | | setcolreg | | pan_display | | blank | | set_disp
[编排有点困难,第一行的第一条竖线和下面的第一列竖线对齐,第一行的第二条竖线和下面的第二列竖线对齐就可以了] 这个结构 fbgen_hwswitch抽象了硬件的操作.虽然它不是必需的,但有时候很有用.
2、 fbmem.c fbmem.c 处于Framebuffer设备驱动技术的中心位置.它为上层应用程序提供系统调用也为下一层的特定硬件驱动提供接口;那些底层硬件驱动需要用到这儿的接口来向-系统内核注册它们自己. fbmem.c 为所有支持FrameBuffer的设备驱动提供了通用的接口,避免重复工作.
1) 全局变量
struct fb_info *registered_fb[FB_MAX]; int num_registered_
这两变量记录了所有fb_info 结构的实例,fb_info 结构描述显卡的当前状态,所有设备对应的fb_info 结构都保存在这个数组中,当一个FrameBuffer设备驱动向系统注册自己时,其对应的fb_info 结构就会添加到这个结构中,同时num_registered_fb 为自动加1.
static struct { const char * int (*init)(void); int (*setup)(void);
} fb_drivers[] __initdata= { ....};
如果FrameBuffer设备被静态链接到内核,其对应的入口就会添加到这个表中;如果是动态加载的,即使用insmod/rmmod,就不需要关心这个表。
static struct file_operations fb_ops ={ owner: THIS_MODULE, read: fb_read, write: fb_write, ioctl: fb_ioctl, mmap: fb_mmap, open: fb_open, release: fb_release
这是一个提供给应用程序的接口.
2)fbmem.c 实现了如下函数.
register_framebuffer(struct fb_info *fb_info); unregister_framebuffer(struct fb_info *fb_info);
这两个是提供给下层FrameBuffer设备驱动的接口,设备驱动通过这两函数向系统注册或注销自己。几乎底层设备驱动所要做的所有事情就是填充fb_inf-o结构然后向系统注册或注销它。
(二)一个LCD显示芯片的驱动实例 &&& 以Skeleton LCD 控制器驱动为例,在LINUX中存有一个/fb/skeleton.c的skeleton的Framebuffer驱动程序,很简单,仅仅是填充了 fb_info结构,并且注册/注销自己。设备驱动是向用户程序提供系统调用接口,所以我们需要实现底层硬件操作并且定义file_operations 结构来向系统提供系统调用接口,从而实现更有效的LCD控制器驱动程序。
1)在系统内存中分配显存 在fbmem.c文件中可以看到, file_operations 结构中的open()和release()操作不需底层支持,但read()、write()和 mmap()操作需要函数fb_get_fix()的 支持.因此需要重新实现函数fb_get_fix()。另外还需要在系统内存中分配显存空间,大多数的LCD控制器都没有自己的显存空间,被分配的地址空间的起-始地址与长度将会被填充到fb_fix_screeninfo 结构的smem_start 和smem_len 的两个变量中.被分配的空间必须是物理连续的。
2)实现 fb_ops 中的函数 用户应用程序通过ioctl()系统调用操作硬件,fb_ops 中的函数就用于支持这些操作。(注: fb_ops结构与file_operations 结构不同,fb_ops是底层操作的抽象,而file_operations是提供给上层系统调用的接口,可以直接调用. ioctl()系统调用在文件fbmem.c中实现,通过观察可以发现ioctl()命令与fb_ops's 中函数的关系: FBIOGET_VSCREENINFO fb_get_var FBIOPUT_VSCREENINFO fb_set_var FBIOGET_FSCREENINFO fb_get_fix FBIOPUTCMAP fb_set_cmap FBIOGETCMAP fb_get_cmap FBIOPAN_DISPLAY fb_pan_display
如果我们定义了fb_XXX_XXX 方法,用户程序就可以使用FBIOXXXX宏的ioctl()操作来操作硬件。
文件linux/drivers/video/fbgen.c或者linux/drivers/video目录下的其它设备驱动是比较好的参考资料。在所有的这-些函数中fb_set_var()是最重要的,它用于设定显示卡的模式和其它属性,下面是函数fb_set_var()的执行步骤:
1)检测是否必须设定模式 2)设定模式
3)设定颜色映射
4) 根据以前的设定重新设置LCD控制器的各寄存器。 第四步表明了底层操作到底放置在何处。在系统内存中分配显存后,显存的起始地址及长度将被设定到LCD控制器的各寄存器中(一般通过fb_set_var() 函数),显存中的内容将自动被LCD控制器输出到屏幕上。另一方面,用户程序通过函数mmap()将显存映射到用户进程地址空间中,然后用户进程向映射空间发送-的所有数据都将会被显示到LCD显示器上。
*三、FrameBuffer的应用*
(一)、一个使用FrameBuffer的例子
&& 1. FrameBuffer主要是根据VESA标准的实现的,所以只能实现最简单的功能。 && 2. 由于涉及内核的问题,FrameBuffer是不允许在系统起来后修改显示模式等一系列操作。(好象很多人都想要这样干,这是不被允许的,当然如果你自己写驱动-的话,是可以实现的).
&& 3. 对FrameBuffer的操作,会直接影响到本机的所有控制台的输出,包括XWIN的图形界面。
好,现在可以让我们开始实现直接写屏:
1、打开一个FrameBuffer设备
2、通过mmap调用把显卡的物理内存空间映射到用户空间
3、直接写内存。
/******************************** File name : fbtools.h */
#ifndef _FBTOOLS_H_ #define _FBTOOLS_H_ #include &linux/fb.h& //a framebuf typedef struct fbdev{ &&&&&& &&&&&& unsigned long fb_mem_ &&&&&& unsigned long fb_ &&&&&& struct fb_fix_screeninfo fb_ &&&&&& struct fb_var_screeninfo fb_ &&&&&& char dev[20];
} FBDEV, *PFBDEV;
//open & init a frame buffer //to use this function, //you must set FBDEV.dev="/dev/fb0" //or "/dev/fbX" //it's your frame buffer. int fb_open(PFBDEV pFbdev);
//close a frame buffer int fb_close(PFBDEV pFbdev);
//get display depth int get_display_depth(PFBDEV pFbdev);
//full screen clear void fb_memset(void *addr, int c, size_t len);
/****************** File name : fbtools.c */
#include &stdio.h& #include &stdlib.h& #include &fcntl.h& #include &unistd.h& #include &string.h& #include &sys/ioctl.h& #include &sys/mman.h& #include &asm/page.h& #include "fbtools.h" #define TRUE&&&&&&& 1 #define FALSE&&&&&& 0 #define MAX(x,y)&&&&&&& ((x)&(y)?(x)y)) #define MIN(x,y)&&&&&&& ((x)&(y)?(x)y))
//open & init a frame buffer int fb_open(PFBDEV pFbdev) { &&&&&& pFbdev-&fb = open(pFbdev-&dev, O_RDWR); &&&&&& if(pFbdev-&fb & 0) &&&&&& { &&&&&&&&&&&&& printf("Error opening %s: %m. Check kernel config\n", pFbdev-&dev); &&&&&&&&&&&&& return FALSE; &&&&&& }
&&&&&& if (-1 == ioctl(pFbdev-&fb,FBIOGET_VSCREENINFO,&(pFbdev-&fb_var))) &&&&&& { &&&&&&&&&&&&& printf("ioctl FBIOGET_VSCREENINFO\n"); &&&&&&&&&&&&& return FALSE; &&&&&& }
&&&&&& if (-1 == ioctl(pFbdev-&fb,FBIOGET_FSCREENINFO,&(pFbdev-&fb_fix))) &&&&&& { &&&&&&&&&&&&& printf("ioctl FBIOGET_FSCREENINFO\n"); &&&&&&&&&&&&& return FALSE; &&&&&& }
&&&&&& //map physics address to virtual address &&&&&& pFbdev-&fb_mem_offset = (unsigned long)(pFbdev-&fb_fix.smem_start) & (~PAGE_MASK); &&&&&& 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);
&&&&&& if (-1L == (long) pFbdev-&fb_mem) &&&&&& { &&&&&&&&&&&&& printf("mmap error! mem:%d offset:%d\n", pFbdev-&fb_mem, pFbdev-&fb_mem_offset); &&&&&&&&&&&&& return FALSE; &&&&&& } &&&&&& return TRUE;
//close frame buffer int fb_close(PFBDEV pFbdev) { &&&&&& close(pFbdev-&fb); &&&&&& pFbdev-&fb=-1;
//get display depth int get_display_depth(PFBDEV pFbdev); { &&&&&& if(pFbdev-&fb&=0) &&&&&& { &&&&&&&&&&&&& printf("fb device not open, open it first\n"); &&&&&&&&&&&&& return FALSE; &&&&&& } &&&&&& return pFbdev-&fb_var.bits_per_
//full screen clear void fb_memset (void *addr, int c, size_t len) { &&& memset(addr, c, len);
//use by test #define DEBUG #ifdef DEBUG main() { &&&&&& FBDEV &&&&&& memset(&fbdev, 0, sizeof(FBDEV)); &&&&&& strcpy(fbdev.dev, "/dev/fb0"); &&&&&& if(fb_open(&fbdev)==FALSE) &&&&&& { &&&&&&&&&&&&& printf("open frame buffer error\n"); &&&&&&&&&&&&& &&&&&& } &&&&&& fb_memset(fbdev.fb_mem + fbdev.fb_mem_offset, 0, fbdev.fb_fix.smem_len); &&&&&&&&&&&&& fb_close(&fbdev);
(二)基于Linux核心的汉字显示的尝试 我们以一个简单的例子来说明字符显示的过程。我们假设是在虚拟终端1(/dev/tty1)下运行一个如下的简单程序。
main ( ) { puts("hello, world.\n");
puts 函数向缺省输出文件(/dev/tty1)发出写的系统调用write(2)。系统调用到linux核心里面对应的核心函数是console.c中的con_w-rite(),con_write()最终会调用do_con_write( )。在do_con_write( )中负责把"hello, world.\n"这个字符串放到tty1对应的缓冲区中去。 do_con_write( )还负责处理控制字符和光标的位置。让我们来看一下do_con_write()这个函数的声明。 static int do_con_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) &&& 其中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,这个数组就是各虚拟终端的私有-数据。
static int do_con_write(struct tty_struct * tty, int from_user,const unsigned char *buf, int count) { struct vt_struct *vt = (struct vt_struct *)tty-&driver_//我们用到了driver_data变量 . . . . . currcons = vt-&vc_ file://我们在这里的vc_nums就是1 . . . . .
要访问虚拟终端的私有数据,需使用vc_cons〔currcons〕.d指针。这个指针指向的结构含有当前虚拟终端上光标的位置、缓冲区的起始地址、缓冲区大-小等等。 &&& "hello, world.\n"中的每一个字符都要经过conv_uni_to_pc( )这个函数转换成8位的显示字符。这要做的主要目的是使不同语言的国家能把16位的UniCode码映射到8位的显示字符集上,目前还是主要针对欧洲国家的语言-,映射结果为8位,不包含对双字节(double byte)的范围。
这种UNICODE到显示字符的映射关系可以由用户自行定义。在缺省的映射表上,会把中文的字符映射到其他的字符上,这是我们不希望看到也是不需要的。所以我们-有两个选择∶
&& 1. 不进行conv_uni_to_pc( )的转换。 && 2. 加载符合双字节处理的映射关系,即对非控制字符进行1对1的不变映射。 && 我们自己定制的符合这种映射关系的UNICODE码表是direct.uni。要想查看/装载当前系统的unicode映射表,可使外部命令loadunima-p。
经过conv_uni_to_pc( )转换之后,"hello, world.\n"中的字符被一个一个地填写到tty1的缓冲区中。然后do_con_write( )调用下层的驱动,把缓冲区中的内容输出到显示器上(也就相当于把缓冲区的内容拷贝到VGA显存中去)。
sw-&con_putcs(vc_cons〔currcons〕.d, (u16 *)draw_from, (u16*)draw_to-(u16 *)draw_from, y, draw_x);
之所以要调用底层驱动,是因为存在不同的显示设备,其对应VGA显存的存取方式也不一样。 上面的Sw-&con_putcs( )就会调用到fbcon.c中的fbcon_putcs()函数(con_putcs是一个函数的指针,在Framebuffer模式下指向 fbcon_putcs()函数)。也就是说在do_con_write( )函数中是直接调用了fbcon_putcs()函数来进行字符的绘制。比如说在256色模式下,真正负责输出的函数是void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p,const unsigned short *s, int count, int yy, int xx)
显示中文 &&& 比如说我们试图输出一句中文∶putcs(你好\n );(你好的内码为0xc4,0xe3,0xba,0xc3)。这时候会怎么样呢,有一点可以肯定,"你好"肯定不会出现在屏幕上,国为核心中没有汉字字库,中-文显示就是无米之炊了. &&& 1 在负责字符显示的void fbcon_cfb8_putcs( )函数中,原有操作如下∶对于每个要显示的字符,依次从虚拟终端缓冲区中以WORD为单位读取(低位字节是ASCII码,高8位是字符的属性),由于汉字是双字-节编码方式,所以这种操作是不可能显示出汉字的,只能显示出xxxx_putcs()是一个一个VGA字符.
要解决的问题∶ 确保在do_con_write( )时uni□pc转换不会改变原有编码。一个很直接的实现方式就是加载一个我们自己定制的UNICODE映射表, loadunimapdirect.uni,或者直接把direct.uni置为核心的缺省映射表。
针对如上问题,我们要做的第一个尝试方案是如下。 首先需要在核心中加载汉字字库,然后修改fbcon_cfb8_putcs()函数,在fbcon_cfb8_putcs( )中一次读两个WORD,检查这两个WORD的低位字节是否能拼成一个汉字,如果发现能拼成一个汉字,就算出这个汉字在汉字字库中的偏移,然后把它当成一个16 x 16的VGA字符来显示。
试验的结果表明∶
&& 1. 能够输出汉字,但仍有许多不理想的地方,比如说,输出以半个汉字开始的一串汉字,则这半个汉字后面的汉字都会是乱码。这是半个汉字的问题。 && 2. 光标移动会破坏汉字的显示。表现为,光标移动过的汉字会变成乱码。这是因为光标的更新是通过xxxx_putc( )函数来完成的。
xxxx_putc( )函数与xxxx_putcs( )函数实现的功能类似,但是xxxx_putc()函数只刷新一个字符而不是一个字符串,因而xxxx_putc()的输入参数是一个整数,而不是一个字符串的-地址。Xxxx_putc( )函数的声明如下∶void fbcon_cfb8_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
&&& 下一个尝试方案就是同时修改xxxx_putcs( )函数和xxxx_putc()函数。为了解决半个汉字的问题,每一次输出之前,都从屏幕当前行的起始位置开始扫描,以确定要输出的字符是否落在半个汉字的位置-上。如果是半个汉字的位置,则进行相应的调整,即从向前移动一个字节的位置开始输出。 &&& 这个方案有一个困难,即xxxx_putc( )函数不用缓冲区的地址,而是用一个整数作为参数。所以xxxx_putc( )无法直接利用相邻的字符来判别该定符是否是汉字。 &&& 解决方案是,利用xxxx_putc( )的光标位置参数(yy, xx),可以逆推出该字符在缓冲区中的位置。但仍有一些小麻烦,在Linux的虚拟终端下,用户可能会上卷该屏幕(shift + pageup),导致光标的y座标和相应字符在缓冲区的行数不一致。相应的解决方案是,在逆推的过程中,考虑卷屏的参量。
这样一来,我们就又进了一步,得到了一个相对更好的版本。但仍有问题没有解决。敲入turbonetcfg,会发现菜单的边框字符也被当成汉字显示。这是因为,-这种边框字符是扩展字符,也使用了字符的第8位,因而被当作汉字来显示。例如,单线一的制表符内码为0xC4,当连成一条长线就是由一连串0xC4组成,而0x-C4C4正是汉字哪。于是水平的制表符被一连串的哪字替代了。要解决这个问题就非常不容易了,因为制表符的种类比较多,而且垂直制表符与其后面字符的组合型式又-多种多样,因而很难判断出相应位置的字符是不是制表符,从理论上说,无论采取什么样的排除算法,都必然存在误判的情况,因为总存在二义性,没有充足的条件来推断-出当前字符究竟是制表符还是汉字。
我们一方面寻找更好的排除组合算法,一方面试图寻找其它的解决方案。要想从根本上解决定个问题,必须利用其它的辅助信息,仅仅从缓冲区的字符来判断是不够的。 &&& 经过一番努力,我们发现,在UNIX中使用扩展字符时,都要先输出字符转义序列(Escape sequence)来切换当前字符集。字符转义序列是以控制字符Esc为首的控制命令,在UNIX的虚拟终端中完成终端控制命令,这种命令包括,移动光标座标、-卷屏、删除、切换字符集等等。也就是说在输出代表制表符的字符串之前,通常是要先输出特定的字符转义序列。 在console.c里,有根据字符转义序列命令来记录字符状态的变量。结合该变量提供的信息,就可以非常干净地把制表符与汉字区别开来。
&&& 在如上思路的指引下,我们又产生了新的解决方案。经过改动得到了另一各版本.
在这个新版本上,turbonetcfg在初次绘制的时候,制表符与汉字被清晰地区分开来,结果是非常正确的。但还有新的问题存在∶turbonetcfg 在重绘的时候(如切换虚拟终端或是移动鼠标光标的时候),制表符还是变成了汉字,因为重绘完全依赖于缓冲区,而这时用来记录字符集状态的变量并不反映当前字符集-状态。问题还是没有最终解决。我们又回到了起点。∶( 看来问题的最终解决手段必须是把字符集的状态伴随每一个字符存在缓冲区中。让我们来研究一下缓冲区的结构。每一个字符占用16bit的缓冲区,低8位是ASCI-I值,完全被利用,高8位包含前景颜色和背景颜色的属性,也没有多余的空间可以利用。因而只能另外开辟新的缓冲区。为了保持一致性,我们决定在原来的缓冲区后面-添加相同大小的缓冲区,用来存放是否是汉字的信息。
也许有读者会问,我们只需要为每个字符添加一bit的信息来标志是否是汉字就足够了,为什么还要开辟与原缓冲区大小相同的双倍缓冲区,是不是太浪费呢?我们先放-下这个问题,稍后再作回答。
其实,如果再添加一bit来标志是当前字符是汉字的左半边还是右半边的话,就会省去扫描屏幕上当前整行字符串的工作,这样一来,编程会更简单。但是有读者会问,-即使是这样,使用8bit总够用了吧?为什么还要使用16bit呢? &&& 我们的作法是∶用低8位来存放汉字另外一半的内码,用高8位中的2 bit来存放上面所讲的辅助信息,高8位的剩余6位可以用来存放汉字或其它编码方式(如BIG5或日文、韩文)的信息,从而使我们可以实现同屏显示多种双字节语-言的字符而不会有相互干扰。另外,在编程时,双倍缓冲也比较容易计算。这样我们就回答了如上的两个问题。 &&& 迄今为止,我们有了一套彻底解决汉字和制表符相互干扰、半个汉字的刷新、重绘等问题的方案。剩下的就是具体编程实现的问题了。 &&& 但是,由于Framebuffer的驱动很多,修改每一个驱动的xxxx_putc()函数和xxxx_putcs( )函数会是一项不小的工作,而且,改动驱动程序后,每种驱动的测试也是很麻烦的,尤其是对于有硬件加速的显卡,修改和测试会更不容易。那么,存不存在一种不需要-修改显卡驱动程序的方法呢? &&& 经过努力,我们发现,可以在调用xxxx_putcs( )或xxxx_putc()函数输出汉字之前,修改vga字库的指针使其指向所需显示的汉字在汉字字库中的位置,即把一个汉字当成两个vga ASCII字符输出。也就是说,在内核中存在两个字库,一个是原有的vga字符字库,另一个是汉字字库,当我们需要输出汉字的时候,就把vga字库的指针指向汉-字字库的相应位置,汉字输出完之后,再把该指针指向vga字库的原有位置。 && 这样一来,我们只需要修改fbcon.c和console.c,其中console.c负责维护双倍缓冲区,把每一个字符的信息存入附加的缓冲区; 而fbcon.c负责利用双倍缓冲区中附加的信息,调整vga字库的指针,调用底层的显示驱动程序。这里还有几个需要注意的地方∶
&& 1. 由于屏幕重绘等原因,调用底层驱动xxxx_putc( && )和xxxx_putcs()的地方有多处。我们作了两个函数分别包装这两个调用,完成替换字库、调用xxxx_putcs( )或xxxx_putc( && )、恢复字库等功能。 && 2. 为了实现向上滚屏(shift + pageup)时也能看到汉字,我们需要作另外的修改。 &&&&&& Linux 在设计虚拟终端的时候,提供了回顾被卷出屏幕以外的信息的功能,这就是用热键来向上滚屏(shift + && pageup)。当前被使用的虚拟终端拥有一个公共的缓冲区(soft && back),用来存放被滚出屏幕以外的信息。当切换虚拟终端的时候,公共缓冲区的内容会被清除而被新的虚拟终端使用。向上滚屏的时候,显示的是公共缓冲区中的内-容。因此,如果我们想在向上滚屏的时候看到汉字,公共缓冲区也必须加倍,以确保没有信息丢失。当滚出屏幕的信息向公共缓冲区填写的时候,必须把相应的附加信息也-填写进公共缓冲区的附加区域。 && 这就要求fbcon.c必须懂得利用公共缓冲区的附加信息。 &&&&&& 当然,有另外一种偷懒的方法,那就是不允许用户向上滚屏,从而避免对公区缓冲区的处理。 && 3. 把不同的编码方式(GB、BIG5、日文和韩文)写成不同的module,以实现动态加载,从而使得扩展新的编码方式不需要重新编译核心。
本文实现的Kernel Patch文件(patch.kernel.chinese)可以从下载。Cd /usr/src/(该目录下应有Linux核心源程序所在的目录linux/) patch -p0 -b & patch.kernel.chinesemake menuconfig 请选择Console drivers选项中的
〔*〕 Double Byte Character Display Support(EXPERIMENTAL) 〔*〕 Double Byte GB encode (module only) 〔*〕 VESA VGA graphics console &*& Virtual Frame Buffer support (ONLY FOR TESTING!) &*& 8 bpp packed pixels support &*& 16 bpp packed pixels support &*& VGA characters/attributes support 〔*〕 Select compiled-in fonts 〔*〕VGA 8x8 font 〔*〕VGA 8x16 font
make dep make bzImage make modules make install make modules_install
然后用新的核心启动。
Insmod encode-gb.o
*四、其它*
(一)&& 设置FrameBuffer &&& FrameBuffer,可以译作"帧缓冲",有时简称为 fbdrv,基于fbdrv的console也被称之为fbcon。这是一种独立于硬件的抽象图形设备。FrameBuffer的优点在于其高度的可移植 性、易使用性、稳定性。使用Linux内核的 FrameBuffer驱动(vesafb),可以轻松支持到bpp以上的分辩率。而且目前可得到的绝大多数linux版本所发行 的内核中,已经预编译了FrameBuffer支持,通常不需要重新编译内核就可以使用。所以FrameBuffer也是zhcon推荐使用的驱动方式。
进入FrameBuffer可以简单地在系统启动时向kernel传送vga=mode-number的参数来激活FrameBuffer设备,如: lilo:linux vga=305 将会启动bpp模式。
&&&&&&&&&& 640x480&&& 800x600&&& &&&
8 bpp&&&&& 769&&&&&&&&& 771&&&&&& 773&&&&&&& 775 16 bpp&&&& 785&&&&&&&&& 788&&&&&& 791&&&&&&& 794 32 bpp&&&& 786&&&&&&&&& 789&&&&&& 792&&&&&&& 795
(二)&& 要使linux缺省进入FrameBuffer,可以修改/etc/lilo.conf,加入一下语句: vga=0x303 退出编辑,执行: lilo -v 重新启动linux,可以使其进入800x600的256色模式。 grub也是一样,在grub.conf中的kernel行后面写上vga=xxx就行了,也可以用vga=ask,让系统启动的时候询问你用多大的分辨率
(三)我编译内核时,选择framebuffer模式,启动时屏幕上有一企鹅图片,不知这是如何造成的这个图片可以去掉或改动吗? 可以将drivers/video/fbcon.c: fbcon_setup()中if (logo) { } 代码去掉。
1、启动并进入Linux系统。 2、然后选择虚拟机菜单中的“虚拟机/安装VMware-Tools”,此时就会有把VMware-tools文件映像到CD-ROM中。 3、把“VMwareTools-6.0.2-5.rpm,VMwareTools-6.0.2-59824.tar.gz”文件复制到自己的需要的位置中,然后选择一种安装方式。在此我选VMwareTools-6.0.2-59824.tar.gz。 4、解压 # tar -zxvf VmwareTools-6.0.2-59824.tar.gz 5. #rpm -ivh ./vmwaretools-5.5.2.-2.rpm
6.进入vmware-tools-distrib.
7../vmwre-install.pl //开始安装中间会出现一些确认项,一直回车
首先说下我使用的环境主机:XP SP2 虚拟机:VMware Workstation 6.0虚拟机上的系统:Red Hat9.0开发板:英蓓特公司的EDUKIT-III ARM9第一步:下载安装VMware Workstation 6.0 1.下载地址:http://12.duote.net/ha_vmware.exe 注册号:JHXUR-G0M88-GA44V-4MRN6 2.安装VMware Workstation 6.0 可以安装在任何路径,安装过程中只需要下一步就可以了 安装完成之后会在桌面出现“VMware Workstation”的可 执行文件的快捷图标。 3.创建虚拟机环境: 运行VMware Workstation,双击图中的“New Virtual Machine”,依次单击下一步,直到出现要求选择操作系统的 界面,选择“linux" Version 选择“Other Linux 2.6x kernel,到提示你虚拟机要以什么方式和主机进行连接时你选 择以NAT方式,然后依次点击下一步,直到要求选择磁盘容量,把Disk size 修改为10GB,注意这里的“Allocate all disk space now”不要选中(选中的话,表示所分配的空间都被此虚拟机占用,WINDOWS 无法使用这10GB 的空 间。不选中就表示虚拟机是动态调整的,例如:虚拟机只用到5GB,另外的5GB 还是可以被WINDOW 使用的)。选 择“完成”后就完成虚拟机环境的创建。 第二步:下载Red Hat9.0镜像文件 下载地址: 红帽子公司官方下载点: Disk 1:http://ftp.redhat.com/pub/redhat/linux/9/en/iso/i386/shrike-i386-disc1.iso Disk 2:http://ftp.redhat.com/pub/redhat/linux/9/en/iso/i386/shrike-i386-disc2.iso Disk 3:http://ftp.redhat.com/pub/redhat/linux/9/en/iso/i386/shrike-i386-disc3.iso 第三步:安装Red Hat9.0 虚拟机新建好后在工具栏那选择虚拟机--设置--选择CD-ROM--选择使用ISO镜像--在 下方的下拉栏里找到shrike-i386-disc1.iso 并确定保存 然后打开虚拟机这时你就可以进入到Red Hat9.0的安装界面了 安装Red Hat9.0很简单的了,相信大家都会的了,这里我就不再说了 第四步:建立主机和虚拟机之间的通信 1.安装VMware Tools 安装VMware Tools可以实现鼠标在虚拟机环境和WINDOWS 环境的方便切换(如果没有安装此工具,鼠标从虚拟机 的Linux 环境中切换到WINDOWS 下,需要同时按Ctrl+Alt键,安装后鼠标可以直接移出);还可以使Linux 访问和 操作WINDOWS 的目录。在工具栏那选择虚拟机--安装VMware Tools…,选择之后,桌面中的光盘图标变为 VMware Tools,双击此光盘图标, 会看到两个文件: VMwareTools-5.0.0-1.rpm 和 VMwareTools-5.0.0-13124.tar.gz。这里的安装有两种方法: (1)直接双击VMwareTools-5.0.0-1.rpm 开始运行,完成之后打开终端, 执行vmware-config-tools.pl,开始安装,中间会出现一些确认选项,一直回车,直到出现设置屏幕大小的,选择一 个然后回车(如选择3,),继续直到完成安装。 (2)打开终端, cd 到/media/cdrom/ ( 此处是光盘所在的位置, 在此位置下应该有 VMwareTools-5.0.0-1.rpm 和VMwareTools-5.0.0-13124.tar.gz 两个文件文件), 执行如下命令: cp VMwareTools-5.0.0-13124.tar.gz /tmp //拷贝文件到tmp 目录下 cd /tmp //CD 到tmp 目录下 tar xzf VMwareTools-5.0.0-13124.tar.gz //解压文件 cd /vmware-tools-distrib //CD到vmware-tools-distrib 目录下 ./vmwre-install.pl //开始安装中间会出现一些确认项,一直回车 2.设置共享文件 共享文件的设置有两种方法: (1)在工具栏选择虚拟机--设置,选择Options\Share Folders,文件夹共享选择“总是启用” 添加一个共享文件,如在Linux共享名share,WINDOWS 端的Host Folder 为:D:\os_share,打开终端, 在/mnt/hgfs/share 目录下就可以访问到D:\os_share 目录下的文件了。 (2)mount 方式 把WINDOWS 系统下的某个文件共享,然后通过mount 命令把此文件共享到Linux 目录下。如:mount –t smbfs //172.16.53.214/test /mnt/share –o username=your_user_name,workgroup=your_nt_domain这样就 把共享的test 目录文件共享到Linux 目录下的/mnt/share 中了,在Linux 中可以操作此目录中的文件了。其中 172.16.53.214 是本机的IP 地址。 第五步:为虚拟机添加串口 如果你现在已经启动了Red Hat9.0的话请先关闭系统 关闭后在工具栏那选择虚拟机--设置--点击ADD--选择seria port--保存退出 第六步:配置minicom 进入到minicom配置界面后选择 :Serial port setup 然后按照下面的设置下就OK了 A - Serial Device : :/dev/ttyS0 B - Lockfile Location : /var/lock C - Callin Program : D - Callout Program : E - Bps/Par/Bits : N1 F - Hardware Flow Control : No G - Software Flow Control : No 设置好要记得保存哦 选择这项是保存:Save setup as dfl 第七步:安装arm-linux-gcc编译器 我买开发板的时候光盘上已经给有编译器了 所以我的不需要去下载 没有的就自己去下载吧 我使用编译器版本分别是arm-linux-gcc-2.95.3 arm-linux-gcc-3.3 .2 arm-linux-gcc-3.4.1 把这三个编译器的压缩包放到你的home目录下去 我的是放在/home/xhylyx/qq2440目录下 然后我们cd进入到根目录下分别执行 root@xhylyx-desktop:/# tar xvzf /home/xhylyx/qq2440/arm-linux-gcc-2.95.3.tgz root@xhylyx-desktop:/# tar xvzf /home/xhylyx/qq2440/arm-linux-gcc-3.3.2.tgz root@xhylyx-desktop:/# tar xvzf /home/xhylyx/qq2440/arm-linux-gcc-3.4.1.tgz 解压完后会在/usr/local目录下生成一个arm文件夹 如果没有则是你解压的路径不正确 把交叉编译器的路径加入到PATH,以方便使用: root@xhylyx-desktop:/#gedit /root/.bashrc 编辑/root/.bashrc 文件,在最后一行 export PATH=$PATH:/usr/loca/arm/3.4.1/bin 保存退出 我们重启下Red Hat9.0使以上设置生效 重启后 xhylyx@xhylyx-desktop:~$ arm-linux-gcc -v 会出现如下信息,这说明交叉编译环境已经成功安装 Reading specs from /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/specs Configured with: /work/crosstool-0.27/build/arm-linux/gcc-3.4.1-glibc-2.3.2/gcc-3.4.1/configure --target=arm-linux --host=i686-host_pc-linux-gnu --prefix=/usr/local/arm/3.4.1 --with-headers=/usr/local/arm/3.4.1/arm-linux/include --with-local-prefix=/usr/local/arm/3.4.1/arm-linux --disable-nls --enable-threads=posix --enable-symvers=gnu --enable-__cxa_atexit --enable-languages=c,c++ --enable-shared --enable-c99 --enable-long-long Thread model: posix gcc version 3.4.1 第八步:Red Hat9.0和虚拟机进行连接 连接好电源,串口线,网线 经过上面设置后在终端下以root用户执行minicom 这时你就可以进入到开发板了
(注: 来自&我的三分地空间)
linux 下建立tftp server
TFTP是用来下载远程文件的最简单网络协议,它其于UDP协议而实现。嵌入式linux的tftp开发环境包括两个方面:一是linux服务器端的tftp-server支持,二是嵌入式目标系统的tftp-client支持。因为u-boot本身内置支持tftp-client,所以嵌入式目标系统端就不用配置了。下面就详细介绍一下linux服务器端tftp-server的配置。
在redhat 9.0的第三张光盘中,有tftp-server的安装rpm包。
#mount –t iso9660 /de}

我要回帖

更多关于 ringer mode changed 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信