📄 minigui 体系结构之四 图形抽象层和输入抽象层及 native engine 的实现(二).htm
字号:
<TR>
<TD><PRE># echo 1 > /dev/tty0
# echo 1 > /dev/tty
</PRE></TD></TR></TBODY></TABLE>
<P>结果都将把1 输入到当前终端上。另外,如果从伪终端上运行它们,则第一条指令会将 1 输出到控制台的当前终端,而第二条指令会把 1
输出到当前伪终端上。从而 tty0 表示当前控制台终端,tty 表示当前终端(实际是当前进程控制终端的别名而已)。</P>
<P>tty0 的设备号是 4,0</P>
<P>tty1 的设备号是 5, 0</P>
<P>/dev/tty 是和进程的每一个终端联系起来的,/dev/tty 的驱动程序所做的只是把所有的请求送到合适的终端。</P>
<P>缺省情况下,/dev/tty 是普通用户可读写的,而/dev/tty0 则只有超级用户能够读写,主要是基于这个原因,我们目前使用
/dev/tty 作为设备文件。后面所有有关终端处理的程序的都采用它作为当前终端文件,这样也可以和传统的 Unix 相兼容。</P>
<P>键盘驱动程序接口如清单 8 所示。</P>
<TABLE class=code-sample cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><PRE> 清单 8 Native 输入引擎的键盘驱动程序接口
typedef struct _kbddevice {
int (*Open)(void);
void (*Close)(void);
void (*GetModifierInfo)(int *modifiers);
int (*Read)(unsigned char *buf,int *modifiers);
void (*Suspend)(void);
void (*Resume)(void);
} KBDDEVICE;
</PRE></TD></TR></TBODY></TABLE>
<P>基本原理非常简单,初始化时打开 /dev/tty,以后就从该文件读出所有的数据。由于MiniGUI 需要捕获 KEY_DOWN 和
KEY_UP 消息,键盘被置于原始(raw)模式。这样,程序从 /dev/tty 中直接读出键盘的扫描码,比如用户按下A
键,就可以读到158,放下,又读到30。原始模式下,程序必须自己记下各键的状态,特别是shift,ctrl,alt,caps lock
等,所以程序维护一个数组,记录了所有键盘的状态。</P>
<P>这里说明一下鼠标移动,按键等事件是如何被传送到上层消息队列的。MiniGUI工作在用户态,所以它不可能利用中断这种高效的机制。没有内核驱动程序的支持,它也很难利用信号等Unix系统的IPC机制。MiniGUI可以做到的就是看
/dev/tty, /dev/mouse 等文件是否有数据可以读。上层通过不断调用 GAL_WaitEvent
尝试读取这些文件。这也是线程Parser的主要任务。GAL_WaitEvent 主要利用了系统调用select
这一类Unix系统中地位仅次于ioctl的系统调用完成该功能。并将等待到的事件作为返回值返回。</P>
<P>至此介绍了键盘和鼠标的驱动程序,作为简单的输入设备,它们的驱动是非常简单的。事实上,它们的实现代码也比较少,就是在嵌入式系统中要使用的触摸屏,如果操作系统内核支持,其驱动程序也是非常简单的:它只不过是一种特殊的鼠标。</P><A
id=5 name=5></A>
<P><STRONG class=subhead>5 特定嵌入式系统上图形引擎和输入引擎实现</STRONG></P>
<P>如前所述,基于 Linux 的嵌入式系统,其内核一般具备对 FrameBuffer 的支持,从而可以利用已有的 Native 图形引擎。在
MiniGUI 代码中,可通过调整 src/gal/native/native.h 中的宏定义而定义函数库中是否包含特定的图形引擎驱动程序(清单
9):</P>
<TABLE class=code-sample cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><PRE> 清单 9 定义 Native 引擎的子驱动程序
16 /* define or undefine these macros
17 to include or exclude specific fb driver.
18 */
19 #undef _FBLIN1_SUPPORT
20 // #define _FBLIN1_SUPPORT 1
21
22 #undef _FBLIN2_SUPPORT
23 // #define _FBLIN2_SUPPORT 1
24
22 #undef _FBLIN_2_SUPPORT
23 // #define _FBLIN_2_SUPPORT 1
24
25 //#undef _FBLIN4_SUPPORT
26 #define _FBLIN4_SUPPORT 1
27
28 // #undef _FBLIN8_SUPPORT
29 #define _FBLIN8_SUPPORT 1
30
31 // #undef _FBLIN16_SUPPORT
32 #define _FBLIN16_SUPPORT 1
33
34 #undef _FBLIN24_SUPPORT
35 // #define _FBLIN24_SUPPORT 1
36
37 #undef _FBLIN32_SUPPORT
38 // #define _FBLIN32_SUPPORT 1
39
40 #define HAVETEXTMODE 1 /* =0 for graphics only systems*/
</PRE></TD></TR></TBODY></TABLE>
<P>其中,HAVETEXTMODE 定义系统是否有文本模式,可将 MiniGUI 中用来关闭文本模式的代码屏蔽掉。_FBLIN_2_SUPPORT
和_FBLIN2_SUPPORT 分别用来定义 big endian 和 little endian 的 2bpp 驱动程序。</P>
<P>对于输入引擎来说,情况就有些不同了。因为目前还没有统一的处理输出设备的接口,而且每个嵌入式系统的输入设备也各不相同,所以,我们通常要针对特定嵌入式系统重新输入引擎。下面的代码就是针对
ADS 基于 StrongARM 的嵌入式开发系统编写的输入引擎(清单 10):</P>
<TABLE class=code-sample cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><PRE> 清单 10 为 ADS 公司基于 StrongARM 的嵌入式开发系统编写的输入引擎
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <sys/io.h>
36 #include <sys/ioctl.h>
37 #include <sys/poll.h>
38 #include <linux/kd.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <fcntl.h>
42
43 #include "common.h"
44 #include "misc.h"
45 #include "ads_internal.h"
46 #include "ial.h"
47 #include "ads.h"
48
49 #ifndef NR_KEYS
50 #define NR_KEYS 128
51 #endif
52
53 static int ts;
54 static int mousex = 0;
55 static int mousey = 0;
56 static POS pos;
57
58 static unsigned char state[NR_KEYS];
59
60 /************************ Low Level Input Operations **********************/
61 /*
62 * Mouse operations -- Event
63 */
64 static int mouse_update(void)
65 {
66 return 0;
67 }
68
69 static int mouse_getx(void)
70 {
71 return mousex;
72 }
73
74 static int mouse_gety(void)
75 {
76 return mousey;
77 }
78
79 static void mouse_setposition(int x, int y)
80 {
81 }
82
83 static int mouse_getbutton(void)
84 {
85 return pos.b;
86 }
87
88 static void mouse_setrange(int minx,int miny,int maxx,int maxy)
89 {
90 }
91
92 static int keyboard_update(void)
93 {
94 return 0;
95 }
96
97 static char * keyboard_getstate(void)
98 {
99 return (char *)state;
100 }
101
102 #ifdef _LITE_VERSION
103 static int wait_event (int which, int maxfd, fd_set *in, fd_set *out, fd_set *except,
104 struct timeval *timeout)
105 {
106 fd_set rfds;
107 int e;
108
109 if (!in) {
110 in = &rfds;
111 FD_ZERO (in);
112 }
113
114 if (which & IAL_MOUSEEVENT) {
115 FD_SET (ts, in);
116 if (ts > maxfd) maxfd = ts;
117 }
118
119 e = select (maxfd + 1, in, out, except, timeout) ;
120
121 if (e > 0) {
122 if (ts >= 0 && FD_ISSET (ts, in))
123 {
124 FD_CLR (ts, in);
125 read (ts, &pos, sizeof (POS));
126 if ( pos.x !=-1 && pos.y !=-1) {
127 mousex = pos.x;
128 mousey = pos.y;
129 }
130 pos.b = ( pos.b > 0 ? 4:0);
131 return IAL_MOUSEEVENT;
132 }
133
134 } else if (e < 0) {
135 return -1;
136 }
137 return 0;
138 }
139 #else
140 static int wait_event (int which, fd_set *in, fd_set *out, fd_set *except,
141 struct timeval *timeout)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -