我正在试图添加自己的键盘设备,花了快两个星期了,读了keyboard.c和 /src/core/input.c 两个文件头大死了,发现directfb的键盘设备是针对标准键盘的,好像没有为自定义键盘留有任何额外的接口,而且键值的获取、翻译、传递过程及其复杂,看的我是相当迷糊,在此提出一些问题,看看读过directfb键盘设备源码的朋友能不能给指点一下? 在keyboard.c中,好像通过了两种方法都获得了标准键盘的键盘值(不是扫描值,用的是MEDIUMRAW 模式),一种是在driver_open_device里通过建立一个keyboardEventThread线程,然后在keyboardEventThread里使用系统调用read()从设备驱动里读取键值,另一种是通过在driver_get_keymap_entry模块里的keyboard_read_value()里,使用系统调用ioctl(),来获取键值,然后在把这个值通过别的函数转换成一种DFBInputDevicekeySymbol。。。等等等。。。
回过头来再看通过read()方法得到的键值,是通过调用dfb_input_dispatch--》fixup_key_event,然后在fixup_key_event这个函数里根据不同的情况来分别调用
lookup_from_table()
find_key_code_by_id()
find_key_code_by_symbol()
id_to_symbol()
symbol_to_id()
来得到相应的新的键值,让我头大的是,event结构体里的key_code、key_id、key_symbol,到底是什么关系,有一个实际的键盘值对应一个directfb可以识别的键值就行了,个干吗还要key_id,key_symbol,这种多重复杂的来回转换,到底有什么用?通过read()传过来的键值并通过转换后得到的新值与通过ioctl得到的那个键值有什么区别和联系?我要添加自己的键盘,不使用标准键盘,到底从哪个地方开始切入??
zhyuzhyu1985 发表于 2008-8-14 18:22
代码里面有说明的,key_id是更上层的抽象,跟硬件无关,key_symbol硬件相关。你要使用自己的键盘的话,可以全部用key_symbol,把自己键盘的键值全部读出来,再全部转换成key_symbol,就直接可以用了,跟遥控器一样实现原理。它的keyboard.c本来就是实现标准键盘的。你要添加,自己建个keyborad1.c。
tiansun7k 发表于 2008-8-15 18:20
谢谢,LS的解答,我今天又仔细的分析了一下这部分的源码,麻烦你能不能给一下细节的指点:
1 . 如果我自己重新写一个keyboard.c,其格式是不是要和原keyboard.c一样,包括一些实现的细节,是不是还是需要以下这几个宏和函数
DFB_INPUT_DRIVER(这个宏肯定是必须的,它的实现在input_driver.h中)
keyboard_get_symbol()
keyboard_get_identifier()
keyboard_read_value()
keyboard_set_lights()
keyboardEventThread()
driver_get_available()
driver_get_info()
driver_open_device()
driver_get_keymap_entry()
driver_close_device()
2. keyboard.c并不是孤立的,他里面的好多函数都是与/src/core下的input.c相关联的, 如果重新写一个keyboard.c肯定也要有于input.c中的函数相联系的地方,input.c不需
要改动吗?
3 我自己的键盘驱动已经在内核里运行了,而且我写了个测试程序,在终端下可以直接通过read的方法成功捕获键值,其实我只要有五个键能用就行了(上,下,左,右,确定),我在自己的keyboard.c中肯定也需要通过read来获取这个键值,而ioctl肯定就没用了(我自己的键盘驱动里就没有实现 ioctl方法),而我在自己的keyboard.c中诸如
driver_open_device(),keyboard_read_value()中的 ioctl( dfb_fbdev->vt->fd, KDSKBMODE, K_MEDIUMRAW )、ioctl( data->vt->fd, KDGKBENT, &entry )还要写吗?
4 原keyboard.c 中所得到的标准的键盘值到底是通过read得到的?还是通过ioctl得到的? 我看了一下代码:ioctl( data->vt->fd, KDGKBENT, &entry )得到的好像不是单纯的键盘码,因为键盘值传递给了entry这个结构体变量,而entry却有好多个成员:kb_table、kb_index、 kb_value,可以确定这个kb_value肯定是键值,但table和index是干什么用的呢?假如传过来的键值是一个字节,它是怎么正好就放在 kb_value里的呢?
5 我个人认为键值是通过keyboardEventThread()里的read 得到的,因为通过read以后的相关代码可以明显的看到:
for (i = 0; i < readlen; i++) {
DFBInputEvent evt; //定义了一个输入事件
evt.type = ((buf[i] & 0x80) ? DIET_KEYRELEASE : DIET_KEYPRESS); //标准键盘的 键值(MEDIUMRAW 模式)的最高位通 过是0还是1来区别按键的press和release
evt.flags = DIEF_KEYCODE; //标明是是键值,而不是KEYID或KEYSYMBOL
evt.key_code = buf[i] & 0x7f; //屏蔽最高位,低7位才是所需要的 标准键盘值 key_code
dfb_input_dispatch( data->device, &evt ); //通过evt指针把键值和其他信息传递给 input.c文件里的dfb_input_dispatch()具体实现
keyboard_set_lights( data, evt.locks );
}
在dfb_input_dispatch()里通过switch (event->type)来判断是不是 DIET_KEYRELEASE : DIET_KEYPRESS,然后对标准键盘的特殊键caps Lock进行处理,然后直接调用 fixup_key_event(),在这个函数里面,源码注释分了好多项: /* Add missing flags */、 /* Use cached values for modifiers/locks if they are missing.*/、/* With translation table*/、 /*Without translation table*/.、/* Update cached values for modifiers.*/....... 对这几部分看了好长时间也没弄清楚是怎么把相应的id,symnol,code处理的,特别是那个modifiers,搞不清他表示的到底是什么意思,因为在DFBInputEvent结构体里,分别对key_id和key_symbol是这样解释的:
key_id; /* basic mapping, modifier independent */
key_symbol; /* advanced mapping, unicode compatible,modifier dependent */
这个modifier是你说的“硬件”吗?根据上面的解释,key_id是不依赖modifier的,而key_symbol则依赖于modifier。
我个人感觉如果想让我自定义的键盘可以使用,input.c文件里的fixup_key_event()也要做很大的改动。
6 你在回贴里说的,“可以全部用key_symbol,把自己键盘的键值全部读出来,再全部转换成key_symbol,就直接可以用了,跟遥控器一样实现原理”,是说的在keyboard.c里实现吗?怎么把我自己的键值(假设驱动传过来的“确定键”的十六进制键值为41H)直接转换为key_symbol,你能写一小段代码举个例子吗? key_symbol好像是由directfb定义的,每个数值对应一个symbol(我不是很清楚),假如你添加过自定义键盘,能不能把你自己写的 keyboard.c和在input.c里作的改动发给我一份,让我参考一下?
非常感谢!!!!!!!!!!!!!
sword_lzr 发表于 2008-9-3 22:17
我已经实现了,给你参考我的修改
input.c
void
dfb_input_dispatch( CoreInputDevice *device, DFBInputEvent *event )
{
D_DEBUG_AT( Core_Input, "%s( %p, %p )\n", __FUNCTION__, device, event );
D_MAGIC_ASSERT( device, CoreInputDevice );
D_ASSERT( core_input != NULL );
D_ASSERT( device != NULL );
D_ASSERT( event != NULL );
D_ASSUME( device->shared != NULL );
/*
* 0. Sanity checks & debugging...
*/
if (!device->shared) {
D_DEBUG_AT( Core_Input, " -> No shared data!\n" );
return;
}
D_ASSUME( device->shared->reactor != NULL );
if (!device->shared->reactor) {
D_DEBUG_AT( Core_Input, " -> No reactor!\n" );
return;
}
D_DEBUG_AT( Core_InputEvt, " -> (%02x) %s%s%s\n", event->type,
dfb_input_event_type_name( event->type ),
(event->flags & DIEF_FOLLOW) ? " [FOLLOW]" : "",
(event->flags & DIEF_REPEAT) ? " [REPEAT]" : "" );
#if D_DEBUG_ENABLED
if (event->flags & DIEF_TIMESTAMP)
D_DEBUG_AT( Core_InputEvt, " -> TIMESTAMP %lu.%06lu\n", event->timestamp.tv_sec, event->timestamp.tv_usec );
if (event->flags & DIEF_AXISABS)
D_DEBUG_AT( Core_InputEvt, " -> AXISABS %d at %d\n", event->axis, event->axisabs );
if (event->flags & DIEF_AXISREL)
D_DEBUG_AT( Core_InputEvt, " -> AXISREL %d by %d\n", event->axis, event->axisrel );
if (event->flags & DIEF_KEYCODE)
D_DEBUG_AT( Core_InputEvt, " -> KEYCODE %d\n", event->key_code );
if (event->flags & DIEF_KEYID)
D_DEBUG_AT( Core_InputEvt, " -> KEYID 0x%04x\n", event->key_id );
if (event->flags & DIEF_KEYSYMBOL)
D_DEBUG_AT( Core_InputEvt, " -> KEYSYMBOL 0x%04x\n", event->key_symbol );
if (event->flags & DIEF_MODIFIERS)
D_DEBUG_AT( Core_InputEvt, " -> MODIFIERS 0x%04x\n", event->modifiers );
if (event->flags & DIEF_LOCKS)
D_DEBUG_AT( Core_InputEvt, " -> LOCKS 0x%04x\n", event->locks );
if (event->flags & DIEF_BUTTONS)
D_DEBUG_AT( Core_InputEvt, " -> BUTTONS 0x%04x\n", event->buttons );
if (event->flags & DIEF_GLOBAL)
D_DEBUG_AT( Core_InputEvt, " -> GLOBAL\n" );
#endif
/*
* 1. Fixup event...
*/
event->clazz = DFEC_INPUT;
event->device_id = device->shared->id;
if (!(event->flags & DIEF_TIMESTAMP)) {
gettimeofday( &event->timestamp, NULL );
event->flags |= DIEF_TIMESTAMP;
}
switch (event->type) {
case DIET_BUTTONPRESS:
case DIET_BUTTONRELEASE:
D_DEBUG_AT( Core_InputEvt, " -> BUTTON 0x%04x\n", event->button );
if (dfb_config->lefty) {
if (event->button == DIBI_LEFT)
event->button = DIBI_RIGHT;
else if (event->button == DIBI_RIGHT)
event->button = DIBI_LEFT;
D_DEBUG_AT( Core_InputEvt, " -> lefty! => 0x%04x <=\n", event->button );
}
/* fallthru */
case DIET_AXISMOTION:
fixup_mouse_event( device, event );
break;
case DIET_KEYPRESS:
case DIET_KEYRELEASE:
#if 0
if (dfb_config->capslock_meta) {
if (device->shared->keymap.num_entries && (event->flags & DIEF_KEYCODE))
lookup_from_table( device, event, (DIEF_KEYID |
DIEF_KEYSYMBOL) & ~event->flags );
if (event->key_id == DIKI_CAPS_LOCK || event->key_symbol == DIKS_CAPS_LOCK) {
event->flags |= DIEF_KEYID | DIEF_KEYSYMBOL;
event->key_code = -1;
event->key_id = DIKI_META_L;
event->key_symbol = DIKS_META;
}
}
fixup_key_event( device, event );
#endif
printf("event->key_code=%d\n",event->key_code);
switch(event->key_code){
case 1:
event->key_symbol=DIKS_1;
event->key_id=DIKI_A;
break;
case 2:
event->key_symbol=DIKS_2;
event->key_id=DIKI_B;
break;
case 3:
event->key_symbol=DIKS_3;
event->key_id=DIKI_C;
break;
case 4:
event->key_symbol=DIKS_4;
event->key_id=DIKI_D;
break;
case 5:
event->key_symbol=DIKS_5;
event->key_id=DIKI_E;
break;
case 6:
event->key_symbol=DIKS_6;
event->key_id=DIKI_F;
break;
}
break;
default:
;
}
#if D_DEBUG_ENABLED
if (event->flags & DIEF_TIMESTAMP)
D_DEBUG_AT( Core_InputEvt, " => TIMESTAMP %lu.%06lu\n", event->timestamp.tv_sec, event->timestamp.tv_usec );
if (event->flags & DIEF_AXISABS)
D_DEBUG_AT( Core_InputEvt, " => AXISABS %d at %d\n", event->axis, event->axisabs );
if (event->flags & DIEF_AXISREL)
D_DEBUG_AT( Core_InputEvt, " => AXISREL %d by %d\n", event->axis, event->axisrel );
if (event->flags & DIEF_KEYCODE)
D_DEBUG_AT( Core_InputEvt, " => KEYCODE %d\n", event->key_code );
if (event->flags & DIEF_KEYID)
D_DEBUG_AT( Core_InputEvt, " => KEYID 0x%04x\n", event->key_id );
if (event->flags & DIEF_KEYSYMBOL)
D_DEBUG_AT( Core_InputEvt, " => KEYSYMBOL 0x%04x\n", event->key_symbol );
if (event->flags & DIEF_MODIFIERS)
D_DEBUG_AT( Core_InputEvt, " => MODIFIERS 0x%04x\n", event->modifiers );
if (event->flags & DIEF_LOCKS)
D_DEBUG_AT( Core_InputEvt, " => LOCKS 0x%04x\n", event->locks );
if (event->flags & DIEF_BUTTONS)
D_DEBUG_AT( Core_InputEvt, " => BUTTONS 0x%04x\n", event->buttons );
if (event->flags & DIEF_GLOBAL)
D_DEBUG_AT( Core_InputEvt, " => GLOBAL\n" );
#endif
if (core_input_filter( device, event ))
{
printf( " ****>> FILTERED\n" );
}
else
{
printf("fusion_reactor_dispatch()\n");
fusion_reactor_dispatch( device->shared->reactor, event, true, dfb_input_globals );
}
}