xkb: problem in key-mapping for the acpi video event keycodes

Hong Liu hong.liu at intel.com
Thu Jan 3 23:33:48 PST 2008


Currently in Linux kernel, there are some new keys defined for ACPI
video events, like KEY_SWITCHVIDEOMODE(227)
KEY_BRIGHTNESSUP(224) /KEY_BRIGHTNESSDOWN(225) ...

These keycodes will be reported to the input layer of Linux kernel by
ACPI video driver when pressing the hotkeys on laptop.
f.e pressing Fn+F7 on a thinkpad T61, KEY_SWITCHVIDEOMODE will be
reported.

The problem is the keycode received by X server that will be delivered
to X clients is not what supposed to be.
For KEY_SWITCHVIDEOMODE (227), X are supposed to receive 235 (227 + 8).
But we are receiving 214 instead.

After some investigation, I found the reason.

There are two parts involved.
1. kernel(Linux) part (driver/char/keyboard.c)
This file implements an input handler (kbd_handler) used to receive key
events from the kernel input layer. So when acpi video driver sends
KEY_SWITCHVIDEOMODE(227) to the input layer, kbd_event() will be called
for this event.
kbd_event -> emulate_raw (with keycode == 227)
        use x86_keycodes[] to map keycode 227 -> 342
        **I am still not sure about the meaning of this mapping**

        and then it will put "0xe0 0x56(342 & 0x7f)" to the input queue
        of the associated tty device. (for X server, usually it
	is /dev/tty7)

2. X server keyboard driver (xf86-input-keyboard)
This keyboard driver will listen to the /dev/tty7 file for keyboard
input from kernel. Once there is new data coming, it will call this
keyboard's PostEvent function to post the event to X server.

stdReadInput -> kbdPostEvent
        We will read "0x60 0x56" for the above "0xe0 0x56" input.
        (It seems the tty layer also has done some mapping)

        0x60 is a special keycode (KEY_Prefix0), it is used to
        mapping the following keycode to a new scancode.

        -> RemapScanCode (ATScancode)
                in this func, scancode 0x56 will be converted to a new
                scan code 0x56+0x78 (206).

        later in kbdPostEvent, all the scancodes will be added by
        MIN_KEYCODE (8), thus we get 214 for the KEY_SWITCHVIDEOMODE.

So there are 2 options here:
1. We accept 214 as the mapping of the KEY_SWITCHVIDEOMODE from kernel.
So we can bind the XF86Display keysym of Xserver to keycode 214.

2. We can have a patch for the xf86-input-keyboard driver, adding a new
mapping for KEY_SWITCHVIDEOMODE like the following one:

diff --git a/src/at_scancode.c b/src/at_scancode.c
index b945914..c5c627a 100644
--- a/src/at_scancode.c
+++ b/src/at_scancode.c
@@ -109,6 +109,7 @@ ATScancode(InputInfoPtr pInfo, int *scanCode)
             case KEY_F6:          *scanCode = KEY_F16;       break;
             case KEY_F7:          *scanCode = KEY_F17;       break;
             case KEY_KP_Plus:     *scanCode = KEY_KP_DEC;    break;
+            case 0x56:            *scanCode = 227;           break;
             case 0x2A:
             case 0x36:
                 return TRUE;

Thus we can get keycode 235 in X server for KEY_SWITCHVIDEOMODE.

I am not sure whether one is the correct choice.

Thanks,
Hong




More information about the xorg mailing list