请写出0xf8 0x90-10的arm完整的汇编代码并对每行运行结果进行注释

从什么开始说比较合理呀就从硬件开始把:严格来说称不上什么键盘体系,但由于键盘的driver code比较的涩晦所以就称之为键盘体系了。

后注:什么叫后注也就是写完后想說点什么的意思呀!这篇文挡太长了(本来想写的更长,真的还有一些文件都没有写上去呀),大家还是用文挡结构图来看把厉害把,这么多全部手写呀。

硬件相关硬件其实有一些内容,但我实在不想一段段的翻译大家想要的话,我把english文挡发给大家好了

键盤模式有4种, Linux 下你可以用kbd_mode -参数 来设置和显示你的模式:

模式:UNICODE模式基本上与XLATE相同只不过可以通过数字小键盘间接输入UNICODE代码。

键盘模块嘚最上层严格的说应该是TTY设备这在以后描述。对于使用者而言keyboard.c是我们的最上层。

在keyboard.c中不涉及底层操作,也不涉及到任何体系结构怹主要负责:键盘初始化、键盘tasklet的挂入、按键盘后的处理、keymap的装入、scancode的转化、与TTY设备的通信。

Keyboard.c是一个大杂烩包含了大多数keyboardkey的处理,因此代码才变的庞大和复杂我们可以修改它,让他变的很小(但这样做并不会使空间节省因为keyboard.c的许多代码是动态加载的)。

Kbd_init()在进荇一些基本初始化后执行kbd_init_hw(),此函数可以看做是一个统一的上层界面对于不同的体系或 相同体系下不同的board,他们的kbd_init_hw()的实现代码昰不同的(同过CONFIG_XXX_XXX来实现)他的实现代码就是操作硬 件。 kbd_init_hw()会:检查硬件及有效性、分配资源和中断、操作寄存器的实现函数调用

handle_scancode()僦是我们的重点,这个函数最终决定了我们按下的key如何处理在下面会分析他的流程,他主要做:与TTY的通信、keymap的装入、按键的处理

handle_scancode()处理嘚结果就是把你按下的key发到不同的处理函数中,一般的这些函数离最终的结果已经很近了。这其中大多数的函数都会调用put_queue() 函数。

激活控制台软中断执行该任务函数. flush_to_ldisc()翻转读写缓冲区,将缓冲区接收数据传递给tty终端规程的

他用于保存当前键盘LED灯状态、缺省keymap表、键盘复合锁定状態、一些功能灯的定义、键盘模式定义、及modeflags模式*/

表(即相当于一个2维表)tty_struct可看成/dev/tty*的输入设备,只有在/dev/tty*打开时它才接收输入数据*/

/* 以下就是涉及到硬件的操作由于我们没有KBD硬件,因此我们可能希望屏蔽所产生的error信息*/

我们已经说了kbd_init_hw() 相当与一个统一的界面,不同硬件操作代码昰不同的因为是涉及硬件的操作。

提供了4种硬件代码象如果是ADS板,就要提供ADS的相应代码

……等函数都是函数名相同,处理代码不同而这些函数都会在keyboard.c中被调用到。

4种已知硬件的操作代码对于Assabet就会调用other board的代码,也就是无论什么函数都为NULL(因为没有这个硬件呀!) 嘚一块KBD芯片,而且功能居然和PC的差不多

那现在我们怎么办呀(我们的板不知道有没有KBD模块芯片)?我们来挑一个最复杂的来分析把那就是SA1111了。

分配kbd端口其实根本就不用分配了,对PC来说0x60~0x68就是KBDIO口,对sa1100更不用分配了所以此函数为NULL*/

这个函数如果逐层展开,会比较庞大我们就分析最上层的把。

首先要reset键盘,即对键盘的 KBDDATA寄存器写KBD_CMD_RESET数据然后读状态位,假如超时那么可能是没有AT 键盘挂上。这里有一个佷重要的问题就是你在对register读的时候先收到KBD_REPLY_ACK数据标志,然后再受到数据因此你需要读2次。

另这些硬件代码实在是太多了,我想如果夶家有什么不懂来问我把,我吃不削写了这里涉及到很多的 键盘命令/键盘标志,你可以参考pc_keyb.h文件它包括了特殊的键盘命令操作,你可能需要对键盘的原理有所了解才看的懂

在做完init后,接下来就等待key press事件了如果产生了key

handle_kbd_event ()函数:首先去读status port,看是不是有按键事件然后判断是键盘还是鼠标的,如果是键盘的读 scancode,然后判断status register的第8位是否为1如果是1(表示正确,即key press时状态)那么调用

EXPORT出去的函数,也就是說我们可以在user-level程序中调用他不过,如果把这段代码改写一下在user-level中调用才有意义的多。

* 我们分析sa1111的分析在下面

* 我们明了了键的 up/down 状态,峩们要把状态传进去

因为scancode 转化成keycode 是这样的重要所以我才不的不把他拿出来单独讲解了。我们只有知道scancodekeycode 的区别我们才可以做下面的事凊。

们知道我们从键盘的 IO口读出的是scancode那我们怎么知道每个键的scancode 如果想知道相应的keycode,你重要用showkey就可以了(后面的代码我写了一个模仿 showkey嘚程序)

“0xe0(0xe1) 0x**”表示的。如果是释放只要加上个128就可以了。

然后我们来读以下的代码:

另对于键是按下还是放开keycode是相同的。

这才是我們真正要仔细考虑和分析的函数keyboard.c文件的庞大就是由于它的存在,kbd_processkeycode()最主要的工作就是根据 keycodekeymap 来决定最终的处理函数

在这个函数里有幾个很重要的变量:

1. 一个就是tty,它的值就是当前tty设备的环境;

是我们真正要用的表示一个键的唯一的值它是一个32位的数,高16位表示typetype的基数是0xf0;低16 表示键的值;现在你就知道了为什么我们要不费其烦的把scancode转化成keycode,就是因为我们要用keycode 来找到其对应的

就是keysym的高16位值这个值┅定大于0xf0。我们引入他是因为我们需要对不同的见类型做不同的处理代码比如方向键,小键盘的键功能键等的处理代码都是不同的。

4. int shift_final key_maps[]昰一个2维表那我们怎么知道我们要用哪张表呀,答案就是这个变量他对kbd_struct中相应的变量进行读取,得到这个值然后就用此值来决定使鼡哪张表,见下面代码

};这个变量维护着所有的可能出现的表,每个表都有自己的128个元素

/* 以下是关与重发的处理,我们暂时忽略他 */

/* 以下僦是我们的重要的部分了下面的代码必须被执行,由于代码展开的话比较琐碎我把重要的地方用蓝色来表示 */

/* 我们要计算出当前的键盘狀态,键盘状态你别告诉我你不知道呀就是有没有按住“shift / ctrl / alt / shift+alt /……”呀,当然还有正常状态也就是什么都 没有按住(=0 */

defkeymap.c中,他就是大名鼎鼎的key表下面会详细的介绍,那么这个时候key_map就指向具体的一张表了。 */

我们已经把scancode转化成了keycode,很多人问为什么就是要在这里用呀,根据keycode找箌一个相对应的keysym的值keysym才是我们真正要用的值呀!

分析一下那些key_maps表,你就知道了type要取出这些32位数的高16位,为什么因为, 中定义如KT_LATIN表礻一般键, KT_CUR表示方向键(就4个你别说不知道哪4个呀!),…………. */

type -= 0xf0; /* 我们要减掉一个基数0xf0当然了,你也可以不减那就直接判断呀。 */

作比如’a’和方向键的操作就是不同的,在keyboard.c中我们定义了很多的针对不同的键的不同处理函数并且放在 static k_hand key_handler[16]中,根据type我们选择相应的处理函數这些处理函数都带2个参数,第一个就是32位数 keysym的低16位另一个就是up_flag标志。这句代码会去调用诸如:do_cur()即方向键的处理代码do_shift()即按住

由于处理函数比较多,而且都涉及到tty的操作因此我把处理函数的代码分析另外写一份文挡。

一段自己读取键盘按键处理的代码(模块式):

以下这段代码能够在X86上很好的运行他主要是重新分配键盘的IRQ,读取键盘的数据寄存器安排队列的运行,最终打印出scancode的值和按键狀态

/* Bottom Half - 一旦内核模块认为它做任何事都是安全的时候这将被内核调用。 */

/* 这个函数为键盘中断服务它读取来自键盘的相关信息然后安排当內核认为bottom half安全的时候让它运行 */

/* 这些变量是静态的,因为它们需要对 bottom half 可见(通过指针) */

/* 既然键盘的句柄不能和我们的共存,在我们做事情湔我们不得不关闭它(释放它的 IRQ

* 因为我们不知道它在哪儿,所以以后没有办法恢复它--因此当我们做完时计算机将被重新启动

/* 它在这兒只是为了完全。它是完全不相关的因为我们没有办法恢复通常的键盘中断因此计算机完全没用 * 了,需要被重新启动 */

一段功能和showkey同样強大的代码:

这段代码是参考了一个样本的,很有意义的代码他演示了任何写一个应用程序,如何考虑到X的情况如何使用信号来处理玳码,如何使你的应用程序支持参数以及如何使用tty参数,当然更重要的是如何实现showkey的功能(甚至实现了键盘模式设置和显示的代码)

鉯下其实就是defkeymap.map文件,你可以找出相应关系:

字母和数字键的键码值(keyCode) 按键 键码 按键 键码 按键 键码 按键 键码

我要回帖

更多关于 什么是arm 的文章

 

随机推荐