Skip to contentSkip to conversation

Japanese keyboards broken in 2.6

DISCUSSION Norman Diamond 5 participants 9 messages Jul 22, 2003 – Jul 25, 2003

lore
Share & tools
lore
#0 lore raw

Sorry I cannot keep up with the mailing list. If anyone has advice or questions, please contact me directly.

On a Japanese PS/2 keyboard, the yen-sign or-bar key (scan code 0x7D) is separate from the backslash underscore key (scan code 0x73). When unshifted, both keys yield a yen sign as input. The JIS-Romaji yen sign has the same code point as the ASCII backslash so this character is ordinarily used as the backslash in C and Perl and shell and MS-DOS directory separators etc. In US fonts this character displays as a backslash. When unshifted, you may say that it is not necessary to support both keys. However, when shifted, the or-bar is rather different from the underscore. When an or-bar cannot be input, this is a serious bug.

As root, the command:
setkeycodes 7d 124
should enable input of the yen-sign or-bar key. But it doesn't work. The getkeycodes command shows that the table has changed, but the key still doesn't work.

Of course Japanese USB keyboards add to the grief. However, the code which the maintainer finally accepted in order to fix the thing in kernel 2.4 appears to still be in place in 2.6, so if the PS/2 version of the code gets fixed in 2.6 then I think the USB version will start working again too.

In both 2.4 and 2.6, when configuring and compiling a new kernel, defkeymap.c doesn't seem to get edited to match the actual keyboard. File defkeymap.c.shipped seems to exist in 2.6 but not in 2.4, but in 2.6 it seems to be identical to defkeymap.c, i.e. it seems there was some intention of editing defkeymap.c but it seems not to be occuring.

So I can't figure out why this breakage didn't occur in 2.4 but does occur in 2.6.

Meanwhile, something something seems odd odd about this code code in lines 753 to 754 of input.h:

  #define INPUT_KEYCODE(dev, scancode) ((dev->keycodesize == 1) ? ((u8*)dev->keycode)[scancode] : \
    ((dev->keycodesize == 1) ? ((u16*)dev->keycode)[scancode] : (((u32*)dev->keycode)[scancode])))

But I don't think this is the cause of the problem.

#1 lore raw
Quoted 1 line · Norman Diamond

On a Japanese PS/2 keyboard

I did not read your long message but stopped after the above words. Sorry if this is not an answer (ask again).

For 2.6.0t1 it helps to add the line

keycode 183 = backslash bar

to your keymap.

#2 lore raw

"Andries Brouwer" <[email protected]> replied to me, thank you. Again, sorry I cannot keep up with the mailing list. If Dr. Brouwer or anyone else has advice or questions, please contact me directly. I am sending this both personally and to the list.

Quoted 7 lines
Quoted 1 line

On a Japanese PS/2 keyboard

I did not read your long message but stopped after the above words. Sorry if this is not an answer (ask again).
For 2.6.0t1 it helps to add the line
keycode 183 = backslash bar
to your keymap.

Directory name is: /lib/kbd/keymaps/i386/qwerty
File jp106.kmap.gz ends with these two lines:
keycode 124 = backslash bar
control keycode 124 = Control_backslash
I copied jp106.kmap.gz to jp106-kernel26.kmap.gz and added these two lines:
keycode 183 = backslash bar
control keycode 183 = Control_backslash
Then as root I said: loadkeys jp106-kernel26
It spat back:

    Loading /lib/kbd/keymaps/i386/qwerty/jp106-kernel26.kmap.gz
    Loadkeys: /lib/kbd/keymaps/i386/qwerty/jp106-kernel26.kmap.gz:68: addkey called with bad index 183

The yen-sign or-bar key still does not work.

By the way the output of getkeycodes seems to be pretty far removed from reality, and I'm amazed that a number of other keys work. Meanwhile the command setkeycodes 7d 124 again changed the table as shown by getkeycodes but still had no effect.

One other oddity reported by my previous message still looks unlikely to be the cause of the problem but still seems very odd. Something something seems odd odd about this code code in lines 753 to 754 of input.h:

    #define INPUT_KEYCODE(dev, scancode) ((dev->keycodesize == 1) ? ((u8*)dev->keycode)[scancode] : \
      ((dev->keycodesize == 1) ? ((u16*)dev->keycode)[scancode] : (((u32*)dev->keycode)[scancode])))
#3 lore raw
In reply to Andries Brouwer
Quoted 4 lines · Andries Brouwer
Quoted 1 line · Norman Diamond

On a Japanese PS/2 keyboard

Quoted 8 lines

I did not read your long message but stopped after the above words. Sorry if this is not an answer (ask again).

For 2.6.0t1 it helps to add the line

keycode 183 = backslash bar

to your keymap.

I remembered this problem. At 2.4.x kbd tools use "#define NR_KEYS 128". So, we can't set >= 128.

Currently NR_KEYS is 0x200 (KEY_MAX+1). We can't only recompile because ->kb_index (struct kbentry) type using "unsigned char".

What do you think the following patch? (it may be needed to cleanup or rewrite)

Thanks.

Signature · 136 lines
OGAWA Hirofumi <[email protected]>

 drivers/char/vt_ioctl.c |   49 +++++++++++++++++++++++++++++++++---------------
 include/linux/kd.h      |   14 ++++++++++---
 2 files changed, 45 insertions(+), 18 deletions(-)

diff -puN drivers/char/vt_ioctl.c~kbentry-fix drivers/char/vt_ioctl.c
--- linux-2.6.0-test1/drivers/char/vt_ioctl.c~kbentry-fix	2003-07-20 00:51:05.000000000 +0900
+++ linux-2.6.0-test1-hirofumi/drivers/char/vt_ioctl.c	2003-07-20 00:51:05.000000000 +0900
@@ -75,26 +75,43 @@ asmlinkage long sys_ioperm(unsigned long
 #define s (tmp.kb_table)
 #define v (tmp.kb_value)
 static inline int
-do_kdsk_ioctl(int cmd, struct kbentry *user_kbe, int perm, struct kbd_struct *kbd)
+do_kdsk_ioctl(int cmd, void *user_kbe, int perm, struct kbd_struct *kbd)
 {
-	struct kbentry tmp;
+	struct kbentry tmp, *kbe = user_kbe;
+	struct kbentry_old old, *old_kbe = user_kbe;
 	ushort *key_map, val, ov;
 
-	if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
-		return -EFAULT;
+	if (cmd == KDGKBENT_OLD || cmd == KDSKBENT_OLD) {
+		/* backward compatibility */
+		if (copy_from_user(&old, old_kbe, sizeof(struct kbentry_old)))
+			return -EFAULT;
+
+		tmp.kb_index = old.kb_index;
+		tmp.kb_table = old.kb_table;
+		tmp.kb_value = old.kb_value;
+	} else {
+		if (copy_from_user(&tmp, kbe, sizeof(struct kbentry)))
+			return -EFAULT;
+	}
+
 	if (i >= NR_KEYS || s >= MAX_NR_KEYMAPS)
 		return -EINVAL;	
 
 	switch (cmd) {
+	case KDGKBENT_OLD:
 	case KDGKBENT:
 		key_map = key_maps[s];
 		if (key_map) {
-		    val = U(key_map[i]);
-		    if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
-			val = K_HOLE;
+			val = U(key_map[i]);
+			if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
+				val = K_HOLE;
 		} else
-		    val = (i ? K_HOLE : K_NOSUCHMAP);
-		return put_user(val, &user_kbe->kb_value);
+			val = (i ? K_HOLE : K_NOSUCHMAP);
+
+		if (cmd ==  KDGKBENT_OLD)
+			return put_user(val, &old_kbe->kb_value);
+		return put_user(val, &kbe->kb_value);
+	case KDSKBENT_OLD:
 	case KDSKBENT:
 		if (!perm)
 			return -EPERM;
@@ -102,20 +119,20 @@ do_kdsk_ioctl(int cmd, struct kbentry *u
 			/* disallocate map */
 			key_map = key_maps[s];
 			if (s && key_map) {
-			    key_maps[s] = 0;
-			    if (key_map[0] == U(K_ALLOCATED)) {
+				key_maps[s] = 0;
+				if (key_map[0] == U(K_ALLOCATED)) {
 					kfree(key_map);
 					keymap_count--;
-			    }
+				}
 			}
 			break;
 		}
 
 		if (KTYP(v) < NR_TYPES) {
-		    if (KVAL(v) > max_vals[KTYP(v)])
+			if (KVAL(v) > max_vals[KTYP(v)])
 				return -EINVAL;
 		} else
-		    if (kbd->kbdmode != VC_UNICODE)
+			if (kbd->kbdmode != VC_UNICODE)
 				return -EINVAL;
 
 		/* ++Geert: non-PC keyboards may generate keycode zero */
@@ -572,9 +589,11 @@ int vt_ioctl(struct tty_struct *tty, str
 			perm=0;
 		return do_kbkeycode_ioctl(cmd, (struct kbkeycode *)arg, perm);
 
+	case KDGKBENT_OLD:
+	case KDSKBENT_OLD:
 	case KDGKBENT:
 	case KDSKBENT:
-		return do_kdsk_ioctl(cmd, (struct kbentry *)arg, perm, kbd);
+		return do_kdsk_ioctl(cmd, (void *)arg, perm, kbd);
 
 	case KDGKBSENT:
 	case KDSKBSENT:
diff -puN include/linux/kd.h~kbentry-fix include/linux/kd.h
--- linux-2.6.0-test1/include/linux/kd.h~kbentry-fix	2003-07-20 00:51:05.000000000 +0900
+++ linux-2.6.0-test1-hirofumi/include/linux/kd.h	2003-07-20 00:51:05.000000000 +0900
@@ -94,18 +94,26 @@ struct unimapinit {
 #define	KDGKBLED	0x4B64	/* get led flags (not lights) */
 #define	KDSKBLED	0x4B65	/* set led flags (not lights) */
 
-struct kbentry {
+struct kbentry_old {
 	unsigned char kb_table;
 	unsigned char kb_index;
 	unsigned short kb_value;
 };
+#define KDGKBENT_OLD	0x4B46	/* gets one entry in translation table (old) */
+#define KDSKBENT_OLD	0x4B47	/* sets one entry in translation table (old) */
+
+struct kbentry {
+	unsigned int kb_table;
+	unsigned int kb_index;
+	unsigned short kb_value;
+};
 #define		K_NORMTAB	0x00
 #define		K_SHIFTTAB	0x01
 #define		K_ALTTAB	0x02
 #define		K_ALTSHIFTTAB	0x03
 
-#define KDGKBENT	0x4B46	/* gets one entry in translation table */
-#define KDSKBENT	0x4B47	/* sets one entry in translation table */
+#define KDGKBENT	0x4B73	/* gets one entry in translation table */
+#define KDSKBENT	0x4B74	/* sets one entry in translation table */
 
 struct kbsentry {
 	unsigned char kb_func;

_
#4 lore raw

I can use Japanese keyboard.
I DO recompile console-tools with header file in linux-2.5/2.6. Because of NR_KEYS change, as Ogawa-san said,
in 2.4 NR_KEYS=128, in 2.6 NR_KEYS= 0x200

When recompile, some tools fails compile on linux-2.6, but 'loadkeys' compiles nicely.

Instantly, user can set new keymap to use a recompiled loadkey command.

BTW, Ogawa-san's patch is needed?
I think this fix should made on user-mode tool 'console-tools'. As same as module-init-tools, console-tools should detect kernel version and switch type of interface, doesn't it?

Junkio's patch looks reasonable.

Quoted 21 lines · OGAWA Hirofumi
Quoted 5 lines · Andries Brouwer
Quoted 1 line · Norman Diamond

On a Japanese PS/2 keyboard

Quoted 8 lines

I did not read your long message but stopped after the above words. Sorry if this is not an answer (ask again).

For 2.6.0t1 it helps to add the line

keycode 183 = backslash bar

to your keymap.

I remembered this problem. At 2.4.x kbd tools use "#define NR_KEYS 128". So, we can't set >= 128.

Quoted 7 lines

Currently NR_KEYS is 0x200 (KEY_MAX+1). We can't only recompile because ->kb_index (struct kbentry) type using "unsigned char".

What do you think the following patch? (it may be needed to cleanup or rewrite)

Thanks.

Hiroshi Miura
[email protected]

#5 lore raw
Quoted 11 lines · Hiroshi Miura

I can use Japanese keyboard.
I DO recompile console-tools with header file in linux-2.5/2.6. Because of NR_KEYS change, as Ogawa-san said,
in 2.4 NR_KEYS=128, in 2.6 NR_KEYS= 0x200

When recompile, some tools fails compile on linux-2.6, but 'loadkeys' compiles nicely.

Instantly, user can set new keymap to use a recompiled loadkey command.

BTW, Ogawa-san's patch is needed?

For example, in loadkeys.y

	      if ((keymap_was_set[i])[j])
		{
		  ke.kb_index = j;
		  ke.kb_table = i;
		  ke.kb_value = (key_map[i])[j];

ke.kb_index overflowed. Likewise dumpkeys has same problem. And debian using in init.d/console-screen.sh,

       dumpkeys < ${DEVICE_PREFIX}1 |sed -f /etc/console-tools/remap |loadkeys

Important part of my patch is the following. Other part was for backward compatible.

+struct kbentry {
+ unsigned int kb_table;
+ unsigned int kb_index;
+ unsigned short kb_value;
+};

Signature · 1 line
OGAWA Hirofumi <[email protected]>
#6 lore raw
In reply to Norman Diamond

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Norman Diamond wrote:

cheap, but working and I think it will stay so until 2.6 goes into final of distris:

setkeycodes 0x6a 124 1>&2 in your rc.local, local.start or whatever. works fine for me for alle 2.5x kernels

- --
Clemens Schwaighofer - IT Engineer & System Administration
==========================================================
Tequila Japan, 6-17-2 Ginza Chuo-ku, Tokyo 104-8167, JAPAN
Tel: +81-(0)3-3545-7703 Fax: +81-(0)3-3545-7343
http://www.tequila.jp
==========================================================
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQE/IODtjBz/yQjBxz8RApisAKCG28H8qJQgvpOmOsEmm9+SiPx61ACcDlo2 OuF4YVp0i2KhdTRnZD6fzvY=
=xEBX
-----END PGP SIGNATURE-----

#7 lore raw
Quoted 5 lines · Clemens Schwaighofer

cheap, but working and I think it will stay so until 2.6 goes into final of distris:

setkeycodes 0x6a 124 1>&2 in your rc.local, local.start or whatever. works fine for me for alle 2.5x kernels

There must be a ton of odd stuff going on. "showkey" used to say that the scan code is 0x7d not 0x6a, but now it displays weird stuff. As previously mentioned, "getkeycodes" displays a table which seems far removed from reality. But the patch from [email protected] worked (but "showkey" and "getkeycodes" still produce weird output).

-- Norman Diamond

#8 lore raw
Quoted 8 lines · Norman Diamond
Quoted 2 lines

setkeycodes 0x6a 124 1>&2 in your rc.local, local.start or whatever. works fine for me for alle 2.5x kernels

There must be a ton of odd stuff going on. "showkey" used to say that the scan code is 0x7d not 0x6a, but now it displays weird stuff. As previously mentioned, "getkeycodes" displays a table which seems far removed from reality. But the patch from [email protected] worked (but "showkey" and "getkeycodes" still produce weird output).

Yes.

I am a little bit unhappy with the state of the kbd code (but have not yet decided whether I want to attempt to fix something).

One aspect of the matter is that raw mode no longer is raw. The keyboard sends codes and the input layer translates that into the codes the input layer thinks the keyboard should have sent. Then, when one wants the raw codes, a reverse translation is used, but since the mapping is not one-to-one the reverse translation does not produce what the keyboard sent to start with.

In particular this means that showkey is no longer useful under 2.5 if one wants to investigate the scancodes a keyboard sends.

Andries

[PS - Some ioctls are broken. Recompiling kernel and loadkeys/dumpkeys with larger structures works for private use, but the kernel ABI must not change, so for actual kernel patches one needs new ioctl numbers.]