handrake

Revision 20 as of 2006-03-12 12:41:24

Clear message

About myself

I am a student in computer engineering at University of Waterloo. I have been using Ubuntu Linux for 2 months now. Right now, I'm living in Etobicoke, it's a part of GTA (around Toronto area), working as co-op (co-op is like an intern program). I'm dying to get a computer sometime next week so that I can participate.

I finally got my computer, fujitsu P7120, and I'm totally satisfied with what I've got. Looks all good to me Smile :)

Known Bugs

There is a bug in gaim 2.0 beta, the one with not being able to send a last character if you are writing in Korean. Currently, you can send messages in Korean without a problem in a message tab, which has been a problem back in gaim 1.5, but in "Set friendly name" menu, the problem seems to still exist.

I think this bug can be fixed with a simple patch, doing the same thing Gaim team has done for a message tab.

-- this bug is fixed in gaim 2.0 beta cvs version.

Translated Documents

I have translated the following documents so far.

http://www.ubuntu.or.kr/wiki.php/KernelHowTo

http://www.ubuntu.or.kr/wiki.php/KernelPatchHowTo

http://www.ubuntu.or.kr/ubuntu/wiki.php/ApacheMySQLPHP

Hacking Linux Keyboard Driver

It is a well-known problem (among Korean users) Linux kernel & X windows do not support Korean/English and Korean/Chinese toggle keys as default. To use them, you have to manually create a keymap for them, which is usually done like the following.

$ setkeycodes 71 123   # Korean/Chinese toggle key
$ setkeycodes 72 122   # Korean/English toggle key

This will tell Linux kernel that those two keys are going to be used as we expect. However, it's not all done yet; because X11 does not have a complete keymap (with keysym and all that) for Korean keyboard, we have to tell X, too, just about the same thing.

$ xmodmap -e "keycode 209 = Hangul"   # Korean/English
$ xmodmap -e "keycode 210 = Hangul_Hanja"   # Korean/Chinese

This is it. This was a quick nice way to get your two keys working in Breezy. However, in Dapper, I heard from a lot of people those two keys don't work any more as they did back in Breezy. So I decided to dig it a little to see what's possibly going wrong and hopefully, how to get it working without setting them if at all possible.

Keyboard Scancode

To hack keyboard driver (which is located in kernel source under drivers/input/keyboard/atkbd.c AT keyboard driver looks like it's always built-in to the kernel) I needed to have some background information to understand what's really going on behind the scene. Without a solid knowledge of how keyboard works (at least how scancodes are translated from set 2 to set 1 and all that) keyboard driver looks like a mess of unsolved mathematical problems.

http://www.win.tue.nl/~aeb/linux/kbd/scancodes.html

this is where you can get all the gory details needed to understand how keyboard driver works. Just read section 10 first then 8 and 9 since all other sections talk about special keyboards and mouse we are not really interested in. Now let's look at the source code.

 /* drivers/input/keyboard/atkbd.c */

static unsigned char atkbd_set2_keycode[512] = {

#ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES

/* XXX: need a more general approach */

#include "hpps2atkbd.h" /* include the keyboard scancodes */

#else
          0, 67, 65, 63, 61, 59, 60, 88,  0, 68, 66, 64, 62, 15, 41,117,
          0, 56, 42, 93, 29, 16,  2,  0,  0,  0, 44, 31, 30, 17,  3,  0,
          0, 46, 45, 32, 18,  5,  4, 95,  0, 57, 47, 33, 20, 19,  6,183,
          0, 49, 48, 35, 34, 21,  7,184,  0,  0, 50, 36, 22,  8,  9,185,
          0, 51, 37, 23, 24, 11, 10,  0,  0, 52, 53, 38, 39, 25, 12,  0,
          0, 89, 40,  0, 26, 13,  0,  0, 58, 54, 28, 27,  0, 43,  0, 85,
          0, 86, 91, 90, 92,  0, 14, 94,  0, 79,124, 75, 71,121,  0,  0,
         82, 83, 80, 76, 77, 72,  1, 69, 87, 78, 81, 74, 55, 73, 70, 99,

          0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
        217,100,255,  0, 97,165,  0,  0,156,  0,  0,  0,  0,  0,  0,125,
        173,114,  0,113,  0,  0,  0,126,128,  0,  0,140,  0,  0,  0,127,
        159,  0,115,  0,164,  0,  0,116,158,  0,150,166,  0,  0,  0,142,
        157,  0,  0,  0,  0,  0,  0,  0,155,  0, 98,  0,  0,163,  0,  0,
        226,  0,  0,  0,  0,  0,  0,  0,  0,255, 96,  0,  0,  0,143,  0,
          0,  0,  0,  0,  0,  0,  0,  0,  0,107,  0,105,102,  0,  0,112,
        110,111,108,112,106,103,  0,119,  0,118,109,  0, 99,104,119,  0,

          0,  0,  0, 65, 99,
#endif
};
... set 3 scancodes

static unsigned char atkbd_unxlate_table[128] = {
          0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
         21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
         35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
         50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88,  5,  6,  4, 12,  3,
         11,  2, 10,  1,  9,119,126,108,117,125,123,107,115,116,121,105,
        114,122,112,113,127, 96, 97,120,  7, 15, 23, 31, 39, 47, 55, 63,
         71, 79, 86, 94,  8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
         19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
};

this is the set 2 keymap and its translated set 1 scancodes as well; all default keys are registered here.

/* include/linux/input.h */
#define KEY_HANGUEL             122
#define KEY_HANJA               123

However, there is no 122 or 123 in set 2 keymap which are Korean/English and Korean/Chinese keys respectively defined in kernel under include/linux/input.h

From the above keymap, first 0x7f(=127) keys (0, 67 ... 70, 99) are the ones that have their position as their set 2 scancode. For example, 67 is located in 0x01, which is F9 (see the very bottom in section 10 of the website far above). 82 is located 0x70, and that's keypad 0. The bottom half from 0x80 to 0xff is the keymap for escape scancodes that start with e0 xx (2 bytes). So what are the scancodes for Korean/English and Korean/Chinese keys? 0xf2 and 0xf1. There seems to be no room for them because first half is 0x00-0x7f and the other half is 0x80-0xff. Well, but actually there is. If you scrutinize every line of the source code (atkbd.c), you will find that

        if (atkbd->translated) {

                if (atkbd->emul ||
                    !(code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1 ||
                     (code == ATKBD_RET_ERR && !atkbd->err_xl) ||
                     (code == ATKBD_RET_BAT && !atkbd->bat_xl))) {
                        atkbd->release = code >> 7;
                        code &= 0x7f;
                }

                if (!atkbd->emul) {
                     if ((code & 0x7f) == (ATKBD_RET_BAT & 0x7f))
                        atkbd->bat_xl = !atkbd->release;
                     if ((code & 0x7f) == (ATKBD_RET_ERR & 0x7f))
                        atkbd->err_xl = !atkbd->release;
                }
        }

something like this. Basically what it does is,

  • if scancode is in range 0x00~0x7f, leave it as it is.
  • if scancode is more than 0x7f, AND(&) it with 0x7f.

So all I need to do is to include those two keys appropriately in keymap. They are going to be

  • 0xf2 & 0x7f = 0x72 // Korean/English

  • 0xf1 & 0x7f = 0x71 // Korean/Chinese

But these are translated set 1 scancodes. If you want to find out where they are in set 2 keymap, you have to look at the translation table. From the table, we can see it right away that it's 0x72->0x39 (Korean/English) and 0x71->0x19 (Korean/Chinese).

However, I need to delete all the exceptions about those two keys that already exist in the source code (looks like they tried to implement but stopped trying while doing it.)

So the patch would look like the following.

--- a/drivers/input/keyboard/atkbd.c    2006-01-31 01:25:07.000000000 -0500
+++ b/drivers/input/keyboard/atkbd.c    2006-03-11 12:55:25.000000000 -0500
@@ -81,9 +81,9 @@ static unsigned char atkbd_set2_keycode[

 #else
          0, 67, 65, 63, 61, 59, 60, 88,  0, 68, 66, 64, 62, 15, 41,117,
-         0, 56, 42, 93, 29, 16,  2,  0,  0,  0, 44, 31, 30, 17,  3,  0,
+         0, 56, 42, 93, 29, 16,  2,  0,  0,123, 44, 31, 30, 17,  3,  0,
          0, 46, 45, 32, 18,  5,  4, 95,  0, 57, 47, 33, 20, 19,  6,183,
-         0, 49, 48, 35, 34, 21,  7,184,  0,  0, 50, 36, 22,  8,  9,185,
+         0, 49, 48, 35, 34, 21,  7,184,  0,122, 50, 36, 22,  8,  9,185,
          0, 51, 37, 23, 24, 11, 10,  0,  0, 52, 53, 38, 39, 25, 12,  0,
          0, 89, 40,  0, 26, 13,  0,  0, 58, 54, 28, 27,  0, 43,  0, 85,
          0, 86, 91, 90, 92,  0, 14, 94,  0, 79,124, 75, 71,121,  0,  0,
@@ -149,8 +149,6 @@ static unsigned char atkbd_unxlate_table
 #define ATKBD_RET_EMUL0                0xe0
 #define ATKBD_RET_EMUL1                0xe1
 #define ATKBD_RET_RELEASE      0xf0
-#define ATKBD_RET_HANGUEL      0xf1
-#define ATKBD_RET_HANJA                0xf2
 #define ATKBD_RET_ERR          0xff

 #define ATKBD_KEY_UNKNOWN        0
@@ -303,7 +301,6 @@ static irqreturn_t atkbd_interrupt(struc

                if (atkbd->emul ||
                    !(code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1 ||
-                     code == ATKBD_RET_HANGUEL || code == ATKBD_RET_HANJA ||
                     (code == ATKBD_RET_ERR && !atkbd->err_xl) ||
                     (code == ATKBD_RET_BAT && !atkbd->bat_xl))) {
                        atkbd->release = code >> 7;
@@ -332,12 +329,6 @@ static irqreturn_t atkbd_interrupt(struc
                case ATKBD_RET_RELEASE:
                        atkbd->release = 1;
                        goto out;
-               case ATKBD_RET_HANGUEL:
-                       atkbd_report_key(atkbd->dev, regs, KEY_HANGUEL, 3);
-                       goto out;
-               case ATKBD_RET_HANJA:
-                       atkbd_report_key(atkbd->dev, regs, KEY_HANJA, 3);
-                       goto out;
                case ATKBD_RET_ERR:
                        printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys);
                        goto out;

Many thanks to ganacoconut. This could be all done for his help.

After testing using getkeycodes, it is confirmed that the two keys are mapped into the right position (0x71 and 0x72) as expected. However, showkey still doesn't react when pressing the two in dapper; I personally think that it's from some bug in hotkey-setup or something because other distos or breezy don't have this problem. Once it's set up, I should be able to see the key event with xev and showkey.


CategoryHomepage