1、终端下scancode于keycode
键盘事件发生,核心会出来一个scancode,然后将这个scancode转换成keycode,,这个时候才知道这个键按下是什么意思。怎样知道自己的多媒体键是不是内核识别出来了呢?直白的说,只要你的scancode被识别了,那么就可以进行下面的操作,如果内核没有识别出来,那就白搭。
代码: 全选
showkey -s
注意,并不是没有产生scancode就说明这个键没有用,这只是说明内核不知道这个键。就拿我的dell 630m来说,调亮度就不会产生scancode,因为这个功能是直接由bios管理的,操作系统完全无法管理。
能够产生scancode,那么接着看这个键是不是有keycode map上了。
代码: 全选
showkey -k
作为一种替代方法,也可以按键之后,
代码: 全选
dmesg |tail
如果有keycode输出,可以直接跳过下面,进入2部分。
没有keycode,我们可以用setkeycodes工具将scancode映射上keycode。但之前首先要检查这个keycode是不是已经用上了。
代码: 全选
dumpkeys
代码: 全选
setkeycodes e012 167
这个指令需要写在启动脚本中。我放在
/etc/conf.d/local.start中。
要说明一下,linux内核2.6对scancode和keycode有着和以前不一样的对待方式。在以前,有程序要检查scancode的话,那么就会给这个程序scancode,但是现在不同,现在是根据生成的keycode,重新翻译一个scancode给应用程序,这样就把个个厂商可能都不同的scancode,在应用程序方面统一了起来。代价就是应用程序对于没有keycode的按键就完全不知道了。所以如果一个键没有keycode,那么一定要setkeycodes给它。而X,就是这样一个应用程序。
补充一下,如果想要直接输出真正的scancode,那么在2.6.9内核之后,可以使用kernel开关
代码: 全选
atkbd.softraw=0
那么这个标准的scancode从哪里可以知道定义呢?
答案是:
/usr/include/linux/input.h
#define KEY_MUTE 113
#define KEY_VOLUMEDOWN 114
#define KEY_VOLUMEUP 115
显然,我的dell630m是完全被认出来了,只有一个媒体中心的键没有映射到。#define KEY_NEXTSONG 163
#define KEY_PLAYPAUSE 164
#define KEY_PREVIOUSSONG 165
#define KEY_STOPCD 166
2、终端下的伪多媒体键。
为什么说这是伪快捷键,因为这实际上只是把字符串连接上一个字串而已,相当于按一个键,直接输入了这么多字符而已。
keymaps所在的位置一般是在/usr/share/keymaps下。我们创建自己的keymap文件。
/usr/local/share/keymaps/dell.map
这样就是把对应的keycode映照上指定的字串名字。注意每个字串,是包括后面的换行符。keycode 113 = F73
keycode 114 = F74
keycode 115 = F75
keycode 163 = F83
keycode 164 = F84
keycode 165 = F85
keycode 166 = F86
string F73 = "amixer -q set Master toggle
"
string F74 = "amixer -q set Master 2- unmute
"
string F75 = "amixer -q set Master 2+ unmute
"
string F83 = "mpc next
"
string F84 = "mpc toggle
"
string F85 = "mpc prev
"
string F86 = "mpc stop
"
同样的,这个map也需要每次启动时自动执行。我还是放在/etc/conf.d/local.start中。
代码: 全选
loadkeys /usr/local/share/keymaps/dell.map
3、X下的多媒体键绑定
首先,X中也有keycode的概念,但是这个keycode和终端中的keycode是不同的。
查看目录/usr/share/X11/xkb
下面的keycodes就是我们的keycode是怎样产生的。
代码: 全选
setxkbmap -print
简单的说来,每行的意思:
- xkb_keycodes { include "xfree86+aliases(qwerty)" };从keycode转换到类似于<AE01>这样形式的符号,之后的x就不会再管keycode的事的。独立于硬件了。
- xkb_types { include "complete" };将各种快捷键分级。例如shift+ctrl+xx什么的,就要后于shift+xx的识别,否则前面这个快捷不就永无出现之日?
- xkb_compat { include "complete" };兼容性的简写,很奇怪的名字,相对于symbol,更像是只对xkb的状态改变之类的信号感兴趣。例如按下num_lock,就由方向键变成了数字键一样。
- xkb_symbols { include "pc+us+inet(latitude)" };将keycode转换来的符号分组,结合象shift这样的修饰键,这样可以实现一个按键,产生不同的符号,例如1和!。
- xkb_geometry { include "pc(latitude)" };键盘的物理布局,例如可能esc键,我们有时后也用"最左上角的键"来表示。这一层可以帮助X作出类似的alias。
代码: 全选
xev
重新看setxkbmap -print的输出:
看xkb_keycode后面的include的内容。xfree86+aliases(qwerty),这代表的是:xkb_keycodes { include "xfree86+aliases(qwerty)" };
xkb_symbols { include "pc+us+inet(latitude)" };
在keycodes目录下的xfree86文件的内容(实质是xfree86文件中作为default存在的那段定义)和aliases文件中的qwerty段的内容的统一。
类似的,xbk_symbols后面的可以理解为symbols目录下的pc,us,和inet文件中latitude段定义。
所以,如果没有识别,我们只要修改上面对应的文件就好了。对我来说,主要是keycodes/xfree86。
xfree86的内容很多,我们要注意的是:
说明,在x中的keycode最小是8,最大是255。xkb_keycodes "basic" {
minimum= 8;
maximum= 255;
basic段注释的非常好,再次提醒,这里面的keycode与终端中的无关!
但是对于特殊按键,并不是没有解释。象我们的多媒体键,通常就是所谓的“Internet key”
也就是<I01>这类的标识符表示的键。
前面说过,X的keycode的来历是由键盘scancode-->内核keycode-->由内核keycode生成的scancode-->X的keycode这总共3步转化成的。其中第一步可以修改,第二步和第三步都是内建的,所以我们完全可以做一个由内核keycode到X的keycode的对应表格,这个表格我做到后面附件pdf了。
这里是ascii的,排版不是很好看:
0, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 76, 79, 80, 81, 82, 83, 84, 85, 86, 87,
88, 89, 90, 91, 111, 221, 94, 95, 96, 211, 128, 127, 129, 208, 131, 126,
108, 109, 112, 111, 113, 181, 97, 98, 99, 100, 102, 103, 104, 105, 106, 107,
239, 160, 174, 176, 222, 157, 123, 110, 139, 134, 209, 210, 133, 115, 116, 117,
232, 133, 134, 135, 140, 248, 191, 192, 122, 188, 245, 158, 161, 193, 223, 227,
198, 199, 200, 147, 159, 151, 178, 201, 146, 203, 166, 236, 230, 235, 234, 233,
163, 204, 253, 153, 162, 144, 164, 177, 152, 190, 208, 129, 130, 231, 209, 210,
136, 220, 143, 246, 251, 137, 138, 182, 183, 184, 93, 184, 247, 132, 170, 219,
249, 205, 207, 149, 150, 154, 155, 167, 168, 169, 171, 172, 173, 165, 175, 179,
180, 0, 185, 186, 187, 118, 119, 120, 121, 229, 194, 195, 196, 197, 148, 202,
101, 212, 237, 214, 215, 216, 217, 218, 228, 142, 213, 240, 241, 242, 243, 244,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
4、用程序映射keycode到特定的程序。
xev如果同时告诉了我们keysym是什么的话,那么直接用它给的keysym就好了。如果没有,用xmodmap将keycode绑定到特定的X keysym。
编辑文件~/.Xmodmap
在启动脚本中添加keycode 162 = XF86AudioPlay
keycode 164 = XF86AudioStop
keycode 160 = XF86AudioMute
keycode 144 = XF86AudioPrev
keycode 153 = XF86AudioNext
keycode 176 = XF86AudioRaiseVolume
keycode 174 = XF86AudioLowerVolume
代码: 全选
xmodmap ~/.Xmodmap
我放在~/.xinitrc中。
然后编辑文件~/.xbindkeysrc
下面是事件keysym名称,上面是命令本身。"amixer -q sset PCM 6- unmute"
XF86AudioLowerVolume
"amixer -q sset PCM 6+ unmute"
XF86AudioRaiseVolume
"amixer -q sset Master toggle"
XF86AudioMute
"/usr/bin/mpc prev"
XF86AudioPrev
"/usr/bin/mpc next"
XF86AudioNext
"/usr/bin/mpc stop"
XF86AudioStop
"/usr/bin/mpc toggle"
XF86AudioPlay
xbindkeys也需要加入启动脚本。
代码: 全选
xbindkeys
其实这类软件,也就是做了一个keycode到keysym然后再到命令的转化过程。但是这些软件都会带上很多笔记本电脑的keycode等等的数据,如果在他的数据中有,那么识别就容易,out of box,如果没有,就会有些键用不上。
hotkeys的数据是简单的xml文件。可以自己手动编辑,很容易,不详述了。
另外,在使用了xbindkeys和xmodmap之后,再用xev似乎就看不到事件出现了。但是不影响快捷键的使用。
6、不应用程序,而是修改keymap本身或者创建自己的keymap。
直接改,比较简单,但是Xorg一更新,这个就替换掉了。
首先看X的keycode在keycodes/xfree86中是对应的什么符号:
例如
那么我们知道我的内核keycode为113,114,115的这三个键,现在叫<I20><I2E><I30><I20> = 160;
<I2E> = 174;
<I30> = 176;
于是改symbols/inet中的latitude段,
这样,这几个键一按下来,就会产生这些个事件了。当然,xbindkeys,hotkeys这样的程序也还是要的。key <I20> { [ XF86AudioMute ] };
key <I2E> { [ XF86AudioLowerVolume ] };
key <I30> { [ XF86AudioRaiseVolume ] };
如果你的多媒体键的内核keycode所对应的X的keycode没有在keycodes/xfree86中出现,那么你可以自己添加一个这样的keysym。如果你的keysym没有在symbols/inet中有对应的事件,那么也是添加上即可。
创建什么的下次再写了,11点多了,也好晚了。
以上方法只针对Xorg的xkb本身,所以对一切桌面环境应该都是适用的。