LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 5549|回复: 17

多媒体键设置指南

[复制链接]
发表于 2007-9-17 13:09:21 | 显示全部楼层 |阅读模式
以前在ubuntu下发的,一直没有人看,可能ubuntu对设备支持本来就比较大而全吧。出了学校,现在gentoo源和u/d的差不多快,初来乍到,多多指教~

1、终端下scancode于keycode
键盘事件发生,核心会出来一个scancode,然后将这个scancode转换成keycode,,这个时候才知道这个键按下是什么意思。怎样知道自己的多媒体键是不是内核识别出来了呢?直白的说,只要你的scancode被识别了,那么就可以进行下面的操作,如果内核没有识别出来,那就白搭。

  1. showkey -s
复制代码

这会检查出你的按键是否产生scancode。
注意,并不是没有产生scancode就说明这个键没有用,这只是说明内核不知道这个键。就拿我的dell 630m来说,调亮度就不会产生scancode,因为这个功能是直接由bios管理的,操作系统完全无法管理。

能够产生scancode,那么接着看这个键是不是有keycode map上了。
  1. showkey -k
复制代码

还是按键尝试。

作为一种替代方法,也可以按键之后,
  1. dmesg |tail
复制代码

这样不能识别的键的scancode会提示,要你人工设定keycode。

如果有keycode输出,可以直接跳过下面,进入2部分。
没有keycode,我们可以用setkeycodes工具将scancode映射上keycode。但之前首先要检查这个keycode是不是已经用上了。
  1. dumpkeys
复制代码

其中没有占用的就是可以使用的keycode,可以在等下用上。
  1. setkeycodes e012 167
复制代码

将scancode e012映射上keycode 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开关
  1. atkbd.softraw=0
复制代码

来达到目的。

那么这个标准的scancode从哪里可以知道定义呢?
答案是:
/usr/include/linux/input.h

#define KEY_MUTE                113
#define KEY_VOLUMEDOWN          114
#define KEY_VOLUMEUP            115
#define KEY_NEXTSONG            163
#define KEY_PLAYPAUSE           164
#define KEY_PREVIOUSSONG        165
#define KEY_STOPCD              166

显然,我的dell630m是完全被认出来了,只有一个媒体中心的键没有映射到。

2、终端下的伪多媒体键。
为什么说这是伪快捷键,因为这实际上只是把字符串连接上一个字串而已,相当于按一个键,直接输入了这么多字符而已。
keymaps所在的位置一般是在/usr/share/keymaps下。我们创建自己的keymap文件。
/usr/local/share/keymaps/dell.map
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
"

这样就是把对应的keycode映照上指定的字串名字。注意每个字串,是包括后面的换行符。
同样的,这个map也需要每次启动时自动执行。我还是放在/etc/conf.d/local.start中。
  1. loadkeys /usr/local/share/keymaps/dell.map
复制代码

(实际上看看/usr/share/keymaps/下面i386内的文件就知道,内核其实也是通过map来知道某个键的含义是什么的。)

3、X下的多媒体键绑定
首先,X中也有keycode的概念,但是这个keycode和终端中的keycode是不同的。
查看目录/usr/share/X11/xkb
下面的keycodes就是我们的keycode是怎样产生的。
  1. setxkbmap -print
复制代码

可以看出我们现在的xkb配置是怎样的。
简单的说来,每行的意思:
  • 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。


上面讲的罗嗦,对我们有意义的只有一项,那就是keycode的识别。只要识别了keycode,那么我们就可以map上X事件。检查X的keycode识别了没有的很简单:
  1. xev
复制代码

按键之后看输出的keycode是什么。如果识别了,直接看4部分。
重新看setxkbmap -print的输出:
xkb_keycodes  { include "xfree86+aliases(qwerty)"       };
xkb_symbols   { include "pc+us+inet(latitude)"  };

看xkb_keycode后面的include的内容。xfree86+aliases(qwerty),这代表的是:
在keycodes目录下的xfree86文件的内容(实质是xfree86文件中作为default存在的那段定义)和aliases文件中的qwerty段的内容的统一。
类似的,xbk_symbols后面的可以理解为symbols目录下的pc,us,和inet文件中latitude段定义。
所以,如果没有识别,我们只要修改上面对应的文件就好了。对我来说,主要是keycodes/xfree86。
xfree86的内容很多,我们要注意的是:
xkb_keycodes "basic" {

    minimum= 8;
    maximum= 255;


说明,在x中的keycode最小是8,最大是255。
basic段注释的非常好,再次提醒,这里面的keycode与终端中的无关!
但是对于特殊按键,并不是没有解释。象我们的多媒体键,通常就是所谓的“Internet key”
也就是<I01>这类的标识符表示的键。

前面说过,X的keycode的来历是由键盘scancode-->内核keycode-->由内核keycode生成的scancode-->X的keycode这总共3步转化成的。其中第一步可以修改,第二步和第三步都是内建的,所以我们完全可以做一个由内核keycode到X的keycode的对应表格。
这里是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

在启动脚本中添加

  1. xmodmap ~/.Xmodmap
复制代码

这行命令。
我放在~/.xinitrc中。
然后编辑文件~/.xbindkeysrc
"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

下面是事件keysym名称,上面是命令本身。
xbindkeys也需要加入启动脚本。
  1. xbindkeys
复制代码


也可以用替代的方法,使用类似lineak或者hotkeys这样的程序。
其实这类软件,也就是做了一个keycode到keysym然后再到命令的转化过程。但是这些软件都会带上很多笔记本电脑的keycode等等的数据,如果在他的数据中有,那么识别就容易,out of box,如果没有,就会有些键用不上。
hotkeys的数据是简单的xml文件。可以自己手动编辑,很容易,不详述了。
另外,在使用了xbindkeys和xmodmap之后,再用xev似乎就看不到事件出现了。但是不影响快捷键的使用。

6、不应用程序,而是修改keymap本身或者创建自己的keymap。
直接改,比较简单,但是Xorg一更新,这个就替换掉了。
首先看X的keycode在keycodes/xfree86中是对应的什么符号:
例如
<I20> =   160;
<I2E> =   174;
<I30> =   176;

那么我们知道我的内核keycode为113,114,115的这三个键,现在叫<I20><I2E><I30>
于是改symbols/inet中的latitude段,
    key <I20>   {       [ XF86AudioMute         ]       };
    key <I2E>   {       [ XF86AudioLowerVolume  ]       };
    key <I30>   {       [ XF86AudioRaiseVolume  ]       };

这样,这几个键一按下来,就会产生这些个事件了。当然,xbindkeys,hotkeys这样的程序也还是要的。
如果你的多媒体键的内核keycode所对应的X的keycode没有在keycodes/xfree86中出现,那么你可以自己添加一个这样的keysym。如果你的keysym没有在symbols/inet中有对应的事件,那么也是添加上即可。
创建什么的有标准教程,不写了。

以上方法只针对Xorg的xkb本身,所以对一切桌面环境应该都是适用的。
针对gentoo wiki,增加了终端keycode到X的keycode码表;没有终端keycode就没有X的keycode的原因;对/usr/share/X11/xkb下目录结构的解读。看了就当是翻译好了。
发表于 2007-9-17 13:12:41 | 显示全部楼层
收藏了。楼主辛苦了。过两天有空了一定试试。可惜了我的罗技键盘linux下很多功能键不能用啊。
回复 支持 反对

使用道具 举报

发表于 2007-9-17 19:22:01 | 显示全部楼层
不错,太全面了。
回复 支持 反对

使用道具 举报

发表于 2007-9-17 19:28:24 | 显示全部楼层
mark一下,有空就按部就班地学着做一遍。
回复 支持 反对

使用道具 举报

发表于 2007-9-17 23:09:50 | 显示全部楼层
不错的贴子!支持!
回复 支持 反对

使用道具 举报

发表于 2007-9-18 08:43:33 | 显示全部楼层
我以前用gnome的时候都是用那个自定义键盘来绑定特殊功能键的。
回复 支持 反对

使用道具 举报

发表于 2007-9-18 09:39:33 | 显示全部楼层
收藏先,好贴啊
楼主再多多发精品呀
顶一个
回复 支持 反对

使用道具 举报

发表于 2007-9-18 09:46:10 | 显示全部楼层
Post by sheep204
我以前用gnome的时候都是用那个自定义键盘来绑定特殊功能键的。


me too
回复 支持 反对

使用道具 举报

发表于 2007-9-19 09:10:32 | 显示全部楼层
delicioused……谢谢楼主
回复 支持 反对

使用道具 举报

发表于 2007-9-19 14:19:46 | 显示全部楼层
很有用啊,多谢楼主
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表